Java Performance Tuning

Java(TM) - see bottom of page

|home |services |training |newsletter |tuning tips |tool reports |articles |resources |about us |site map |contact us |
Tools: | GC log analysers| Multi-tenancy tools| Books| SizeOf| Thread analysers|

Our valued sponsors who help make this site possible
New Relic: Try free w/ production profiling and get a free shirt! 

Site24x7: Java Method-Level Tracing into Transactions @ $12/Month/JVM. Sign Up! 

News August 2012

jKool for DevOps
Light up your Apps & get a cool t-shirt

JProfiler
Get rid of your performance problems and memory leaks!


Java Performance Training Courses
COURSES AVAILABLE NOW. We can provide training courses to handle all your Java performance needs

Java Performance Tuning, 2nd ed
The classic and most comprehensive book on tuning Java

Java Performance Tuning Newsletter
Your source of Java performance news. Subscribe now!
Enter email:


New Relic
New Relic: Try free w/ production profiling and get a free shirt!

Site24x7
Site24x7: Java Method-Level Tracing into Transactions @ $12/Month/JVM. Sign Up!


jKool for DevOps
Light up your Apps & get a cool t-shirt

JProfiler
Get rid of your performance problems and memory leaks!


Back to newsletter 141 contents

There was an interesting change in Java 7 update 6, which was released this month. An alternative hash function was included for all the commonly used hash map classes (see our news below). This alternative hash function is off by default, as it affects the ordering of keys and values and some (incorrectly implemented) apps may rely on that ordering. You can turn on the alternative hashing by setting the property jdk.map.althashing.threshold to the capacity of maps above which you want the alternative hashing to kick in (the default value is -1, hence the threshold is never reached). E.g. setting -Djdk.map.althashing.threshold=512 will cause every map that reaches a capacity of 512 to switch to using alternative hashing.

With the alternative hash function off, each affected map has an extra conditional test on all updates and accesses, but as it's always if(false) the JIT compiler should quickly eliminate it thus giving no real overhead in that case.

A note from this newsletter's sponsor

ManageEngine: Application Performance Management for Java EE Apps.
Monitor App Servers: JBoss, WebSphere, WebLogic, JVMs and JMX Apps.
*** Monitor up to 25 App Servers, Databases & Servers at $795/Yr***.

The interesting thing is why this was added, and how. It's a little story that illustrates many a performance fix. Firstly, the problem it's addressing is that hash maps can suffer from excessive collisions if the hash codes are badly distributed, and it appears Strings are often badly distributed [to remind you, hash maps internally use an array, and use the hash code of the key to select an index into the array where the key and value will be stored; a collision is where two different keys map to the same index - cases that obviously need extra work to handle, hence the overhead of collisions]. The ideal solution here would be to just change the String.hashCode() method, but sadly the String.hashCode() method is documented to work in a particular way, and so many things could conceivably be broken if this method implementation was changed, which means it can't be changed.

The next best option would be to add a new hash() method to Object which returns hashCode(), and override that for String (and anything else that could benefit from an improved hashcode), then change the maps to use hash() instead of hashCode(). Anyone from a Smalltalk background would recognize that option - in Smalltalk you could easily add methods to Object and it was a pretty good solution to these types of problems. But adding a new method to Object in Java is controversial and not done lightly, so this option was discarded (for now).

So instead the hash function within the various maps need to be changed. The generic way to do this would be to create a new interface, say called Hashable with method interface int hash(), and then the "get the hash code" call in the map would be h = (key instanceof Hashable)? ((Hashable)key).hash() : key.hashCode();. And, of course, String would implement Hashable. Job done.

But it turns out that calling instanceof against an interface is slooow. At least compared to calling instanceof against a class - Mike Duigou at Oracle says "often more than 25X" slower. So given that this is a performance fix for a particular issue (String hashcodes badly distributed), the decision was made to apply the tactical fix to the update 6 release that solves the specific problem. This results in the following code (roughly) added to hash functions in various map implementations if (useAltHashing) if (key instanceof String) return Hashing.stringHash((String) key);

So, finally, end of story? Not quite. Like most performance fixes, there is a tradeoff. The alternative hash function can be slower for short strings, so if your maps consist of short string keys that don't have many collisions, performance would be worse with the alternative hash function turned on. But that's normal for performance fixes: fiddly details to get around in the implementation to minimize the changes across the system; better speed for the majority of cases; some cases worse off; a config switch that lets you turn it on or off. A classic performance tune.

Now on to all our usual links to Java performance tools, news, articles and, as ever, all the extracted tips from all of this month's referenced articles.

A note from this newsletter's sponsor

New Relic - Try New Relic today and get your free Data Nerd shirt!
Free SaaS APM tool to monitor, troubleshoot, and tune apps
running on Websphere, Weblogic, Tomcat, Jetty, JBoss, Solr, Resin

News

Java performance related news.

Tools

Java performance related tools.

A note from this newsletter's sponsor

Free Java Performance Tool - From AppDynamics
Fight fires in production with less than 2% overhead.
Gain complete visibility into your java app. Free Download!

Articles

Jack Shirazi


Back to newsletter 141 contents


Last Updated: 2017-05-31
Copyright © 2000-2017 Fasterj.com. All Rights Reserved.
All trademarks and registered trademarks appearing on JavaPerformanceTuning.com are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. JavaPerformanceTuning.com is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
URL: http://www.JavaPerformanceTuning.com/news/news141.shtml
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us