So I have been trying to digest the discussion of the Spring v Guice benchmarks. There seems to be a lot of play on the "Guice isn't *that* much faster than Spring" meme.
The thing is, even the author of this study notes:
Analysis of the CPU metering data also revealed the same strange difference in test ordering across technologies when the table was sorted by the Total column. Because CPU is a thread specific meter I looked at the totals for the Run probe group. Spring (CS) was 11.028 seconds compared with Guice’s (CS) 13.112 seconds - approximately 2 seconds in the difference but not 6 seconds. Could this be a clue? Well not necessarily because the CPU times for Spring (S) and Guice (S) were reversed though somewhat closer - 2.203 seconds compared to 2.075 seconds respectively. It would appear from this that Guice trades additional CPU processing with a reduction in thread monitor contention.
Now, I am not going get into the whole fray here, but in the Web world, isn't this the best tradeoff you can make?
Here's the thing about the web: threading matters. My friend Michael this weekend was showing off MERB, a replacement runtime host for Ruby on Rails that is seriously faster. Why is it faster? Because he cribbed the servlet model. That is, everything is hard threadsafe and therefore a single container can service multiple simultaneous requests, unlike the standard Ruby technique of running multiple Mongrels on a box. Of course, people complain about the non-threadsafe ActiveRecord, which gives rise to hacks like this.
That's a lot of Ruby, but the short version is, they are learning what the Java People figured out a while ago: minimum thread munging makes your app rule. This is, it seems to me, the beauty of Guice.
This continues into the Singleton testing done here...
The Guice singleton tests had not only higher values than the same tests under Spring but more significantly they were higher than the Guice non-singleton tests. But why did the Spring numbers for singleton tests look still too high? I decided to take another look at the validate(...) method and the out bound calls. This time I was looking for a method that might inadvertently create objects. I found the culprit. The JUnit assertEquals(int,int) creates two Integers before calling Object.equals(Object).
Here are the revised figures after replacing the Assert.assertEquals(int, int) method with an implementation that does not create any Integer objects. The Spring results now looked inline with what we would expect from a single factory - an object instance created for each additional concurrent thread.
Really, what is the short answer to this question? Singletons == bad. The idiosyncrasies of JUnit here aside, properly managing singletons in a thread safe factory is hard, which is why we are told to avoid them in the first place. Really in this context, you should be dealing with mostly session scoped stuff anyway, but I digress.
Comments
Clarifications
Hi kebernet,
This was an runtime analysis report and nowhere did I say this is good or bad. I stuck to the facts of this particular runtime and execution model. No serious performance engineer or architect is going to state that singleton are bad or good it all depends. The purpose of this article was to show how to understand what exactly is inferred when such results are published and whether this is indeed the case.
I really think you need to re-read the article again and capture the essence rather than a sample which is our of context and is ironically the issue with benchmarks themselves. Disconnect the engineer for a second and you might actually see the forest from the trees. I am not saying I do not have this problem myself occasionally which my daugther always seems to point out when I play with her. The keyword here is "Observation". There advice is not in the results of the analysis but in the analysis itself.
regards,
William