Optimizing Spring Application Startup Time

The application I’m currently working on is built around Spring. A couple of weeks ago, as I waited for it to start up for the 27th time that day, I began wondering if there was any way to get it to start faster. Coincidentally, our whole development team had just received upgraded laptops, so the fact that numbers are stagnating in the “Megahertz” department (but not in the “CPU cores” department) had been recently emphasized.

Further, I had just read a series of articles by Cédric Beust regarding recent improvements to the TestNG threading engine. In short, TestNG allows you to run tests on multiple threads in order to shorten the test suite run time. However, when you start creating tests with dependencies on other tests, TestNG punts and runs all of these groups of dependent tests serially, on a single thread. Cédric wanted to remove this limitation, and approached the enhancement as a topological sort problem, viewing the tests as nodes in a directed acyclic graph.

Most of the startup time in Spring-centric applications involves the initialization of singleton beans. It wasn’t too much of a mental leap to wonder if the same graph/sort approach could be applied to the application startup optimization question — with the Spring beans acting as the nodes in the graph, instead of the tests.

It turns out to be (sort of) possible, and (sort of) worth the time. I’ve posted the details, including the source, here. Feel free to check it out and make suggestions. The Spring framework does contain a very coarse lock that required a pretty horrible hack in order to get any performance gains out of the experiment, but once this is worked out I don’t see why an implementation of this approach couldn’t make it into real applications. Again, see the project page for more details.

On a side note, this is the first time that I’ve used GitHub to host any code, and I have to say that I really like the fact that the README file serves the dual purposes of local project documentation and homepage markup!

JBoss 5 + Spring 2.5.6 = BOOM!

If you tell Spring 2.5.6 to scan the classpath for application context XML files and you’re deploying to JBoss 5, you may run into this bug; something to do with JBoss’ new Virtual File System (VFS) and its non-standard URLs. It looks like this issue was caught in time to be fixed for 2.5.6, but I guess the SpringSource guys didn’t have time to test it before releasing — the fix doesn’t really work.

It appears there will be a 2.5.7 release within the next couple of months (see slide 14), but it’s probably going to be the first of the commercial-only Spring releases. However, Spring 3.0 is also due within the next couple of months (see slide 5); let’s hope for a fix then. Otherwise, they may have to take JBoss off of the deploy graph on slide 4 ;-)

SpringSource Reworks Maintenance Policy

A couple of weeks ago SpringSource modified their maintenance policy. The change was a significant move in that it stripped non-paying users of certain perks (rights?), to the point of triggering arguments regarding what, exactly, constitutes an “open source” project.

In an attempt to find a balance between their open source roots and their commercial obligations, SpringSource made a mistake. They’ve now admitted it, and they’ve acted upon that knowledge. Kudos to them.

Back to work.

SpringSource Killing the Golden Goose?

As per this post on TSS, SpringSource have announced a new maintenance policy:

Customers who are using SpringSource Enterprise, available under a subscription, will receive maintenance releases for three years from the general availability of a major new version. These customers receive ongoing, rapid patches as well as regular maintenance releases to address bugs, security vulnerabilities and usability issues, making SpringSource Enterprise the best option for production systems.

After a new major version of Spring is released, community maintenance updates will be issued for three months to address initial stability issues. Subsequent maintenance releases will be available to SpringSource Enterprise customers. Bug fixes will be folded into the open source development trunk and will be made available in the next major community release of the software.

Now, there are only two ways I can read this:

  1. After the initial three-month window following a major release, bug fixes will not be available to non-paying customers until the next major release.
  2. After the initial three-month window following a major release, bug fixes will be available to non-paying customers only via public source control — not via real, numbered releases.

If we take the Spring 2.5.x series of releases as an example, we have the following time line:

Spring 2.5.0: 2007-11-19
Spring 2.5.1: 2008-01-09
Spring 2.5.2: 2008-02-29
Spring 2.5.3: 2008-04-06
Spring 2.5.4: 2008-04-28
Spring 2.5.5: 2008-06-23

Applying the three-month rule to these releases, we can see that the community around this open source project would only have access to Spring 2.5.0, 2.5.1 and 2.5.2 (if we’re generous and round up).

I’m not sure whether or not the community would have access via public source control to the bugfixes included in the subsequent releases prior to the next major release, but as far as I can tell the best-case scenario is that we would have to build the subsequent releases ourselves, rather than just download the JARs directly.

Additionally, this policy takes effect immediately. If you’re not paying SpringSource, you may not get access to the upcoming 2.5.6 release…

Somebody tell me I’m misreading this.

UPDATE: Here.

Embedding Jetty 6 in Spring

There’s not much info out there on embedding a Jetty server in Spring, and much of what does exist is for Jetty 5 (not Jetty 6) or uses helper classes that nobody wants to write. However, there is a decent example hidden in the Jetty Subversion repository (which requires an exploded WAR directory structure), and the Jetty documentation is pretty nice. The API docs are useful, as well.

I had two goals: embed Jetty 6 (not 5), and do so without having to rearrange my directories into an exploded WAR structure. After a bit of tinkering, this is the file I ended up with. It contains 5 servlets and their mappings, just so that you can get a feel for the file, but you can certainly use it with any number of servlets.

Note that I had to change the file extension from .xml to .txt in order to appease my blogging software… Note also that this setup does not require the exploded WAR directory structure. The parts you’ll probably want to customize are the servlets list, the servletMappings list, the resourceBase property, and possibly the contextPath property.

Hibernate, Spring and ASM

As far as I can tell, there isn’t much love lost between the folks at JBoss (including the Hibernate team) and the guys at Interface21 (the people behind Spring). Of course, it’s hard to gauge these things based on third-party reports and miscellaneous blog posts, but I think I’ve found confirmation — and in the process, discovered Gavin’s secret weapon against the Spring onslaught.

The secret weapon is ASM. No, not the American School of Madrid (where yours truly spent three years of his high school career). Rather, the Java bytecode manipulation library which allows Hibernate (and Spring) to attain that level of awesomeness we’ve all come to love. So both projects are cool — the problem is that they’re incompatibly cool. Spring uses ASM 2.2.3, which is the latest version of the stable branch. Hibernate, on the other hand, uses ASM 1.5.3, which is the latest version of the, ah, antediluvian branch.

The Spring forums are full of people dealing with this issue, which presents itself in the form of NoSuchMethodErrors, AbstractMethodErrors and other unintuitive exceptions. If you’re using Maven, as many people are, the solution is to exclude certain transitive dependencies in your POM files. I’ve had to do this at least 4 times in the past couple of months.

But why should this even be necessary? I’ve found no clue as to why the Hibernate team has not upgraded from the 1.X branch to the 2.X branch in the roughly 20 years it has been available [1]. Which is why I’ve come to the conclusion that the only possible rationale behind this state of affairs is that the Hibernate team is using it as a stumbling block to Spring adoption. Forward the rumor mill!

[1] Time estimate in dog / internet years.

Follow

Get every new post delivered to your Inbox.