Disposable Memories

This post is going to be a very technical look at GATE's memory consumption. This will involve discussion of Java's class loading mechanism and garbage collection. If none of that interests you, or if that first sentence didn't make sense, then can I make a friendly suggestion that you stop reading about now!

Before we dive in you need a little background on how memory is used in Java. This short description isn't entirely accurate (a full and accurate description would probably require an entire book) but will suffice for the purposes of this post.

There are, broadly speaking, two types of information that Java keeps in memory when running an application; the definitions of each class that has been used and the information about each instance of a particular class. The instance level information is created when you use the new keyword and is made available for garbage collection when there is no longer anyway of accessing the specific instance. The class definitions on the other hand are only ever released when the classloader instance, which loaded them into memory, is garbage collected. If the Java application doesn't do any custom class loading then all class definitions will be loaded into the system classloader which is never garbage collected. Class definitions are stored in the PermGen area of the Java heap which is why, if you load too many class definitions, you will eventually get the message:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
The common way of avoiding this problem is simply to increase the amount of available memory (either the total heap size or just the PermGen area). While this often makes the problem go away, it actually just increases the time until the problem will occur.

GATE itself contains a lot of classes (over 2000 just in the main source tree) but also supports dynamically loading plugins and compiling new classes from JAPE grammars. This all means that there is no maximum number of classes that might be loaded and hence no way of ensuring that the PermGen is always big enough. Fortunately GATE doesn't dynamically load classes into the system classloader but into a custom classloader as you can see from this diagram. Unfortunately this classloader is a singleton instance which is never released.

One of the side effects of this is that if you re-initialize (or close and re-create) a JAPE transducer a new copy of the class definitions are created and added to the PermGen area. This is one of the reasons that when using GATE as part of a web service we suggest using a pool of pipelines rather than creating a new pipeline for each request. Not only does this reduce response times (assuming an adequate sized pool) but also prevents exhaustion of the PermGen area. To show just how quickly this can become a problem I wrote the following short piece of code.
Gate.runInSandbox(true);
Gate.init();

Gate.getCreoleRegister().registerDirectories(
  (new File("/home/mark/gate-top/externals/gate/plugins/ANNIE/"))
    .toURI().toURL());

FeatureMap params = Factory.newFeatureMap();
Transducer jape = (Transducer)Factory.createResource(
  "gate.creole.ANNIETransducer", params);

long count = 1;
while (true) {
  System.out.println(count);
  jape.reInit();
  ++count;
}
This simply initializes GATE, creates a single instance of the ANNIE NE Transducer and then repeatedly re-initializes it. On my machine Java defaults to using 82MB for the PermGen and this was exhausted after loading the transducer just 104 times. I was monitoring the performance using VisualVM and you can see from the following screen shot how the memory was quickly exhausted.


There are a number of other issues with using a singleton classloader but they boil down to the fact that once a class has been defined it can never be forgotten or redefined. The practical aspects of this are that unloading a plugin doesn't actually result in the class definitions being forgotten, so you can't unload, recompile, reload a plugin. If you want to make a change you have to close and restart GATE. Another problem is that if two plugins try and load different versions of the same class only the first version will be used. This is particularly problematic when dealing with complex plugins which may use multiple third-party libraries. With the plugins in the main distribution we try and keep to just one version of each library but clearly we have no control over third-party plugins.

These issues have annoyed me for a while, but I haven't had either the time (this has all been done in my own time) or in some cases the technical knowledge to do anything about it. A few weeks ago, having read a book on Java Performance, a couple of pieces of the puzzle started to fall into place and I realized that I could probably have a good crack at a new classloader architecture that would solve all of these problems. You can see the architecture I've adopted in the diagram to the right. There are two things this diagram doesn't show. Firstly there can be any number of plugin or JAPE classloaders, and secondly those classloaders are what is known as parent last. The reason for having any number of plugin or JAPE classloaders (they are actually the same class I'm just splitting them up on the diagram to show that it handles both plugin loading and compiling JAPE grammars) should be obvious, as it allows us to throw one away when it is no longer required (i.e. we don't want to have to unload all plugins just to unload one). The idea of parent last classloading, however, requires a more detailed explanation.

Traditionally classloaders in Java take a parent first approach. This means that when they are asked to load a class they start by asking their parent classloader (follow the arrows upwards) to load the class, which in turn asks it's parent etc. It's only if this fails that a classloader will itself try and load a class. Changing to using parent last means that two classloaders can now have different copies of the same class defined within them, and hence we can support different versions of the same third party library appearing within different plugins. This works because when a class in a plugin tries to load a class it looks within it's own plugin before looking in either the main GATE classloader or the classloaders associated with other plugins or JAPE grammars. This mechanism also allows classes in different plugins to refer to one another (i.e. a JAPE grammar can refer to classes loaded via a plugin).

To ensure that classloaders can be released and garbage collected properly, I've also made a change to the way plugins are unloaded. Currently in GATE unloading a plugin simply removes the definition of the resources it contains from the CREOLE register, but it doesn't unloaded any instances of the resources that are currently in use. This does tend to lead to some funny behaviour (often weird AWT error messages) and to ensure a thorough cleanup I've updated this code so that it does now unload any instances of resources that depend on the plugin before unloading the plugin itself.

It's taken quite a bit of time hunting through heap dumps using VisualVM but I'm now confident that this new approach works well and that classloaders, and hence classes, can be thrown away when they are no longer needed. As an example, we can use this modified version of GATE along with the sample code I showed before (to re-initialize a JAPE grammar over and over again). This time I let it run for over 1000 iterations (almost 10 minutes) before I stopped it as there was no sign of it running out of memory. A quick look at VisualVM explains why.


You can clearly see that every time the PermGen is almost exhausted garbage collection kicks in freeing some of the previously loaded and discarded class definitions.

This work has all been done in this separate SVN branch so as not to disrupt the main source tree. This means that to try this modified, memory friendly version of GATE you will need to check out the branch and compile it yourself. Mind you if you have read all the way to here then I'm going to guess that won't be a problem. My hope is that this will eventually be merged back into the trunk but I'd prefer to wait until this branch has been tested by a number of other people and not just me. Also there are currently 9 tests that fail when using this branch, although I've looked at the failing code and in every case it's actually the test that is at fault. Essentially the tests load each plugin twice, once into the system classloader (as the classes are on the main Java classpath) and once into the GATE classloader (when the plugin is loaded via the API). Because of the change to parent last classloading, this means that two different definitions of the same class can end up being used which results in apparently nonsensical error messages such as: Error converting class gate.chineseSeg.RunMode to class gate.chineseSeg.RunMode. This situation never happens during normal use of GATE Developer, and can be fixed by altering the creole.xml files used to define the plugins. In other words the failed tests shouldn't stop you trying this branch, although I also wouldn't suggest using this branch in a production environment until it has seen further testing.

So on that note, please try the branch if you have been concerned about memory consumption or had problems with clashing library versions and let me know if you find any problems, or if you have any further suggestions for improvements.

Disable Dynamic Views: An Update

Just over a month ago I blogged about a small GreaseMonkey script that you could install so that you didn't have to see any of Blogger's new dynamic view templates ever again. Well it turns out that there was a small bug in that version of the script.

If you remember, the script essentially works by tricking Blogger into thinking you are viewing the blog without JavaScript by adding v=0 to the query string of each link within the blog. Well it turns out that there was one case where this wasn't working properly; the link that jumps you to the comments within the post specific page. The problem was that these links point not only to a page but a specific anchor by adding #comments to the URL. Unfortunately my script was adding the query string after the anchor reference (i.e. post-page.html#comments?v=0) when it should add it to the page location (i.e. post-page.html?v=0#comments). I've updated the script to v1.1 which contains a fix for this. In theory if you have already installed the script your browser should eventually pick up the new version. But if you haven't yet installed the script or just want to make sure you have the latest version then you can install/upgrade by simply clicking this link.

One Byte At A Time

Whilst working on Postvorta one of the things I've tried to do is to make the code as efficient as possible in order that search results are returned as quickly as possible. Mostly this has involved caching data where possible as well as using efficient data structures and algorithms. Of course with Postvorta being a web application part of the time taken to show search results is dependent on the amount of data that is actually returned to a browser including; HTML pages, JavaScript files, style sheets, and images. I am already using JAWR to minify and compress JavaScript and CSS files which makes a real difference to the amount of data that you have to download each time you search but in this post I want to talk about a small issue I uncovered when trying to trim just a few bytes from the HTML pages.

I've recently been reading a book on Java Performance by Charlie Hunt and Binu John. While it covers quite a few aspects of performance that I was already aware of there is also quite a lot of information that is new to me. One chapter is devoted to performance tuning for web applications and as well as mentioning minifying and compressing static files (JavaScript, CSS etc.) it devotes a section to considering whitespace in the dynamically generated pages.

When you save a file of text, whitespace characters (spaces, tabs, new lines) all take up the same amount of disk space as any other character, i.e. 1 byte (I know this isn't entirely accurate but I don't want to get into a long discussion of line endings and encoding formats so this assumption will suffice for what follows). This is acceptable if you want to use whitespace for formatting but HTML specifically doesn't use whitespace in this way. Any sequence of whitespace in a HTML file is converted by the browser into a single space character, so it is wasteful to transmit extra whitespace than is needed for the page to be understood and rendered. Of course most people use whitespace not just for formatting but to make the HTML code easier to understand and debug. There are filters that I could add to Postvorta that would strip out all extraneous whitespace before transmitting the results back to the browser but a) this would make debugging the page tricky and b) each filter I add has it's own performance overhead. My plan, therefore, has been to try and re-work the code where possible to eliminate some whitespace while leaving the code readable and to not add an extra filter. In most cases this is easy, but there is one area where eliminating whitespace is more difficult.

When switching between HTML and Java in a JSP page whitespace is often inserted to ensure that the resulting page can be properly interpreted. Unfortunately in almost every case this whitespace is superfluous and can be removed. Fortunately there is an easy way of removing the blank lines from the output that these whitespace characters introduce. The easiest way is to added the following page directive to a JSP page:
<%@ page trimDirectiveWhitespaces="true" %>
While Postvorta currently only contains two pages (the results page and the advanced syntax page) this is easy to do, but in a more complex application there may be tens or hundreds of pages at which point this approach becomes less appealing. You can, however, enable the same feature for every page by editing the applications web.xml to add the following:
<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <trim-directive-whitespaces>true</trim-directive-whitespaces>
  </jsp-property-group>
</jsp-config>
I tried both approaches and they do indeed produce the same output, which in my test case brought the page size down to 13,238 bytes from the original 13,300, saving me a total of 62 bytes! Now 62 bytes might not be very much but this is per page view and so can quickly mount up. Looking at the differences between the old and new pages I noticed that there were still quite a large number of blank lines in the head section of the HTML file that I thought should have been removed. It turns out that the problem is related to how I style the pages but is easy to solve.

I use SiteMesh (I'm using v2.4.1) to style all the pages within Postvorta. This allows me to define the main layout of the pages once and then use this to display all pages. For those of you who use Blogger, you can consider a SiteMesh layout to be equivalent to your blog template. The layout is applied via a SiteMesh specific filter and it appears, that when using the web.xml approach to enable the trimming of whitespace, the layout is applied after the whitespace has been trimmed. This means that whitespace within the main body of the page is removed but not within the head section. The trick is to use the page directive approach within the SiteMesh layout. This has the advantage of being applied to the entire page, only needs to be specified once, and in my test case saves another 15 bytes which brings the total page size down by 77 bytes to 13,223 bytes.

The total savings are small, but if Postvorta ever becomes really popular, shaving a few bytes here and there might well make a noticeable different to performance.

Postvorta Mk II: Faster And With More Features!

The Spitfire Mk II was essentially the same as the original model, just with an upgraded Merlin engine. Today I've done something similar to Postvorta my "intelligent blog search engine".

Those of you who read the initial blog posting I did on Postvorta may remember that underneath it all Postvorta relies on GATE Mímir for indexing and search. Yesterday we (i.e. the GATE group at the University of Sheffield) released new versions of most of the software we develop, including Mímir 4. While I'm not heavily involved with the development of Mímir I do use it quite substantially at work and I've been slowly updating all the systems I'm involved with, including Postvorta, to use this new version. Not only is this new version of Mímir faster it also takes a slightly different approach in the way it handles search results which is more suited to Postvorta than the old approach. I've also added some extra code to Postvorta to cache more information locally. Together these changes have resulted in Postvorta returning results an awful lot faster than before. You will also notice that switching between pages of results is significantly faster than it was before. Of course all these changes are "under the hood" so just like with the Spitfire Mk II, Postvorta should look roughly the same but work much faster. There is one new feature though that is worth talking about: result visualization.

When you search a blog using Postvorta it returns a list of relevant documents ordered from most recent to oldest. Combined with the different ways you can search a blog this ordering is usually the most useful. In some cases, however, especially when a search returns lots of results, it can be difficult to hunt through the posts to find the one you are interested in. To help with this I've started to think about different ways of visualizing the results. Whilst I've had a number of ideas the first to make it as far as a working, stable implementation is a date distribution graph.

A date distribution graph (in this context anyway) is simply a vertical bar chart showing how the results are distributed by month. The graph, just like the results, works backwards so the most recent month is on the left. The bars of the graph can be clicked on to go to the result page containing the first result for that month. Essentially it allows you to jump to posts from a given month directly without having to page through lots of irrelevant results. Currently, depending upon the number of search results, the graph can take a moment or two to be produced, but this is done asynchronously to the normal page loading to allow you to see the actual results as soon as possible.

As always I'd be interested in knowing what you think of this new feature. You can play with it either by searching this blog (the search box is just over on the right), or your own blog.

Putting A Spanner In The Works

I'm really not a luddite, I have no problem with new technical inventions that make life easier or cheaper. What I object to is using technology simply for the sake of it, when the result is inferior to what there was before. Unfortunately, in my view, a lot of recent "innovations" on blogger seem to fall into this second category. Today my object of hate is dynamic views.

Dynamic views are a nice way of showcasing the new web standards, HTML5 and CSS3, but personally I think they are horrible. In my experience they are slow to load (and believe me my machine ranks above average on CPU and memory), and they remove any sense of individuality from the blogs on which they are used. Whilst the presentation shouldn't be as important as the content, I think we all judge books by their covers and blogs by their layout. Unfortunately once a blog owner has decided to use dynamic layouts us as readers have no option to view the original template unless we turn off JavaScript. Unfortunately, if you turn off JavaScript you will be able to see the main page of the blog using the normal template but you won't be able to look at older posts and none of the widgets will work. Fortunately the rest of this post introduces a solution that means if you hate dynamic views as much as I do you can banish them for good!

When you turn JavaScript off Blogger doesn't gracefully show you the old template for a dynamic blog. What it does is give you a link to the front page of the blog with ?v=0 appended to the end. It turns out that adding v=0 to the query string of the URL for any page within a blog causes it to be displayed using the old template. Unfortunately Blogger doesn't re-write the links in a page when you add v=0 to the URL, so they all point back to the dynamic view. And even if you have JavaScript turned off they just send you back to the homepage not the actual page you wanted to look at. This is a horrid mess, but it does give us a way of fixing things.

My solution is a GreaseMonkey script that runs as the page loads, redirects you away from the dynamic view and back to the original template pages and re-writes all the out going links, where necessary, to include the v=0 parameter so that they all just work. If you use Firefox then you will need to install the GreaseMonkey addon before you can use the script, if you use Google Chrome then support for GreaseMonkey scripts is built in. Once you are ready you can install my script by clicking this link. Currently it will only be applied to blogspot hosted blogs so unfortunately you might still see the odd dynamic view blog (Blogger Buzz for example) but hopefully there shouldn't be too many.

Let me know what you think and if you have any suggestions for improvements, and certainly links to any blogspot hosted blogs where you still see the dynamic views.

Threaded Comments

It would appear that a few days ago Blogger introduced another new feature to our blogs: threaded comments.

Now while I actually quite like the idea (much like the lightbox fiasco) it has been introduced as the default if you use an embedded comment form and publish full feeds. The other problem (and the one that affected this blog) is that the HTML elements and CSS styles used to display the comments have changed, which (depending on your template) might mean that they look different or even wrong. So while I quite like the idea here are two little tips that might make life easier.

Firstly, let's assume that while they display correctly you just don't like threaded comments and want to turn them off. This is actually easily achievable with following piece of CSS.
.comment-actions {
   display: none;
}
You need to add this to your blog template, either by editing the HTML of your template and adding it anywhere inside a style element, or by going to advanced in the Template Designer where you can add arbitrary CSS. Essentially this just removes the reply link, so to leave a comment everyone is forced to use the main comment form at the bottom of the post. This has, however, the unfortunate side effect of also removing the default delete comment link. Personally I don't think that's too much of an issue as it is easy to moderate comments through the dashboard. If I have the time I'll try and figure out how to reinstate the delete link and then I'll publish another post explaining how.

On this blog I actually don't mind the comments being threaded, but I do mind them not displaying properly, which is exactly what was happening. When I customized the template I use for this blog I added some CSS styles to control how blockquotes appear. I wasn't intending to use them for structure within the template so I styled them to look like an actual quote. You can see the styles in action in this post where I quote part of an e-mail. The problem is that blogger are now using blockquote to layout comments. This meant that each comment was styled in the same way as that e-mail quote, and because the surrounding context was different the comments were actually overlapping one another slightly. All in all it looked pretty horrible. Fortunately there is an easy fix. Because I know that I only want to use my styles within the body of a post I can limit the CSS to only applying within that section of the page by prefixing the style with .post-body as the post is always contained within a div with the class post-body. So my three blockquote styles now look like.
.post-body blockquote {
   font-style: italic;
   width: 500px;
   margin: 0 auto;
   text-align: justify;
}

.post-body blockquote:before {
   display:block;
   content: open-quote;
   font-size: 300%;
   height: 0;
   margin-left: -0.8em;
}

.post-body blockquote:after {
   display: block;
   font-size: 300%;
   content: close-quote;
   margin-top: -0.8em;
   margin-left: 500px;
}
Of course depending on the template you use you may have different problems that show up because of the new comment system so you may need to experiment a little to find exactly what CSS tricks you need to apply to put things back the way they were before Blogger introduced the new feature/bug (delete as you see fit).

I Do Exist, Honest!

After a stressful day I appear to exist once again. If you tried to visit my blog yesterday you would have seen that it had been removed. Worse than that Google had decided to suspended my entire account. That meant I lost access not only to all my blogs, but photos in picasa, my calendars, my gmail account, and my Google+ profile. It was almost as if I no longer existed (online). I filled in the contact us form to request my account back and then almost a day later I got this e-mail from Google:

We apologize for any inconvenience you may have experienced. The issue you described should now be resolved.
I don't think I've ever been quite so relieved. While the whole experience was a bit of a nightmare it did get me thinking about how I could keep backups of all my Google data in case something similar happened again in the future. After a little bit of hunting around the web (via Google of course) I came across the Data Liberation Front.

The Data Liberation Front is a Google engineering team who are trying to make it easy to liberate your data from Google products. This is useful for either moving your data to a competing service or for simply backing it up locally.

They have step by step instructions on exporting your data from most of Google's products, but they are also developing Google Takeout. Google Takeout brings together a number of the export tools into a simple interface allowing you to select which data you want to download. It then collects the data together into a single zip file that you can easily download and archive. Currently it supports: +1’d sites, Buzz, Contacts and Circles, Picasa Web Albums, Profile, and Google+ Stream. As far as I can tell the aim is to add more products to this list and I'd certainly appreciate Blogger being included.

So if you don't have a recent backup of your Google hosted data maybe now is the time to do something about it.