<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1729822519392175009</id><updated>2012-02-03T15:05:53.445Z</updated><category term='Puzzles'/><category term='Info'/><category term='Opinion'/><category term='Performance'/><category term='concurrency'/><category term='Testing'/><title type='text'>Vanilla #Java</title><subtitle type='html'>Understanding how Core Java really works can help you write simpler, faster applications.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default?start-index=101&amp;max-results=100'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>166</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4222864502158035254</id><published>2012-01-26T09:07:00.003Z</published><updated>2012-01-26T15:15:47.237Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>"Java Sucks" revisited</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;An interesting document on Java's short comings (from C developer's perspective) was written some time ago (about 2000? ) but many of the arguments issues are as true (or not) today as they were ten years ago.&lt;p/&gt;The original &lt;a href="http://www.jwz.org/doc/java.html"&gt;Java Sucks&lt;/a&gt; posting.&lt;p/&gt;&lt;h2&gt;Review of short comings&lt;/h2&gt;&lt;h4&gt;Java doesn't have free().&lt;/h4&gt;The author lists this as a benefit and 99% of the time is a win.  There are times when not having it is a downside, when you wish escape analysiswould eliminate, recycle or free immediately an object you know isn't needed any more (IMHO the JIT / javac should be able to work it out in theory)&lt;p/&gt;&lt;h4&gt;lexically scoped local functions&lt;/h4&gt;The closest Java has is anonymous methods.  This is a poor cousin to Closures (coming in Java 8), but it can be made to do the same thing.&lt;p/&gt;&lt;h4&gt;No macro system&lt;/h4&gt;Many of the useful tricks you can do with macros, Java can do for you dynamically. Not needing a macro system is an asset because you don't need to know when Java will give you the same optimisations.  There is an application start up cost that macros don't have and you can't do the really obfuscated stuff, but this is probably a good thing.&lt;p/&gt;&lt;h4&gt;Explicitly Inlined functions&lt;/h4&gt;The JIT can inline methods for you.  Java can inline methods from shared libraries, even if they are updated dynamically.  This does come at a run time cost, but its nicer not to need to worry about this IMHO.&lt;p/&gt;&lt;h4&gt;I find lack of function pointers a huge pain&lt;/h4&gt;Function pointers makes in lining methods more difficult for the compiler.  If you are using object orientated programming, I don't believe you need these.  For other situations, I believe Closures in Java 8 is likely to be nicer.&lt;p/&gt;&lt;h4&gt;The fact that static methods aren't really class methods is pretty dumb&lt;/h4&gt;I imagine most Java developers have come across this problem at some stage.  IMHO: The nicest solution is to move the "static" functionality to its own class and not use static methods if you want polymorphism.&lt;p/&gt;&lt;h4&gt;It's far from obvious how one hints that a method should be inlined, or otherwise go real fast&lt;/h4&gt;Make it small and call it lots of times. ;)&lt;p/&gt;&lt;h4&gt;Two identical byte[] arrays aren't equal and don't hash the same&lt;/h4&gt;I agree that its pretty ugly design choice not to make arrays proper objects.  They inherit from Object, but don't have useful implementation for toString, equals, hashCode, compareTo.  clone() and getClass() are the most useful methods.  You can use helper methods instead, but with  many different helper classes called Array, Arrays, ArrayUtil, ArrayUtils in different packages its all a mess for a new developer to deal with.&lt;p/&gt;&lt;h4&gt;Hashtable/HashMap does allow you to provide a hashing function&lt;/h4&gt;This is also a pain if you want to change the behaviour.  IMHO, The best solution is to write a wrapper class which implements equals/hashCode, but this adds overhead.&lt;p/&gt;&lt;h4&gt;iterate the characters in a String without implicitly involving half a dozen method calls per character&lt;/h4&gt;There is now String.toCharArray() but this creates a copy you don't need and is not eliminated by escape analysis.  When it is, this is the obvious solution.&lt;p/&gt;The same applies to "The other alternative is to convert the String to a byte[] first, and iterate the bytes, at the cost of creating lots of random garbage"&lt;p/&gt;&lt;h4&gt;overhead added by Unicode support in those cases where I'm sure that there are no non-ASCII characters. &lt;/h4&gt;Java 6 has a solution to this which is -XX:+UseCompressedStrings. Unfortunately Java 7 has dropped support for this feature. I have no idea why as this option improves performance (as well as reducing memory usage) in test I have done.&lt;p/&gt;&lt;h4&gt;Interfaces seem a huge, cheesy copout for avoiding multiple inheritance; they really seem like they were grafted on as an afterthought.&lt;/h4&gt;I prefer a contract which only lists functionality offered without adding implementation.  The newer &lt;a href="http://medianetwork.oracle.com/video/player/1113272518001"&gt;Virtual Extension Methods&lt;/a&gt; in Java 8 will provide default implementations without state.  In some cases this will be very useful.&lt;p/&gt;&lt;h4&gt;There's something kind of screwy going on with type promotion &lt;/h4&gt;The problem here is solved by co-variant return types which Java 5.0+ now supports.&lt;p/&gt;&lt;h4&gt;You can't write a function which expects and Object and give it a &lt;i&gt;short&lt;/i&gt;&lt;/h4&gt;Today you have auto-boxing.  The author complains that Short and short are not the same thing.  For efficiency purposes this can make surprisingly little difference in some cases with auto-boxing. In some cases it does make a big difference, and I don't foresee Java optimising this transparently in the near future. :|&lt;p/&gt;&lt;h4&gt;it's a total pain that one can't iterate over the contents of an array without knowing intimate details about its contents&lt;/h4&gt;Its rare you really need to do this IMHO.  You can use &lt;i&gt;Array.getLength(array)&lt;/i&gt; and &lt;i&gt;Array.get(array, n)&lt;/i&gt; to handle a generic array. Its ugly but you can do it. Its one of the helper class which should really be methods on the array itself IMHO.&lt;p/&gt;&lt;h4&gt;The only way to handle overflow is to use BigInteger (and rewrite your code)&lt;/h4&gt;Languages like Scala support operators for BigInteger and it has been suggested that Java should too.  I believe overflow detection is also being considered for Java 8/9.&lt;p/&gt;&lt;h4&gt;I miss &lt;i&gt;typedef&lt;/i&gt;&lt;/h4&gt;This allows you to use primitives and still get type safety.  IMHO, the real issue is that the JIT cannot detect that a type is just a wrapper for a primitive (or two) and eliminate the need for the wrapped class.  This would provide the benefits of &lt;i&gt;typedef&lt;/i&gt; without changing the syntax and make the code more Object Orientated.&lt;p/&gt;&lt;h4&gt;I think the available idioms for simulating enum and :keywords are fairly lame&lt;/h4&gt;Java 5.0+ has &lt;a href="http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html"&gt;&lt;i&gt;enum&lt;/i&gt;&lt;/a&gt; which are first class objects and are surprising powerful.&lt;p/&gt;&lt;h4&gt;there's no efficient way to implement `assert'&lt;/h4&gt;&lt;i&gt;assert&lt;/i&gt; is now built in. To implement it yourself is made efficient by the JIT. (Probably not tens years ago)&lt;p/&gt;&lt;h4&gt;By having `new' be the only possible interface to allocation, ... there are a whole class of ancient, well-known optimizations that one just cannot perform. &lt;/h4&gt;This should be performed by the JIT IMHO. Unfortunately, it rarely does, but this is improving.&lt;p/&gt;&lt;h4&gt;The finalization system is lame.&lt;/h4&gt;Most people agree its best avoided.  Perhaps it could be more powerful and reliable. ARM (Automatic Resource Management) may be the answer.&lt;p/&gt;&lt;h4&gt;Relatedly, there are no ``weak pointers.''&lt;/h4&gt;Java has always had weak, soft and phantom references, but I suspect this is not what is meant here. ??&lt;p/&gt;&lt;h4&gt;You can't close over anything but final variables in an inner class!&lt;/h4&gt;There is true of anonymous inner classes, but not nested inner classes referring to fields.  Closures might not have this restriction but its likely to be just as confusing.  Being used to the requirement for final variables, I don't find this problem esp. as my IDE will correct the code as required for me.&lt;p/&gt;&lt;h4&gt;The access model with respect to the mutability (or read-only-ness) of objects blows&lt;/h4&gt;The main complaint appears to be that there are ways of treating final fields as mutable.  This is required for de-serialization and dependency injectors.  As long as you realise that you have two possible behaviours, one lower level than the other, it is far more useful than it is a problem.&lt;p/&gt;&lt;h4&gt;The language also should impose the contract that literal constants are immutable.&lt;/h4&gt;Literal constants are immutable. It appears the author would like to expand what is considered a literal constant. &lt;p/&gt;It would be useful IMHO, to support &lt;i&gt;const&lt;/i&gt; in the way C++ does. &lt;i&gt;const&lt;/i&gt; is a keyword in Java and the ability to define immutable versions of classes without creating multiple implementations or read only wrappers would be more productive.&lt;p/&gt;&lt;h4&gt;The locking model is broken.&lt;/h4&gt;The memory overhead of locking concern is really an implementation detail.  Its up to the JVM to decide how large the header is and whether it can be locked.  The other concern is that there is no control over who can obtain a lock.  The common work around for this is to encapsulate your lock, which is what you would have to do in any case.&lt;p/&gt;In theory the lock can be optimised away.  Currently this only happens when the whole object is optimised way.&lt;p/&gt;&lt;h4&gt;There is no way to signal without throwing&lt;/h4&gt;For this, I use a listener pattern with an &lt;i&gt;onError&lt;/i&gt; method.  There is no support in the language for this, but I don't see the need to.&lt;p/&gt;&lt;h4&gt;Doing foo.x should be defined to be equivalent to foo.x(), &lt;/h4&gt;Perhaps foo.x =&gt; foo.getX() would be a better choice, rather like C# does.&lt;p/&gt;&lt;blockquote&gt;Compilers should be trivially able to inline zero-argument accessor methods to be inline object+offset loads.&lt;/blockquote&gt;The JIT does this, rather than the compiler.  This allows the calling code to be changed after the callee has been compiled.&lt;p/&gt;&lt;h4&gt;The notion of methods "belonging" to classes is lame. &lt;/h4&gt;This is a "cool" feature which some languages support.  In a more dynamic environment, this can look nicer.  The down side is that you can piece of code for a class all over the place and you would have to have some way of managing duplicates in different libraries. e.g. library A defines a new printString() method and library B also defines a printString method for the same class.  You would need to make each library see its own copy and have some way of determining which version library C would want when it calls this method.&lt;p/&gt;&lt;h2&gt;Libraries&lt;/h2&gt;&lt;h4&gt;It comes with hash tables, but not qsort&lt;/h4&gt;It comes with an "optimised merge sort" which is designed to be faster.&lt;p/&gt;&lt;h4&gt;String has length+24 bytes of overhead over byte[]&lt;/h4&gt;That is without considering that each of the two objects are aligned to an 8 byte boundary (making it higher).  If that sounds bad, consider that &lt;i&gt;malloc&lt;/i&gt; can be 16-byte aligned with a minimum size of 32 bytes.  If you use a shared_ptr to a byte[] (to give you similar resource management) it can be much larger in C++ than Java.&lt;blockquote&gt;The only reason for this overhead is so that String.substring() can return strings which share the same value array. &lt;/blockquote&gt;This is not correct.  The problem is that Java doesn't support variable sized objects (apart from arrays).  This means that String object is a fixed size and to have variable sized field, you have to have another object.  Its not great either way. ;)&lt;p/&gt;&lt;h4&gt;String.substring can be a source of "memory leak"&lt;/h4&gt;You have to know to take an explicit copy of you are going to retain a substring of a larger string.  This is ugly, however the benefits usually out weight the down side.  What would be a better solution is to be able to optimise the code so that a defensive copy was taken by default, except when the defensive copy is not needed (it is optimised away)&lt;p/&gt;&lt;h4&gt;The file manipulation primitives are inadequate&lt;/h4&gt;The file system information has been improved in Java 7. I don't think these options are available, but can be easily inferred if you need to know this.&lt;p/&gt;&lt;h4&gt;here is no robust way to ask ``am I running on Windows'' or ``am I running on Unix.'&lt;/h4&gt;There are System properties &lt;i&gt;os.name, os.arch, os.version&lt;/i&gt; which have always been there.&lt;p/&gt;&lt;h4&gt;There is no way to access link() on Unix, which is the only reliable way to implement file locking. &lt;/h4&gt;This was added in Java 7 &lt;a href="http://docs.oracle.com/javase/tutorial/essential/io/links.html#hardLink"&gt;Creating a Hard Link&lt;/a&gt;&lt;p/&gt;&lt;h4&gt;There is no way to do ftruncate(), except by copying and renaming the whole file. &lt;/h4&gt;You can use RandomAccessFile.truncate(). Adding in Java 1.4.&lt;p/&gt;&lt;h4&gt;Is "%10s %03d" really too much to ask?&lt;/h4&gt;It was added in Java 5.0&lt;p/&gt;&lt;h4&gt;A RandomAccessFile cannot be used as a FileInputStream or FileOutputStream&lt;/h4&gt;RandomAccessFile supports DataInput and DataOutput, FileInputStream and FileOutputStream can be wrapped in DataInputStream and DataOutputStream.   They can be made to support the same interfaces.  I have never come across a situation where I would want to use both classes in a single method.&lt;p/&gt;&lt;h4&gt;markSupported is stupid&lt;/h4&gt;True.  There are a number of stupid methods which are only there for historical purposes.  Another being &lt;i&gt;Object.wait(millis, nanos)&lt;/i&gt; on every object (even arrays) and yet the nanos is never really used.&lt;p/&gt;&lt;h4&gt;What in the world is the difference between System and Runtime?&lt;/h4&gt;I agree it appears arbitrary and in some cases doubled up.  System.gc() actually calls Runtime.getRuntime().gc() and yet is called System GC even in internal code.  In hind site they should really be one class with monitoring functionality moved to JMX.&lt;p/&gt;&lt;h4&gt;What in the world is application-level crap like checkPrintJobAccess() doing in the base language class library&lt;/h4&gt;So your SecurityManager can control whether you can perform printing. (Without having to have an Application level Security Manager as well)  Not sure is this really prevents the need to have Application level security. ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4222864502158035254?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4222864502158035254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-sucks-revisited.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4222864502158035254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4222864502158035254'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-sucks-revisited.html' title='&quot;Java Sucks&quot; revisited'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1585992349454762219</id><published>2012-01-23T08:32:00.002Z</published><updated>2012-02-02T09:06:27.035Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Demonstrating when volatile is required</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;In many cases &lt;i&gt;volatile&lt;/i&gt; is required when you need a guarantee about visibility of changes between threads. i.e. All threads see a consistent view of the same field.  Demonstrating a consistent failure when you don't use &lt;i&gt;volatile&lt;/i&gt; is tricky, and likely to be platform specific.&lt;p/&gt;&lt;h2&gt;An example&lt;/h2&gt;The following example show that each thread starts by flipping the value and then stops as each thread has a different view of the field &lt;i&gt;value&lt;/i&gt;  This works on Java 7 update 2 on Centos 5.7 (x64).  &lt;p/&gt;Even incidental change to the code, change the behaviour showing how brittle the example is. I would be interested if others can reproduce this behaviour&lt;p/&gt;&lt;h2&gt;The code&lt;/h2&gt;&lt;pre&gt;&lt;br /&gt;public class RequiresVolatileMain {&lt;br /&gt;    static boolean value;&lt;br /&gt;&lt;br /&gt;    public static void main(String... args) {&lt;br /&gt;        new Thread(new MyRunnable(true), "Sets true").start();&lt;br /&gt;        new Thread(new MyRunnable(false), "Sets false").start();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static class MyRunnable implements Runnable {&lt;br /&gt;        private final boolean target;&lt;br /&gt;&lt;br /&gt;        private MyRunnable(boolean target) {&lt;br /&gt;            this.target = target;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public void run() {&lt;br /&gt;            int count = 0;&lt;br /&gt;            boolean logged = false;&lt;br /&gt;            while (true) {&lt;br /&gt;                if (value != target) {&lt;br /&gt;                    value = target;&lt;br /&gt;                    count = 0;&lt;br /&gt;                    if (!logged)&lt;br /&gt;                        System.out.println(Thread.currentThread().getName() + ": reset value=" + value);&lt;br /&gt;                } else if (++count % 1000000000 == 0) {&lt;br /&gt;                    System.out.println(Thread.currentThread().getName() + ": value=" + value + " target=" + target);&lt;br /&gt;                    logged = true;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;As you can see, each thread tries to flip the &lt;i&gt;value&lt;/i&gt; whenever it doesn't match the &lt;i&gt;target&lt;/i&gt;.  When you attempt to run this fails, perhaps not in the way you might expect. If you run this with -XX:+PrintCompilation&lt;pre&gt;&lt;br /&gt;Sets true: reset value=true&lt;br /&gt;Sets false: reset value=false&lt;br /&gt;....&lt;br /&gt;Sets true: reset value=true&lt;br /&gt;Sets false: reset value=false&lt;br /&gt;     44    1 %           com.google.code.java.core.threads.RequiresVolatileMain$MyRunnable::run @ 4 (129 bytes)&lt;br /&gt;Sets true: reset value=true&lt;br /&gt;Sets false: reset value=false&lt;br /&gt;....&lt;br /&gt;Sets true: reset value=true&lt;br /&gt;Sets false: reset value=false&lt;br /&gt;Sets true: value=false target=true&lt;br /&gt;Sets false: value=true target=false&lt;br /&gt;...&lt;br /&gt;Sets true: value=false target=true&lt;br /&gt;Sets false: value=true target=false&lt;br /&gt;&lt;/pre&gt;Not long after the code is compiled, the code starts acting as if it doesn't detect a change even though the value printed is clearly not the target.  Exactly why it fails this way is not clear. esp. as the &lt;i&gt;value&lt;/i&gt; in the same thread appears to be inconsistent.&lt;p/&gt;The only explanation I can come up with is that &lt;i&gt;if (value != target)&lt;/i&gt; has been incorrectly optimised away.  Possibly because the only branch which sets this value is not run most of the time.&lt;p/&gt;Just caching the value stops it failing for me, but this is not a proper fix and might fail on a different platform&lt;pre&gt;&lt;br /&gt;                // caching the value stops the failure.&lt;br /&gt;                boolean value = RequiresVolatileMain.value;&lt;br /&gt;                if (value != target) {&lt;br /&gt;                    RequiresVolatileMain.value = target;&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;&lt;h2&gt;The solution&lt;/h2&gt;The solution is to use a volatile variable, in which case it keeps printing that the value is reset as expected.&lt;p/&gt;&lt;h2&gt;Why does this fail&lt;/h2&gt;The values are boolean.  This is like a game of ping-pong.  The ball is only on one side, either true or false (if you use volatile)  It doesn't matter which values it is, only one thread will change the value.&lt;p/&gt;Without volatile, this breaks down in a number of possible ways.  One way is that the two threads each think they have changed the value and are waiting for the other i.e. each has its own cached copy of the value.&lt;p/&gt;The way it breaks down in the example above is that the compiler detect that the value is not changed if it is the target value already and the thread is not going to set it to any other value.  It then assumes the check isn't required and even though both thread print the value as needing changing (the opposite of the previous case) it stops changing the value.&lt;p/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1585992349454762219?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1585992349454762219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/demonstrating-when-volatile-is-required.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1585992349454762219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1585992349454762219'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/demonstrating-when-volatile-is-required.html' title='Demonstrating when volatile is required'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7484353716697042525</id><published>2012-01-22T10:52:00.001Z</published><updated>2012-01-22T19:31:40.812Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Another Shifty Challenge</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Shifting has lots of edge cases.  Some particular to Java.&lt;p/&gt;&lt;h2&gt;Over shifting&lt;/h2&gt;In C the expression &lt;i&gt;n &lt;&lt; 64&lt;/i&gt; and &lt;i&gt;n &gt;&gt; 64&lt;/i&gt; would always be 0, but in Java it will always be &lt;i&gt;n&lt;/i&gt;  This is because the shifted value is mod'ed by the number of bits.&lt;p/&gt;&lt;h2&gt;A puzzle&lt;/h2&gt;If the following program&lt;pre&gt;&lt;br /&gt;for (int i = -200; i &lt; 200; i++)&lt;br /&gt;    if (i &gt;&gt;&gt; i == 1)&lt;br /&gt;        System.out.print(i+" ");&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;-193 -161 -129 -97 -65 -33 -1 37 70 102 135 167 199 &lt;br /&gt;&lt;/pre&gt;What do you get if you change the type to &lt;i&gt;long&lt;/i&gt;?&lt;p/&gt;&lt;h4&gt;See if you can work it out without running the code.&lt;/h4&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7484353716697042525?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7484353716697042525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/another-shifty-challenge.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7484353716697042525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7484353716697042525'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/another-shifty-challenge.html' title='Another Shifty Challenge'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5104030107590253674</id><published>2012-01-19T08:59:00.000Z</published><updated>2012-01-22T19:31:40.781Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Shifting Challenge</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Using shift in Java and some surprising edge cases.&lt;p/&gt;&lt;h2&gt;Getting the sign&lt;/h2&gt;For the following program, what is the values for &lt;i&gt;n&lt;/i&gt; so that I can change the type of &lt;i&gt;x&lt;/i&gt; without having to change the code.&lt;pre&gt;&lt;br /&gt;// sign is 1 if negative and 0 if non-negative&lt;br /&gt;long sign = x &gt;&gt;&gt; n;&lt;br /&gt;&lt;/pre&gt;There is a value you can replace &lt;i&gt;n&lt;/i&gt; such that you don't need to know the type of &lt;i&gt;x&lt;/i&gt;&lt;p/&gt;Similarly, I want to shift the lowest bit to be the highest without knowing what type I am shifting&lt;pre&gt;&lt;br /&gt;// sign is MIN_VALUE if odd otherwise 0&lt;br /&gt;long sign = x &lt;&lt; n;&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;For bonus points, write formula for all the possible solutions of &lt;i&gt;n&lt;/i&gt; (there is more than one)&lt;p/&gt;&lt;h2&gt;Is a power of two&lt;/h2&gt;How do you determine an integer is a power of 2.&lt;p/&gt;This is a fairly common interview question.  Its pretty hard to figure out in an interview I imagine. To save you googling, you can write this in C with &lt;pre&gt;&lt;br /&gt;x&amp;&amp;!(x&amp;(x-1))&lt;br /&gt;&lt;/pre&gt;In Java, you can write this using just 0 ~ - &amp; == != .  Complete this expression using those operators&lt;pre&gt;&lt;br /&gt;long x = &lt;br /&gt;boolean isPow2 = x != 0 .....&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5104030107590253674?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5104030107590253674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/shifting-challenge.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5104030107590253674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5104030107590253674'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/shifting-challenge.html' title='Shifting Challenge'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6556657534298731086</id><published>2012-01-18T20:58:00.001Z</published><updated>2012-01-22T19:31:40.797Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Unsigned Challenge</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Its easy to assume that because Java doesn't support unsigned primitives that you need a complex wrapper to using unsigned numbers.&lt;p/&gt;&lt;h2&gt;The challenge&lt;/h2&gt;Modify the following class which has been written to use signed &lt;i&gt;int&lt;/i&gt; as unsigned value. The starting code works for signed values.  You need to change the methods so it treats them as unsigned 32-bit &lt;i&gt;int&lt;/i&gt; values.  The aim is to add/change a minimum of lines. (You can't change the tests or turn them off)&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;public enum Unsigned {;&lt;br /&gt;    public static int add(int i, int j) {&lt;br /&gt;        return i + j;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static int subtract(int i, int j) {&lt;br /&gt;        return i - j;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static int multiply(int i, int j) {&lt;br /&gt;        return i * j;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static int shiftLeft(int i, int n) {&lt;br /&gt;        return i &lt;&lt; n;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static int shiftRight(int i, int n) {&lt;br /&gt;        return i &gt;&gt; n;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static int parseUnsignedInt(String text) {&lt;br /&gt;        return Integer.parseInt(text);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static String toString(int n) {&lt;br /&gt;        return Integer.toString(n);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String... args) {&lt;br /&gt;        assert "2500000000".equals(toString(subtract(add(2000 * 1000 * 1000, 1750 * 1000 * 1000), 1250 * 1000 * 1000)));&lt;br /&gt;        assert "4000000000".equals(toString(multiply(1000 * 1000, 4000)));&lt;br /&gt;        assert "3200000000".equals(toString(shiftLeft(100 * 1000 * 1000, 5)));&lt;br /&gt;        assert "1000000000".equals(toString(shiftRight(parseUnsignedInt("4000000000"), 2)));&lt;br /&gt;&lt;br /&gt;        ByteArrayOutputStream baos = new ByteArrayOutputStream();&lt;br /&gt;        DataOutputStream dos = new DataOutputStream(baos);&lt;br /&gt;        writeUnsignedInt(dos, multiply(1000 * 1000, 4000));&lt;br /&gt;        writeUnsignedInt(dos, parseUnsignedInt("3210000000"));&lt;br /&gt;        dos.close();&lt;br /&gt;        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));&lt;br /&gt;        assert "4000000000".equals(toString(readUnsignedInt(dis)));&lt;br /&gt;        assert "3210000000".equals(toString(readUnsignedInt(dis)));&lt;br /&gt;        dis.close();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;Hint: The solutions are surprisingly simple (which is the point of this article)  If you are adding many lines of code, you are heading down the wrong path.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6556657534298731086?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6556657534298731086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/unsigned-challenge.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6556657534298731086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6556657534298731086'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/unsigned-challenge.html' title='Unsigned Challenge'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2650276145296281187</id><published>2012-01-16T16:52:00.000Z</published><updated>2012-01-30T10:13:40.507Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Java Thread Affinity support for ExecutorService</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The &lt;a href="https://github.com/peter-lawrey/Java-Thread-Affinity"&gt;Java Thread Affinity version 1.4.1&lt;/a&gt; library has support for the concurrency library through an AffinityThreadFactory.&lt;p/&gt;This follows my previous article on &lt;a href="http://vanillajava.blogspot.com/2012/01/java-thread-affinity-support-for-hyper.html"&gt;HyperThreading support in the library&lt;/a&gt; which give mroe detail on what it does and how it works.&lt;p/&gt;&lt;h2&gt;Example&lt;/h2&gt;In the AffinityThreadFactoryMain example,&lt;pre&gt;&lt;br /&gt;private static final ExecutorService ES = Executors.newFixedThreadPool(4,&lt;br /&gt;        new AffinityThreadFactory("bg", SAME_CORE, DIFFERENT_SOCKET, ANY));&lt;br /&gt;&lt;br /&gt;public static void main(String... args) throws InterruptedException {&lt;br /&gt;    for (int i = 0; i &lt; 12; i++)&lt;br /&gt;        ES.submit(new Callable&lt;Void&gt;() {&lt;br /&gt;            @Override&lt;br /&gt;            public Void call() throws InterruptedException {&lt;br /&gt;                Thread.sleep(100);&lt;br /&gt;                return null;&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;    Thread.sleep(200);&lt;br /&gt;    System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks());&lt;br /&gt;    ES.shutdown();&lt;br /&gt;    ES.awaitTermination(1, TimeUnit.SECONDS);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;by changing the ThreadFactory, you can decide how threads in the factory should be laid out.  The default behaviour is to allocate from highest CPU id to lowest, however by changing the AffinityStrategy you can make it try to minimise the number of cores it uses.&lt;pre&gt;&lt;br /&gt;Assigning cpu 7 to Thread[bg,5,main]&lt;br /&gt;Assigning cpu 6 to Thread[bg-2,5,main]&lt;br /&gt;Assigning cpu 3 to Thread[bg-3,5,main]&lt;br /&gt;Assigning cpu 2 to Thread[bg-4,5,main]&lt;br /&gt;&lt;br /&gt;The assignment of CPUs is&lt;br /&gt;0: General use CPU&lt;br /&gt;1: General use CPU&lt;br /&gt;2: Thread[bg-4,5,main] alive=true&lt;br /&gt;3: Thread[bg-3,5,main] alive=true&lt;br /&gt;4: General use CPU&lt;br /&gt;5: General use CPU&lt;br /&gt;6: Thread[bg-2,5,main] alive=true&lt;br /&gt;7: Thread[bg,5,main] alive=true&lt;br /&gt;&lt;br /&gt;Releasing cpu 7 from Thread[bg,5,main]&lt;br /&gt;Releasing cpu 6 from Thread[bg-2,5,main]&lt;br /&gt;Releasing cpu 3 from Thread[bg-3,5,main]&lt;br /&gt;Releasing cpu 2 from Thread[bg-4,5,main]&lt;br /&gt;&lt;/pre&gt;In this case, the second thread is allocated to the SAME_CORE as the first, the third cannot get one on the same core so it tries to get on on a DIFFERENT_SOCKET, but there is only one so it takes ANY available core which can be reserved. &lt;p/&gt;&lt;h2&gt;Related topics&lt;/h2&gt;&lt;!-- a href="http://vanillajava.blogspot.com/2012/01/java-thread-affinity-library-to-support.html"&gt;Java Thread Affinity support for ExecutorService&lt;/a&gt;&lt;br/ --&gt;&lt;a href="http://vanillajava.blogspot.com/2012/01/java-thread-affinity-support-for-hyper.html"&gt;Java Thread Affinity support for hyper threading.&lt;/a&gt;&lt;br/&gt;&lt;a href="http://vanillajava.blogspot.com/2012/01/java-thread-affinity-supports-groups-of.html"&gt;Java Thread Affinity supports groups of threads.&lt;/a&gt;&lt;/br/&gt;&lt;a href="http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java_29.html"&gt;Thread Affinity library for Java supports JNA &lt;/a&gt;&lt;/br&gt;&lt;a href="http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java.html"&gt;Thread Affinity library for Java. &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2650276145296281187?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2650276145296281187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-thread-affinity-library-to-support.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2650276145296281187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2650276145296281187'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-thread-affinity-library-to-support.html' title='Java Thread Affinity support for ExecutorService'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-137777632096429922</id><published>2012-01-16T13:00:00.000Z</published><updated>2012-01-30T10:13:46.114Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Java Thread Affinity support for hyper threading.</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;A benefit of hyper-threading is the ability to support more threads without incurring the overhead of context switches.  If your threads spend a high proportion of their time waiting for resources e.g. busy waiting on a data source, accessing main memory or waiting for short periods of time for IO,  hyper threading can improve performance at little cost.&lt;p/&gt;However, hyper threading can impact performance when the two threads on the same core start competing for resources, such as the FPU, Level 1 cache, or CPU pipeline.  For these reasons, hyper-threading is often turned off in high performance systems.&lt;h2&gt;A solution to get the best of both worlds&lt;/h2&gt;The &lt;a href="https://github.com/peter-lawrey/Java-Thread-Affinity"&gt;Java Thread Affinity version 1.4&lt;/a&gt; library attempts to get the best of both worlds, by allowing you to reserve a logical thread for critical threads, and reserve a whole core for the most performance sensitive threads.  Less critical threads will still run with the benefits of hyper threading.&lt;p/&gt;&lt;h2&gt;Example&lt;/h2&gt;Say you have a system e.g. an Intel i7 with four core and two logical threads per core.&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-CCidh-_w2JA/TxQcNNrpZrI/AAAAAAAAAI8/_iq94GoUE5Q/s1600/CPUs1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="221" width="330" src="http://4.bp.blogspot.com/-CCidh-_w2JA/TxQcNNrpZrI/AAAAAAAAAI8/_iq94GoUE5Q/s400/CPUs1.png" /&gt;&lt;/a&gt;&lt;/div&gt;You want to reserve two cores to dedicate to critical threads. On Linux you can do this but using isolcpus= in grup.conf&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-bjzJmU8ZB1g/TxQceYSouAI/AAAAAAAAAJI/zFAFBUXfYk8/s1600/CPUs2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="218" width="339" src="http://4.bp.blogspot.com/-bjzJmU8ZB1g/TxQceYSouAI/AAAAAAAAAJI/zFAFBUXfYk8/s400/CPUs2.png" /&gt;&lt;/a&gt;&lt;/div&gt;Say you have two critical thread which are busy waiting for resources and can share a core called "reader" and "writer" and you have an "engine" thread you want to dedicate a whole core to (so it doesn't have to compete for resources)  You can assign the threads as follows.&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-votmjWibAfw/TxQdbBvIqAI/AAAAAAAAAJU/NwMzG3kdsFM/s1600/CPUs3.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="290" width="373" src="http://3.bp.blogspot.com/-votmjWibAfw/TxQdbBvIqAI/AAAAAAAAAJU/NwMzG3kdsFM/s400/CPUs3.png" /&gt;&lt;/a&gt;&lt;/div&gt;The "engine" only uses "CPU 3" and "CPU 7" is reserved as idle.&lt;p/&gt;&lt;h2&gt;How does this look in code&lt;/h2&gt;Sample code to allocate these thread/cores is as follows&lt;pre&gt;&lt;br /&gt;AffinityLock al = AffinityLock.acquireLock();&lt;br /&gt;try {&lt;br /&gt;    // find a cpu on a different socket, otherwise a different core.&lt;br /&gt;    AffinityLock readerLock = al.acquireLock(DIFFERENT_SOCKET, DIFFERENT_CORE);&lt;br /&gt;    new Thread(new SleepRunnable(readerLock, false), "reader").start();&lt;br /&gt;&lt;br /&gt;    // find a cpu on the same core, or the same socket, or any free cpu.&lt;br /&gt;    AffinityLock writerLock = readerLock.acquireLock(SAME_CORE, SAME_SOCKET, ANY);&lt;br /&gt;    new Thread(new SleepRunnable(writerLock, false), "writer").start();&lt;br /&gt;&lt;br /&gt;    Thread.sleep(200);&lt;br /&gt;} finally {&lt;br /&gt;    al.release();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// allocate a whole core to the engine so it doesn't have to compete for resources.&lt;br /&gt;al = AffinityLock.acquireCore(false);&lt;br /&gt;new Thread(new SleepRunnable(al, true), "engine").start();&lt;br /&gt;&lt;br /&gt;Thread.sleep(200);&lt;br /&gt;System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks());&lt;br /&gt;&lt;/pre&gt;This code declares that the "main" thread uses a cpu (it gets 7).  The "reader" thread should use a different socket or a different core. It get a different core as there is no second socket.  The "writer" thread tries to get a thread on the same core, or the same socket, or any thread.  The AffinityStrategy is an interface which allows you to create your own thread allocation strategies.&lt;p/&gt;The "engine" thread tries to allocate a whole core to the thread. (It finds a core where it can allocate all the threads for that core)&lt;p/&gt;When run on an i7 with &lt;i&gt;isolcpus=2,3,6,7&lt;/i&gt; you get the following output&lt;pre&gt;&lt;br /&gt;Assigning cpu 7 to Thread[main,5,main]&lt;br /&gt;Assigning cpu 6 to Thread[reader,5,main]&lt;br /&gt;Assigning cpu 2 to Thread[writer,5,main]&lt;br /&gt;Releasing cpu 7 from Thread[main,5,main]&lt;br /&gt;Assigning core 3: cpus 3, 7 to Thread[engine,5,main]&lt;br /&gt;&lt;br /&gt;The assignment of CPUs is&lt;br /&gt;0: General use CPU&lt;br /&gt;1: General use CPU&lt;br /&gt;2: Thread[writer,5,main] alive=true&lt;br /&gt;3: Thread[engine,5,main] alive=true&lt;br /&gt;4: General use CPU&lt;br /&gt;5: General use CPU&lt;br /&gt;6: Thread[reader,5,main] alive=true&lt;br /&gt;7: Thread[engine,5,main] alive=true&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;&lt;h2&gt;Related topics&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2012/01/java-thread-affinity-library-to-support.html"&gt;Java Thread Affinity support for ExecutorService&lt;/a&gt;&lt;br/&gt;&lt;!-- a href="http://vanillajava.blogspot.com/2012/01/java-thread-affinity-support-for-hyper.html"&gt;Java Thread Affinity support for hyper threading.&lt;/a&gt;&lt;br/ --&gt;&lt;a href="http://vanillajava.blogspot.com/2012/01/java-thread-affinity-supports-groups-of.html"&gt;Java Thread Affinity supports groups of threads.&lt;/a&gt;&lt;/br/&gt;&lt;a href="http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java_29.html"&gt;Thread Affinity library for Java supports JNA &lt;/a&gt;&lt;/br&gt;&lt;a href="http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java.html"&gt;Thread Affinity library for Java. &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-137777632096429922?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/137777632096429922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-thread-affinity-support-for-hyper.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/137777632096429922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/137777632096429922'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-thread-affinity-support-for-hyper.html' title='Java Thread Affinity support for hyper threading.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-CCidh-_w2JA/TxQcNNrpZrI/AAAAAAAAAI8/_iq94GoUE5Q/s72-c/CPUs1.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-799118654358966309</id><published>2012-01-16T09:20:00.005Z</published><updated>2012-01-22T19:31:57.924Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Surprising results of autoboxing</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;There are a number of surprising consequences of auto-boxing.  Some are more widely known than others. Most of them are due to the effect of caching of some auto boxed objects.&lt;p/&gt;&lt;h2&gt;== and equals may or may not match&lt;/h2&gt;If you run the program AutoboxEqualsMain with default options.&lt;pre&gt;&lt;br /&gt;All Boolean are cached.&lt;br /&gt;All Byte are cached.&lt;br /&gt;The first auto-boxed char is 0 and the last is 127&lt;br /&gt;The first auto-boxed short is -128 and the last is 127&lt;br /&gt;The first auto-boxed int is -128 and the last is 127&lt;br /&gt;The first auto-boxed long is -128 and the last is 127&lt;br /&gt;No Float are cached.&lt;br /&gt;No Double are cached.&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;For those that know that == compares &lt;b&gt;references&lt;/b&gt;, for Integer or any Object type.&lt;/p&gt;Run the program again with -XX:+AggressiveOpts on Java 7 and you get almost the same result.&lt;pre&gt;&lt;br /&gt;All Boolean are cached.&lt;br /&gt;All Byte are cached.&lt;br /&gt;The first auto-boxed char is 0 and the last is 127&lt;br /&gt;The first auto-boxed short is -128 and the last is 127&lt;br /&gt;The first auto-boxed int is -128 and the last is 20000&lt;br /&gt;The first auto-boxed long is -128 and the last is 127&lt;br /&gt;No Float are cached.&lt;br /&gt;No Double are cached.&lt;br /&gt;&lt;/pre&gt;Note: This option has increased the maximum for the Integer cache.&lt;p/&gt;&lt;h2&gt;The performance improvements&lt;/h2&gt;The memory size for an &lt;i&gt;int[]&lt;/i&gt; and an &lt;i&gt;ArrayList&amp;lt;Integer&gt;&lt;/i&gt; can be almost the same size for cached values.  If you run this program which builds a collection of both using the numbers 1 to 16,000 with &lt;i&gt;-XX:-UseTLAB&lt;/i&gt; and &lt;i&gt;-XX:+AgressiveOpts&lt;/i&gt; you can get this result.&lt;pre&gt;&lt;br /&gt;The int[16000] took 64592 bytes and new ArrayList&lt;Integer&gt;() with 16000 values took 65048 bytes&lt;br /&gt;&lt;/pre&gt;This result is surprising for two reasons.  Firstly, it is run in a 64-bit JVM.  The ArrayList is an array of references, however the JVM can use 32-bit reference for up to 32 GB of heap memory. Note: You can use direct memory and memory mapped files to use much more than 32 GB, but as long as your heap is smaller than 32 GB it can use 32-bit references.&lt;br/&gt;Secondly, the objects themselves don't appear to take any space.  This is because all the values are cached before the program starts so you don't see the space they occupy.&lt;p/&gt;Note: being such a short test the values for size you get vary with each run. I ran this test a few times and took the lowest result.  The highest results were not that much higher (within 20%)&lt;p/&gt;&lt;h2&gt;Auto-boxed objects don't get garbage collected&lt;/h2&gt;If you use auto-boxed objects as keys, they might never be unloaded.&lt;pre&gt;&lt;br /&gt;Map&amp;lt;Long, String&gt; keyValueMap = new WeakHashMap&amp;lt;Long, String&gt;(10000);&lt;br /&gt;for (long i = 1; i &lt;= 8192; i *= 2)&lt;br /&gt;    keyValueMap.put(i, "key-" + i);&lt;br /&gt;System.out.println("Before GC: " + keyValueMap);&lt;br /&gt;System.gc();&lt;br /&gt;System.out.println("After GC: " + keyValueMap);&lt;br /&gt;&lt;/pre&gt;The keys of the map are not being held so you would expect them to be cleaned up on a GC.  What might be surprising is that not all keys are cleaned up.&lt;pre&gt;&lt;br /&gt;Before GC: {8192=key-8192, 4096=key-4096, 2048=key-2048, 1024=key-1024, 512=key-512, 256=key-256, &lt;br /&gt;    128=key-128, 64=key-64, 32=key-32, 16=key-16, 8=key-8, 4=key-4, 2=key-2, 1=key-1}&lt;br /&gt;After GC: {64=key-64, 32=key-32, 16=key-16, 8=key-8, 4=key-4, 2=key-2, 1=key-1}&lt;br /&gt;&lt;/pre&gt;Note: I increased the initial capacity of the WeakHashMap so that the keys would appear in a predictable order.&lt;p/&gt;&lt;h2&gt;Don't use auto-boxed object for as locks&lt;/h2&gt;This goes up there with not using string literals for locks&lt;pre&gt;&lt;br /&gt;synchronized("lock one") { // DON'T do this.&lt;br /&gt;&lt;/pre&gt;But what can make using auto-boxed values worse is that your program can work fine when tested, provided the objects locked are small.  When you program happens to use a larger value, the locking suddenly fails.&lt;pre&gt;&lt;br /&gt;Object o = &lt;br /&gt;Integer lock = o.hashCode() &amp; 255;&lt;br /&gt;synchronized(lock)  { // DON'T do this either.&lt;br /&gt;&lt;/pre&gt;This could look like a clever way to have locks for all objects which are equal.  However, its very brittle and obtuse and you could find your program fails unexpectedly in ways which are difficult to reproduce e.g. depending on whether you have use &lt;i&gt;-XX:+AggressiveOpts&lt;/i&gt; If you have more than one library or section of code which does this, you could get bizarre deadlocks between unrelated code.&lt;p/&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/#svn%2Ftrunk%2Fsrc%2Ftest%2Fjava%2Fcom%2Fgoogle%2Fcode%2Fjava%2Fcore%2Fautoboxing"&gt;&lt;h3&gt;The code&lt;/h3&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-799118654358966309?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/799118654358966309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/surprising-results-of-autoboxing.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/799118654358966309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/799118654358966309'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/surprising-results-of-autoboxing.html' title='Surprising results of autoboxing'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6362552746168851753</id><published>2012-01-12T15:01:00.001Z</published><updated>2012-01-22T19:37:34.767Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Java Thread Affinity supports groups of threads.</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The &lt;a href="https://github.com/peter-lawrey/Java-Thread-Affinity"&gt;Java Thread Affinity Library&lt;/a&gt; version 1.3, supports assigning groups of threads together by Socket, Core, or a custom strategy.&lt;p/&gt;&lt;h2&gt;Determining the grouping of threads&lt;/h2&gt;The following &lt;a href="https://github.com/peter-lawrey/Java-Thread-Affinity/blob/master/src/test/java/vanilla/java/affinity/AffinityLockBindMain.java"&gt;Affinity Lock binding example&lt;/a&gt;, shows how you can choose to take either different sockets or cores, or share the same sockets or cores.&lt;p/&gt;It creates a thread lock for "main".  For the reader and writer threads it tries to get a different socket or core to "main", and reserve a cpu on the same core or socket as each other.&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;AffinityLock al = AffinityLock.acquireLock();&lt;br /&gt;try {&lt;br /&gt;    // find a cpu on a different socket, otherwise a different core.&lt;br /&gt;    AffinityLock readerLock = al.acquireLock(DIFFERENT_SOCKET, DIFFERENT_CORE);&lt;br /&gt;    new Thread(new SleepRunnable(readerLock), "reader").start();&lt;br /&gt;    // find a cpu on the same core, or the same socket, or any free cpu.&lt;br /&gt;    AffinityLock writerLock = readerLock.acquireLock(SAME_CORE, SAME_SOCKET, ANY);&lt;br /&gt;    new Thread(new SleepRunnable(writerLock), "writer").start();&lt;br /&gt;    Thread.sleep(200);&lt;br /&gt;} finally {&lt;br /&gt;    al.release();&lt;br /&gt;}&lt;br /&gt;// re-use the same cpu for the engine.&lt;br /&gt;new Thread(new SleepRunnable(al), "engine").start();&lt;br /&gt;&lt;/pre&gt;When this runs you can see that &lt;i&gt;reader&lt;/i&gt; gets cpu 6 which is on a different core to &lt;i&gt;main&lt;/i&gt; on cpu 7, however &lt;i&gt;writer&lt;/i&gt; is on cpu 2 which is another thread on the same core as &lt;i&gt;reader&lt;/i&gt;.&lt;pre&gt;&lt;br /&gt;Jan 12, 2012 2:58:56 PM vanilla.java.affinity.AffinityLock bind&lt;br /&gt;INFO: Assigning cpu 7 to Thread[main,5,main]&lt;br /&gt;Jan 12, 2012 2:58:56 PM vanilla.java.affinity.AffinityLock bind&lt;br /&gt;INFO: Assigning cpu 6 to Thread[reader,5,main]&lt;br /&gt;Jan 12, 2012 2:58:56 PM vanilla.java.affinity.AffinityLock bind&lt;br /&gt;INFO: Assigning cpu 2 to Thread[writer,5,main]&lt;br /&gt;Jan 12, 2012 2:58:56 PM vanilla.java.affinity.AffinityLock release&lt;br /&gt;INFO: Releasing cpu 7 from Thread[main,5,main]&lt;br /&gt;Jan 12, 2012 2:58:56 PM vanilla.java.affinity.AffinityLock bind&lt;br /&gt;INFO: Assigning cpu 7 to Thread[engine,5,main]&lt;br /&gt;&lt;br /&gt;The assignment of CPUs is&lt;br /&gt;0: General use CPU&lt;br /&gt;1: General use CPU&lt;br /&gt;2: Thread[writer,5,main] alive=true&lt;br /&gt;3: Reserved for this application&lt;br /&gt;4: General use CPU&lt;br /&gt;5: General use CPU&lt;br /&gt;6: Thread[reader,5,main] alive=true&lt;br /&gt;7: Thread[engine,5,main] alive=true&lt;br /&gt;&lt;br /&gt;Jan 12, 2012 2:58:57 PM vanilla.java.affinity.AffinityLock release&lt;br /&gt;INFO: Releasing cpu 6 from Thread[reader,5,main]&lt;br /&gt;Jan 12, 2012 2:58:57 PM vanilla.java.affinity.AffinityLock release&lt;br /&gt;INFO: Releasing cpu 2 from Thread[writer,5,main]&lt;br /&gt;Jan 12, 2012 2:58:57 PM vanilla.java.affinity.AffinityLock release&lt;br /&gt;INFO: Releasing cpu 7 from Thread[engine,5,main]&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6362552746168851753?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6362552746168851753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-thread-affinity-supports-groups-of.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6362552746168851753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6362552746168851753'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-thread-affinity-supports-groups-of.html' title='Java Thread Affinity supports groups of threads.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5618350196664614365</id><published>2012-01-10T14:04:00.000Z</published><updated>2012-01-22T19:31:40.786Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Generating every combination without duplicates</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Generating every combination where there is no duplicates is pretty simple.  Handling the situation where there can be more than one value which is the same is trickier.&lt;p/&gt;&lt;h2&gt;The problem&lt;/h2&gt;In this problem you have a list, with duplicates. e.g. [1, 1, 2, 3, 3, 3]  Find all the combinations of this list, is a way which doesn't create any duplicates. e.g. if you swap the 1s around, its the same list.&lt;p/&gt;You can do this with brute force by creating every combination and adding them to a Set to remove duplicates.  The Set grows with the number of solutions.  You can avoid the need to do this, by using a strategy to generate all possible lists which don't result in duplicates.&lt;p/&gt;&lt;h2&gt;A solution&lt;/h2&gt;When building a collection to describe the problem all elements which are the same are equal and the order doesn't matter, only the number of times that element appears. e.g. 2 of 1, 1 of 2, 3 of 3.&lt;p/&gt;This collection can also be used to determine how many of each time is still left.  For the first number there is only three possibilities, 1, 2, 3 (not six if you were to use brute force)  If you choice a 1, there is still three possibilities because you can still have another 1.  After you choice 1 again, there is only two possibilities as there can only be one 2, and three 3's left.&lt;p/&gt;In this post, I use a recursion and a Bag which keep a count of the values remaining.  This ensures the number of options for an element is the number of unique values which have no appeared already.&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;import java.util.*;&lt;br /&gt;import java.util.concurrent.atomic.AtomicInteger;&lt;br /&gt;&lt;br /&gt;public class Main {&lt;br /&gt;    public static void main(String... args) {&lt;br /&gt;        Bag&amp;lt;Integer&gt; b = new Bag&amp;lt;&gt;();&lt;br /&gt;        b.countFor(1, 2);&lt;br /&gt;        b.countFor(2, 1);&lt;br /&gt;        b.countFor(3, 3);&lt;br /&gt;        Set&amp;lt;String&gt; set = new LinkedHashSet&amp;lt;&gt;();&lt;br /&gt;        for (List&amp;lt;Integer&gt; list : b.combinations()) {&lt;br /&gt;            System.out.println(list);&lt;br /&gt;            String s = list.toString();&lt;br /&gt;            if (!set.add(s))&lt;br /&gt;                System.err.println("Duplicate entry " + s);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Bag&amp;lt;E&gt; {&lt;br /&gt;    final Map&amp;lt;E, AtomicInteger&gt; countMap = new LinkedHashMap&amp;lt;&gt;();&lt;br /&gt;&lt;br /&gt;    void countFor(E e, int n) {&lt;br /&gt;        countMap.put(e, new AtomicInteger(n));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void decrement(E e) {&lt;br /&gt;        AtomicInteger ai = countMap.get(e);&lt;br /&gt;        if (ai.decrementAndGet() &amp;lt; 1)&lt;br /&gt;            countMap.remove(e);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void increment(E e) {&lt;br /&gt;        AtomicInteger ai = countMap.get(e);&lt;br /&gt;        if (ai == null)&lt;br /&gt;            countMap.put(e, new AtomicInteger(1));&lt;br /&gt;        else&lt;br /&gt;            ai.incrementAndGet();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    List&amp;lt;List&amp;lt;E&gt;&gt; combinations() {&lt;br /&gt;        List&amp;lt;List&amp;lt;E&gt;&gt; ret = new ArrayList&amp;lt;&gt;();&lt;br /&gt;        List&amp;lt;E&gt; current = new ArrayList&amp;lt;&gt;();&lt;br /&gt;        combinations0(ret, current);&lt;br /&gt;        return ret;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void combinations0(List&amp;lt;List&amp;lt;E&gt;&gt; ret, List&amp;lt;E&gt; current) {&lt;br /&gt;        if (countMap.isEmpty()) {&lt;br /&gt;            ret.add(new ArrayList&amp;lt;E&gt;(current));&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;        int position = current.size();&lt;br /&gt;        current.add(null);&lt;br /&gt;        List&amp;lt;E&gt; es = new ArrayList&amp;lt;&gt;(countMap.keySet());&lt;br /&gt;        if (es.get(0) instanceof Comparable)&lt;br /&gt;            Collections.sort((List) es);&lt;br /&gt;        for (E e : es) {&lt;br /&gt;            current.set(position, e);&lt;br /&gt;            decrement(e);&lt;br /&gt;            combinations0(ret, current);&lt;br /&gt;            increment(e);&lt;br /&gt;        }&lt;br /&gt;        current.remove(position);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;[1, 1, 2, 3, 3, 3]&lt;br /&gt;[1, 1, 3, 2, 3, 3]&lt;br /&gt;[1, 1, 3, 3, 2, 3]&lt;br /&gt;[1, 1, 3, 3, 3, 2]&lt;br /&gt;[1, 2, 1, 3, 3, 3]&lt;br /&gt;[1, 2, 3, 1, 3, 3]&lt;br /&gt;[1, 2, 3, 3, 1, 3]&lt;br /&gt;[1, 2, 3, 3, 3, 1]&lt;br /&gt;[1, 3, 1, 2, 3, 3]&lt;br /&gt;[1, 3, 1, 3, 2, 3]&lt;br /&gt;[1, 3, 1, 3, 3, 2]&lt;br /&gt;[1, 3, 2, 1, 3, 3]&lt;br /&gt;[1, 3, 2, 3, 1, 3]&lt;br /&gt;[1, 3, 2, 3, 3, 1]&lt;br /&gt;[1, 3, 3, 1, 2, 3]&lt;br /&gt;[1, 3, 3, 1, 3, 2]&lt;br /&gt;[1, 3, 3, 2, 1, 3]&lt;br /&gt;[1, 3, 3, 2, 3, 1]&lt;br /&gt;[1, 3, 3, 3, 1, 2]&lt;br /&gt;[1, 3, 3, 3, 2, 1]&lt;br /&gt;[2, 1, 1, 3, 3, 3]&lt;br /&gt;[2, 1, 3, 1, 3, 3]&lt;br /&gt;[2, 1, 3, 3, 1, 3]&lt;br /&gt;[2, 1, 3, 3, 3, 1]&lt;br /&gt;[2, 3, 1, 1, 3, 3]&lt;br /&gt;[2, 3, 1, 3, 1, 3]&lt;br /&gt;[2, 3, 1, 3, 3, 1]&lt;br /&gt;[2, 3, 3, 1, 1, 3]&lt;br /&gt;[2, 3, 3, 1, 3, 1]&lt;br /&gt;[2, 3, 3, 3, 1, 1]&lt;br /&gt;[3, 1, 1, 2, 3, 3]&lt;br /&gt;[3, 1, 1, 3, 2, 3]&lt;br /&gt;[3, 1, 1, 3, 3, 2]&lt;br /&gt;[3, 1, 2, 1, 3, 3]&lt;br /&gt;[3, 1, 2, 3, 1, 3]&lt;br /&gt;[3, 1, 2, 3, 3, 1]&lt;br /&gt;[3, 1, 3, 1, 2, 3]&lt;br /&gt;[3, 1, 3, 1, 3, 2]&lt;br /&gt;[3, 1, 3, 2, 1, 3]&lt;br /&gt;[3, 1, 3, 2, 3, 1]&lt;br /&gt;[3, 1, 3, 3, 1, 2]&lt;br /&gt;[3, 1, 3, 3, 2, 1]&lt;br /&gt;[3, 2, 1, 1, 3, 3]&lt;br /&gt;[3, 2, 1, 3, 1, 3]&lt;br /&gt;[3, 2, 1, 3, 3, 1]&lt;br /&gt;[3, 2, 3, 1, 1, 3]&lt;br /&gt;[3, 2, 3, 1, 3, 1]&lt;br /&gt;[3, 2, 3, 3, 1, 1]&lt;br /&gt;[3, 3, 1, 1, 2, 3]&lt;br /&gt;[3, 3, 1, 1, 3, 2]&lt;br /&gt;[3, 3, 1, 2, 1, 3]&lt;br /&gt;[3, 3, 1, 2, 3, 1]&lt;br /&gt;[3, 3, 1, 3, 1, 2]&lt;br /&gt;[3, 3, 1, 3, 2, 1]&lt;br /&gt;[3, 3, 2, 1, 1, 3]&lt;br /&gt;[3, 3, 2, 1, 3, 1]&lt;br /&gt;[3, 3, 2, 3, 1, 1]&lt;br /&gt;[3, 3, 3, 1, 1, 2]&lt;br /&gt;[3, 3, 3, 1, 2, 1]&lt;br /&gt;[3, 3, 3, 2, 1, 1]&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5618350196664614365?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5618350196664614365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/generating-every-combination-without.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5618350196664614365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5618350196664614365'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/generating-every-combination-without.html' title='Generating every combination without duplicates'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6794006040521490903</id><published>2012-01-09T11:58:00.001Z</published><updated>2012-01-22T19:31:40.800Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Project Euler</title><content type='html'>&lt;a href="http://projecteuler.net/about"&gt;Project Euler&lt;/a&gt; has a good list of interesting puzzles to solve for any language.  I worked on a quite a few at one point but haven't for a while until someone mentioned &lt;a href="http://projecteuler.net/problem=303"&gt;Problem 303&lt;/a&gt;&lt;p/&gt;I suggest you try a few if you haven't already &lt;a href="http://projecteuler.net/problems"&gt;Project Euler Problems&lt;/a&gt;.&lt;p/&gt;For extra difficulty you can try to make the program shorter, or faster. e.g. My solution to Problem 303 runs in 1.524 seconds solving all values (without guessing)  When you solve a problem you can look at how some people solved the problem in different languages which is pretty cool IMHO.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6794006040521490903?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6794006040521490903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/project-euler.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6794006040521490903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6794006040521490903'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/project-euler.html' title='Project Euler'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4990321768957666432</id><published>2012-01-09T09:00:00.001Z</published><updated>2012-01-26T15:15:47.243Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Generic class names to avoid</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Java (Oracle Java update 2) has many classes with the same generic name.  To avoid further confusion, I suggest avoiding these names if you can.&lt;h2&gt;Most repeated&lt;/h2&gt;The following class names are repeated,      19 Handler,      16 Messages,      13 Util,      10 Element,       8 Attribute,       7 SecuritySupport,       7 Node,       6 Provider,       6 Header,       6 FactoryFinder,       6 Document.      5 SOAPBinding,       5 Repository,       5 Ref,       5 ORB,       5 Name,       5 Constants,       5 Connection,       5 Comment,       5 Binding,       5 Attributes, &lt;br/&gt;This excludes the Apache XML library which repeats many names. If you include these libraries there are 26 classes called SecuritySupport.&lt;p/&gt;&lt;h2&gt;Four times&lt;/h2&gt;       Window,        Version,        Utility,        Timer,        Text,        State,        Signature,        ServiceName,        ServiceConfigurationError,        Service,        ResourceLoader,        Queue,        Policy,        Parser,        Operation,        NativeLibLoader,        Message,        Label,        JSObject,        GetPropertyAction,        FactoryFinder$ConfigurationError,        Event,        ConstantPool,        AppletAudioClip,        Action, &lt;p/&gt;&lt;h2&gt;Three times&lt;/h2&gt;       XMLWriter,        Wrapper,        WildcardTypeImpl,        Visitor,        Validator,        Types,        TypeMismatch,        TypeInfo,        Type,        Trace,        Token,        Timestamp,        Target,        Symbol,        StyleSheet,        SOAPFault,        SOAPConstants,        Scope,        Schema,        ResourceManager,        Resource,        Resolver,        Request,        Reference,        Properties,        ProgressMonitor,        PrincipalImpl,        Principal,        Port,        PooledConnection,        Pool,        Pipe,        Patcher,        ParseException,        OutputStream,        ObjectStreamField,        Navigator,        NamespaceSupport$Context,        NamespaceSupport,        MimeType,        MemoryCache,        MarshalException,        Manifest,        Main,        Location,        List,        JarVerifier,        IOR,        Invoker,        InvalidName,        Introspector,        InputStream,        Import,        ImageCache,        HTMLDocument,        HTMLCollection,        Headers,        FinalArrayList,        Filter,        FileSystem,        FactoryImpl,        Extension,        EventListener,        ErrorHandler,        Entity,        EncryptedPrivateKeyInfo,        Delegate,        DataSource,        CurrentOperations,        CurrentHelper,        Current,        Counter,        Context,        ContentType,        Config,        Code,        CharacterData,        Certificate,        CacheTable,        Cache,        Bridge,        Base64,        Authenticator,        AttributeList,        ArrayType,        Array,        AppletAudioClip$1,        Annotation, &lt;p/&gt;&lt;h2&gt;Appearing twice&lt;/h2&gt;Too many to mention.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4990321768957666432?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4990321768957666432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/generic-class-names-to-avoid.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4990321768957666432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4990321768957666432'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/generic-class-names-to-avoid.html' title='Generic class names to avoid'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2719130855758323372</id><published>2012-01-05T12:12:00.001Z</published><updated>2012-01-26T15:15:47.233Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Top Java Article of 2011</title><content type='html'>If you google &lt;a href="http://www.google.co.uk/search?q=Top%20Java%20Article%20of%202011"&gt;Top Java Article of 2011&lt;/a&gt; the first site it matches is an interesting web site &lt;a href="http://www.mkyong.com/featured/top-20-java-websites/"&gt;Top 20 Java Websites&lt;/a&gt; and the first article is a mirror an &lt;a href="http://vanillajava.blogspot.com/2011/05/how-to-get-c-like-performance-in-java.html"&gt;article&lt;/a&gt; from this blog &lt;a href="http://java.dzone.com/news/how-get-c-performance-java"&gt;How to get C like performance in Java&lt;/a&gt;. BTW: If you do it multiple times the order changes sometimes. Perhaps it hits different servers?&lt;p/&gt;I am sure its just a matter of using the right combination of words to search for, but I think its pretty cool. ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2719130855758323372?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2719130855758323372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/top-java-article-of-2011.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2719130855758323372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2719130855758323372'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/top-java-article-of-2011.html' title='Top Java Article of 2011'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5654384580413018157</id><published>2012-01-05T11:30:00.001Z</published><updated>2012-01-22T19:31:40.790Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>String.valueOf(int) vs "" + int</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;There are a number of reason prefer either&lt;p /&gt;&lt;pre&gt;int i = ...&lt;br /&gt;String s = "" + i;&lt;br /&gt;String s = String.valueOf(i);&lt;br /&gt;&lt;/pre&gt;&lt;p /&gt;These include&lt;br /&gt;&lt;ul&gt;&lt;li&gt;simplicity&lt;/li&gt;&lt;li&gt;clarity&lt;/li&gt;&lt;li&gt;efficiency&lt;/li&gt;&lt;li&gt;performance&lt;/li&gt;&lt;/ul&gt;&lt;p/&gt;Personally I prefer efficiency for the developer as the performance difference is very, very small.  IMHO, &lt;tt&gt;"" + i&lt;/tt&gt; is also simpler and clearer, but that is a matter of taste.&lt;p/&gt;&lt;h2&gt;Comparing the performance difference&lt;/h2&gt;&lt;pre&gt;&lt;br /&gt;public static void main(String... args) throws IOException {&lt;br /&gt;    for (int i = 0; i &lt; 3; i++) {&lt;br /&gt;        long svo = perfStringValueOf();&lt;br /&gt;        long qqp = perfQuoteQuotePlus();&lt;br /&gt;        System.out.printf("String.valueOf took an average of %.3f us and \"\"+ took an average of %.3f us%n", svo / 1e3, qqp / 1e3);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static long perfStringValueOf() {&lt;br /&gt;    long start = System.nanoTime();&lt;br /&gt;    final int runs = 100000;&lt;br /&gt;    String s;&lt;br /&gt;    for (int i = 0; i &lt; runs; i++) {&lt;br /&gt;        s = String.valueOf(i * i);&lt;br /&gt;        // ensure s is not optimised away&lt;br /&gt;        if (s.length() &lt; 1) throw new AssertionError();&lt;br /&gt;    }&lt;br /&gt;    long time = System.nanoTime() - start;&lt;br /&gt;    return time / runs;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static long perfQuoteQuotePlus() {&lt;br /&gt;    long start = System.nanoTime();&lt;br /&gt;    final int runs = 100000;&lt;br /&gt;    String s;&lt;br /&gt;    for (int i = 0; i &lt; runs; i++) {&lt;br /&gt;        s = "" + i * i;&lt;br /&gt;        // ensure s is not optimised away&lt;br /&gt;        if (s.length() &lt; 1) throw new AssertionError();&lt;br /&gt;    }&lt;br /&gt;    long time = System.nanoTime() - start;&lt;br /&gt;    return time / runs;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;prints&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;String.valueOf took an average of 0.140 us and ""+ took an average of 0.243 us&lt;br /&gt;String.valueOf took an average of 0.063 us and ""+ took an average of 0.058 us&lt;br /&gt;String.valueOf took an average of 0.044 us and ""+ took an average of 0.058 us&lt;br /&gt;&lt;/pre&gt;This suggest that using &lt;tt&gt;String.valueOf&lt;/tt&gt; will save 0.014 micro-seconds.  However, using &lt;tt&gt;"" + &lt;/tt&gt; will save you, the developer far, far more than that in time. (possibly a million times over)&lt;p/&gt;As I have mentioned in previous article, if performance is really critical, you are better off writing the number as text to the direct ByteBuffer which will be written to the device where the text will be going.  This creates no objects at all and is clearly OTT for 99% of use cases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5654384580413018157?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5654384580413018157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/stringvalueofint-vs-int.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5654384580413018157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5654384580413018157'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/stringvalueofint-vs-int.html' title='String.valueOf(int) vs &quot;&quot; + int'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6623478726224212927</id><published>2012-01-04T09:32:00.001Z</published><updated>2012-01-26T15:16:51.863Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>An odd case of initialization</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;You might assume that once a variable has been initialized it stays that way.  However, the javac compiler, treats a variable as initialized only when it can determine a variable has been set, and exception handling can confuse the compiler.&lt;p/&gt;&lt;h2&gt;But I know its initialised because I used it&lt;/h2&gt;In the following example, a variable is treated as initialized but after a catch block, the compiler isn't sure, and the variable can assigned again and used later.&lt;pre&gt;&lt;br /&gt;int a;&lt;br /&gt;try {&lt;br /&gt;    a = 1;&lt;br /&gt;    // a is initialised and can be read.&lt;br /&gt;    System.out.println(a); // compiles ok.&lt;br /&gt;} catch (RuntimeException ignored) {&lt;br /&gt;}&lt;br /&gt;// a is not considered initialised as the compiler &lt;br /&gt;// doesn't know the catch block couldn't be thrown before a is set.&lt;br /&gt;System.out.println(a); // Variable 'a' might not have been initialized&lt;br /&gt;&lt;br /&gt;a = 2;&lt;br /&gt;// a is definitely initialised.&lt;br /&gt;System.out.println(a); // compiles ok.&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;The problem here is that you know that the variable cannot throw an exception before the variable a is set, but the compiler doesn't know this.  The simplest solution is to move the initialization out of the try/catch block.&lt;p/&gt;Note: If you make the variable a final, the second a = 2 gets an error "Variable 'a' might have been initialized"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6623478726224212927?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6623478726224212927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/odd-case-of-initialization.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6623478726224212927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6623478726224212927'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/odd-case-of-initialization.html' title='An odd case of initialization'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-391859864345328413</id><published>2012-01-03T10:31:00.000Z</published><updated>2012-01-22T19:31:40.761Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java Puzzler, double chars</title><content type='html'>&lt;h2&gt;A teaser which uses char and double&lt;/h2&gt;The following compiles and produces an output. Can you explain why?&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;char ch = 'A';&lt;br /&gt;ch *= 1.5;&lt;br /&gt;System.out.println(ch); // prints 'a'&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;Here is a hint for a simpler example.&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;byte b = 100;&lt;br /&gt;b /= 2.5;&lt;br /&gt;System.out.println(b); // prints 40&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-391859864345328413?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/391859864345328413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-puzzler-double-chars.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/391859864345328413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/391859864345328413'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/java-puzzler-double-chars.html' title='Java Puzzler, double chars'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3483415680567982377</id><published>2012-01-02T18:11:00.001Z</published><updated>2012-01-22T19:34:51.489Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Regex vs IndexOf in Java.</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The author of these articles &lt;a href="http://omegacoder.com/?p=324"&gt;Are C# .Net Regular Expressions Fast Enough for You?&lt;/a&gt; and &lt;a href="http://omegacoder.com/?p=850"&gt;.Net Regex: Can Regular Expression Parsing be Faster than XmlDocument or Linq to Xml?&lt;/a&gt; recently pointed out to me that he had found that Regular expressions were at least as fast or faster than the alternatives in C#.  However it has been my experience that regular expressions in Java were slower.  It is hard for me to say why this might be different in Java and C# or even if these are fair comparisons but here is what I found in Java.&lt;h2&gt;Searching XML for the start of a field&lt;/h2&gt;This test searches for the expression "&lt;url&gt;\\s*&lt;loc&gt;" in short section of text.&lt;pre&gt;&lt;br /&gt;Performing 1 loops, regex took 323.389 us and indexOf took 73.026 us on average, ratio=4.4&lt;br /&gt;Performing 10 loops, regex took 61.513 us and indexOf took 42.480 us on average, ratio=1.4&lt;br /&gt;Performing 100 loops, regex took 84.899 us and indexOf took 8.134 us on average, ratio=10.4&lt;br /&gt;Performing 1,000 loops, regex took 16.307 us and indexOf took 5.851 us on average, ratio=2.8&lt;br /&gt;Performing 10,000 loops, regex took 3.751 us and indexOf took 1.321 us on average, ratio=2.8&lt;br /&gt;Performing 100,000 loops, regex took 3.586 us and indexOf took 1.260 us on average, ratio=2.8&lt;br /&gt;&lt;/pre&gt;Using indexOf is somewhat faster, but more complex to code. You would only optimise this example if you really needed to as even one million searches takes a fraction of a second.&lt;p/&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/regex/RegexTestOne.java"&gt;&lt;h3&gt;Code for Search XML example&lt;/h3&gt;&lt;/a&gt;&lt;p/&gt;&lt;h2&gt;Searching for a value= expression in a short string&lt;/h2&gt;This test search for the {value} in value="{value}" of a short string.&lt;pre&gt;&lt;br /&gt;Performing 1 loops, regex took 227.029 us and indexOf took 9.387 us on average, ratio=24.2&lt;br /&gt;Performing 10 loops, regex took 11.141 us and indexOf took 1.195 us on average, ratio=9.3&lt;br /&gt;Performing 100 loops, regex took 9.631 us and indexOf took 1.108 us on average, ratio=8.7&lt;br /&gt;Performing 1,000 loops, regex took 14.993 us and indexOf took 2.491 us on average, ratio=6.0&lt;br /&gt;Performing 10,000 loops, regex took 2.472 us and indexOf took 0.254 us on average, ratio=9.7&lt;br /&gt;Performing 100,000 loops, regex took 0.583 us and indexOf took 0.097 us on average, ratio=6.0&lt;br /&gt;Performing 100,000 loops, regex took 0.465 us and indexOf took 0.032 us on average, ratio=14.5&lt;br /&gt;Performing 100,000 loops, regex took 0.467 us and indexOf took 0.032 us on average, ratio=14.6&lt;br /&gt;&lt;/pre&gt;Since the times keep improving even after 100K iterations, I suspect the JIT is able to optimise indexOf more than the relatively complex code supporting regular expressions.&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/regex/RegexTestTwo.java"&gt;&lt;h3&gt;Code for Searching a short string example&lt;/h3&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3483415680567982377?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3483415680567982377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2012/01/regex-vs-indexof-in-java.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3483415680567982377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3483415680567982377'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2012/01/regex-vs-indexof-in-java.html' title='Regex vs IndexOf in Java.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2337136185472182532</id><published>2011-12-31T19:04:00.000Z</published><updated>2012-01-26T15:17:51.385Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>Happy New Year all</title><content type='html'>Thank you everyone who read my blog, especially those who gave feedback.  It encourages me to write me more.&lt;p/&gt;I hope everyone has a Happy New Year.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2337136185472182532?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2337136185472182532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/happy-new-year-all.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2337136185472182532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2337136185472182532'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/happy-new-year-all.html' title='Happy New Year all'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6759323258609583735</id><published>2011-12-30T12:54:00.000Z</published><updated>2012-01-22T19:34:51.561Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Using a memory mapped file for a huge matrix</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Matrices can be really large, sometimes larger than you can hold in one array.  You can extend the maximum size by having multiple arrays however this can make your heap size really large and inefficient.  An alternative is to use a wrapper over a memory mapped file.  The advantage of memory mapped files is that they have very little impact on the heap and can be swapped in and out by the OS fairly transparently.&lt;p/&gt;&lt;h2&gt;A huge matrix&lt;/h2&gt;This code supports large matrices of double.  It partitions the file into 1 GB mappings. (As Java doesn't support mappings of 2 GB or more at a time, a pet hate of mine ;)&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;import sun.misc.Cleaner;&lt;br /&gt;import sun.nio.ch.DirectBuffer;&lt;br /&gt;&lt;br /&gt;import java.io.Closeable;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.RandomAccessFile;&lt;br /&gt;import java.nio.MappedByteBuffer;&lt;br /&gt;import java.nio.channels.FileChannel;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;public class LargeDoubleMatrix implements Closeable {&lt;br /&gt;    private static final int MAPPING_SIZE = 1 &lt;&lt; 30;&lt;br /&gt;    private final RandomAccessFile raf;&lt;br /&gt;    private final int width;&lt;br /&gt;    private final int height;&lt;br /&gt;    private final List&lt;MappedByteBuffer&gt; mappings = new ArrayList&lt;MappedByteBuffer&gt;();&lt;br /&gt;&lt;br /&gt;    public LargeDoubleMatrix(String filename, int width, int height) throws IOException {&lt;br /&gt;        this.raf = new RandomAccessFile(filename, "rw");&lt;br /&gt;        try {&lt;br /&gt;            this.width = width;&lt;br /&gt;            this.height = height;&lt;br /&gt;            long size = 8L * width * height;&lt;br /&gt;            for (long offset = 0; offset &lt; size; offset += MAPPING_SIZE) {&lt;br /&gt;                long size2 = Math.min(size - offset, MAPPING_SIZE);&lt;br /&gt;                mappings.add(raf.getChannel().map(FileChannel.MapMode.READ_WRITE, offset, size2));&lt;br /&gt;            }&lt;br /&gt;        } catch (IOException e) {&lt;br /&gt;            raf.close();&lt;br /&gt;            throw e;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected long position(int x, int y) {&lt;br /&gt;        return (long) y * width + x;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int width() {&lt;br /&gt;        return width;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int height() {&lt;br /&gt;        return height;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public double get(int x, int y) {&lt;br /&gt;        assert x &gt;= 0 &amp;&amp; x &lt; width;&lt;br /&gt;        assert y &gt;= 0 &amp;&amp; y &lt; height;&lt;br /&gt;        long p = position(x, y) * 8;&lt;br /&gt;        int mapN = (int) (p / MAPPING_SIZE);&lt;br /&gt;        int offN = (int) (p % MAPPING_SIZE);&lt;br /&gt;        return mappings.get(mapN).getDouble(offN);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void set(int x, int y, double d) {&lt;br /&gt;        assert x &gt;= 0 &amp;&amp; x &lt; width;&lt;br /&gt;        assert y &gt;= 0 &amp;&amp; y &lt; height;&lt;br /&gt;        long p = position(x, y) * 8;&lt;br /&gt;        int mapN = (int) (p / MAPPING_SIZE);&lt;br /&gt;        int offN = (int) (p % MAPPING_SIZE);&lt;br /&gt;        mappings.get(mapN).putDouble(offN, d);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void close() throws IOException {&lt;br /&gt;        for (MappedByteBuffer mapping : mappings)&lt;br /&gt;            clean(mapping);&lt;br /&gt;        raf.close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void clean(MappedByteBuffer mapping) {&lt;br /&gt;        if (mapping == null) return;&lt;br /&gt;        Cleaner cleaner = ((DirectBuffer) mapping).cleaner();&lt;br /&gt;        if (cleaner != null) cleaner.clean();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class LargeDoubleMatrixTest {&lt;br /&gt;    @Test&lt;br /&gt;    public void getSetMatrix() throws IOException {&lt;br /&gt;        long start = System.nanoTime();&lt;br /&gt;        final long used0 = usedMemory();&lt;br /&gt;        LargeDoubleMatrix matrix = new LargeDoubleMatrix("ldm.test", 1000 * 1000, 1000 * 1000);&lt;br /&gt;        for (int i = 0; i &lt; matrix.width(); i++)&lt;br /&gt;            matrix.set(i, i, i);&lt;br /&gt;        for (int i = 0; i &lt; matrix.width(); i++)&lt;br /&gt;            assertEquals(i, matrix.get(i, i), 0.0);&lt;br /&gt;        long time = System.nanoTime() - start;&lt;br /&gt;        final long used = usedMemory() - used0;&lt;br /&gt;        if (used == 0)&lt;br /&gt;            System.err.println("You need to use -XX:-UsedTLAB to see small changes in memory usage.");&lt;br /&gt;        System.out.printf("Setting the diagonal took %,d ms, Heap used is %,d KB%n", time / 1000 / 1000, used / 1024);&lt;br /&gt;        matrix.close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private long usedMemory() {&lt;br /&gt;        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;With the following test, which writes to each of the diagonal values of a one million * one million matrix. This is too large to hope to create on the heap.&lt;pre&gt;&lt;br /&gt;Setting the diagonal took 314,819 ms, Heap used is 2,025 KB&lt;br /&gt;&lt;br /&gt;$ ls -l ldm.test&lt;br /&gt;-rw-rw-r-- 1 peter peter 8000000000000 2011-12-30 12:42 ldm.test&lt;br /&gt;$ du -s ldm.test &lt;br /&gt;4010600 ldm.test&lt;br /&gt;&lt;/pre&gt;That's 8,000,000,000,000 bytes or ~7.3 TB in virtual memory, in a Java process!  This works because it only allocates or pages in the pages which you use. So while the file size is almost 8 TB, the actual disk space and memory used is 4 GB.&lt;p/&gt;With a more modest file size of 100K * 100K matrix you see something like the following. Its still an 80 GB matrix, which uses trivial heap space. ;)&lt;pre&gt;&lt;br /&gt;Setting the diagonal took 110 ms, Heap used is 71 KB&lt;br /&gt;&lt;br /&gt;$ ls -l ldm.test&lt;br /&gt;-rw-rw-r-- 1 peter peter 80000000000 2011-12-30 12:49 ldm.test&lt;br /&gt;$ du -s ldm.test &lt;br /&gt;400000 ldm.test&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6759323258609583735?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6759323258609583735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/using-memory-mapped-file-for-huge.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6759323258609583735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6759323258609583735'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/using-memory-mapped-file-for-huge.html' title='Using a memory mapped file for a huge matrix'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1325489942128510297</id><published>2011-12-29T11:38:00.001Z</published><updated>2012-01-22T19:29:23.860Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Thread Affinity library for Java supports JNA</title><content type='html'>Java Thread Affinity library 1.1&lt;p/&gt;BegemoT has provided same code to allow the Thread Affinity library can use JNA if its available.  This means you don't have to have the JNI library.&lt;p/&gt;The latest version is available &lt;a href="https://github.com/peter-lawrey/Java-Thread-Affinity"&gt;HERE&lt;/a&gt;  Click on the ZIP button to download the whole thing as a zip file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1325489942128510297?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1325489942128510297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java_29.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1325489942128510297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1325489942128510297'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java_29.html' title='Thread Affinity library for Java supports JNA'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3909258619738596190</id><published>2011-12-27T15:42:00.002Z</published><updated>2012-01-22T19:37:34.752Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>What skills should a Core Java Developer have?</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;I have been trying to put together a list of basic skills a Java developer should have to move on to being an advanced Core Java programmer.&lt;p /&gt;&lt;h2&gt;Skills&lt;/h2&gt;You;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;can write code on paper which has a good chance of compiling.&lt;/li&gt;&lt;li&gt;can use a debugger to debug programs and profile an application.&lt;/li&gt;&lt;li&gt;are familiar all the primitives types and operators in Java.&lt;/li&gt;&lt;li&gt;understands the class loading process and how class loaders work&lt;/li&gt;&lt;li&gt;can use multiple threads both correctly and can prove this improve performance or behaviour. e.g. wait/notify/notifyAll, SwingUtils.invokeLater, the concurrency library&lt;/li&gt;&lt;li&gt;can use checked exceptions, generics and enums&lt;/li&gt;&lt;li&gt;can time a small benchmark and get reproducible results&lt;/li&gt;&lt;li&gt;can write a very simple client server TCP service&lt;/li&gt;&lt;li&gt;have an understanding of garbage collection, when is it triggered, what can you do to minimise it&lt;/li&gt;&lt;li&gt;understand when to use design patterns such as Singleton, Factory, Fly-weight, Builder, Object Pool, Iterator, Strategy, Visitor, Composite&lt;li&gt;&lt;/ul&gt;&lt;h2&gt;Suggestions on how to get these skills&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;read Java Concurrency in Practice (&lt;a href="http://jcip.net/"&gt;http://jcip.net/&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;write a simple client server TCP service such as chat&lt;/li&gt;&lt;li&gt;read up on Design Patterns and try to use them. &lt;a href="http://www.oodesign.com/"&gt;http://www.oodesign.com/&lt;/a&gt; so you can learn when they help and don't help&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3909258619738596190?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3909258619738596190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/what-skills-should-core-java-developer.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3909258619738596190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3909258619738596190'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/what-skills-should-core-java-developer.html' title='What skills should a Core Java Developer have?'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1566383074245703881</id><published>2011-12-22T13:38:00.002Z</published><updated>2012-01-22T19:31:40.753Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Solution: What is this broken code doing</title><content type='html'>Following my earlier &lt;a href="http://vanillajava.blogspot.com/2011/12/what-is-this-broken-code-doing.html"&gt;blog&lt;/a&gt;, here is my solutions to these puzzles.&lt;p/&gt;&lt;h2&gt;Loop every second value&lt;/h2&gt;&lt;pre&gt;&lt;br /&gt;List&lt;Integer&gt; list = new ArrayList&amp;lt;&gt;();&lt;br /&gt;for (int i = 0; i &amp;lt; 10; i++) list.add(i);&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &amp;lt; list.size(); i++) {&lt;br /&gt;    System.out.println(list.get(i));&lt;br /&gt;    list.remove(i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;When you call remove(i) it shifts all the elements down one AND i++ shifts the index up one.  This means, you see every second value.&lt;p/&gt;A work around is as follows.&lt;pre&gt;&lt;br /&gt;while(!list.isEmpty) &lt;br /&gt;    System.out.println(list.remove(0));&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Endless loop&lt;/h2&gt;This prints all the characters which have value&lt;pre&gt;&lt;br /&gt;for(char ch = Character.MIN_VALUE; ch&lt;= Character.MAX_VALUE; ch++) {&lt;br /&gt;    int i = Character.getNumericValue(ch);&lt;br /&gt;    if (i &gt;= 0)&lt;br /&gt;        System.out.println("char "+ch + ' ' + (int) ch+" = "+i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;As many realised, this doesn't stop because a char is always less than or equals to the maximum value. (Which is why its called the maximum ;)&lt;p/&gt; Some suggested avoiding this difficult value and have the loop iterate one less.  However, another approach is to use a do/while loop which most developers don't use much AFAIK.&lt;pre&gt;&lt;br /&gt;char ch = Character.MIN_VALUE;&lt;br /&gt;do {&lt;br /&gt;    int i = Character.getNumericValue(ch);&lt;br /&gt;    if (i &lt; 0) continue;&lt;br /&gt;    System.out.println("char "+ch + ' ' + (int) ch+" = "+i);&lt;br /&gt;} while(ch++ &lt; Character.MAX_VALUE) &lt;br /&gt;&lt;/pre&gt;The difference is that the check is at the end of the loop instead of the start.  This means its stops after ch = MAX_VALUE instead of before it iterates with this value.&lt;p/&gt;&lt;h2&gt;What am I waiting for?&lt;/h2&gt;This "program" deadlocks.  The main method is optional ;)&lt;pre&gt;&lt;br /&gt;class Main {&lt;br /&gt;    static int value;&lt;br /&gt;    &lt;br /&gt;    static {&lt;br /&gt;        final Thread t = new Thread() {&lt;br /&gt;            @Override&lt;br /&gt;            public void run() {&lt;br /&gt;                value = 1; // attempts to set Main.value&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;        t.start();&lt;br /&gt;        System.out.println("Dead locking");&lt;br /&gt;        try {&lt;br /&gt;            t.join();&lt;br /&gt;        } catch (InterruptedException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;        System.out.println("Released");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The problem here is that class initialization is single threaded and implicitly locked.  This means another thread cannot use or access the class or its fields or method while another thread is initialising it. Using pseudo-Java it looks like this.&lt;pre&gt;&lt;br /&gt;class Main {&lt;br /&gt;    static int value;&lt;br /&gt;    &lt;br /&gt;    static {&lt;br /&gt;      // synchronized(Main.class) {&lt;br /&gt;        final Thread t = new Thread() {&lt;br /&gt;            @Override&lt;br /&gt;            public void run() {&lt;br /&gt;             // deadlocks as the thread initialising Main has not finished.&lt;br /&gt;             // synchronized(Main.class) { &lt;br /&gt;                value = 1; // attempts to set Main.value&lt;br /&gt;             // }&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;        t.start();&lt;br /&gt;        System.out.println("Dead locking");&lt;br /&gt;        try {&lt;br /&gt;            t.join();&lt;br /&gt;        } catch (InterruptedException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;        System.out.println("Released");&lt;br /&gt;      // }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1566383074245703881?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1566383074245703881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/solution-what-is-this-broken-code-doing.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1566383074245703881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1566383074245703881'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/solution-what-is-this-broken-code-doing.html' title='Solution: What is this broken code doing'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-429084662772951183</id><published>2011-12-21T09:22:00.000Z</published><updated>2012-01-22T19:31:40.773Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>What is this broken code doing</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Here are some examples of broken code. I find the interesting to understand what they don't do what they appear to.&lt;p/&gt;Can you work out why these don't work? ;)&lt;p/&gt;&lt;h2&gt;Loop every second value&lt;/h2&gt;&lt;pre&gt;&lt;br /&gt;List&lt;Integer&gt; list = new ArrayList&amp;lt;&gt;();&lt;br /&gt;for (int i = 0; i &amp;lt; 10; i++) list.add(i);&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &amp;lt; list.size(); i++) {&lt;br /&gt;    System.out.println(list.get(i));&lt;br /&gt;    list.remove(i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;0&lt;br /&gt;2&lt;br /&gt;4&lt;br /&gt;6&lt;br /&gt;8&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;&lt;h2&gt;Endless loop&lt;/h2&gt;This prints all the characters which have value&lt;pre&gt;&lt;br /&gt;for(char ch = Character.MIN_VALUE; ch&lt;= Character.MAX_VALUE; ch++) {&lt;br /&gt;    int i = Character.getNumericValue(ch);&lt;br /&gt;    if (i &gt;= 0)&lt;br /&gt;        System.out.println("char "+ch + ' ' + (int) ch+" = "+i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;However it doesn't stop.  Can you change the code to use a do/while loop so that every char is considered but it does stop? (Without using a larger type)&lt;p/&gt;&lt;h2&gt;What am I waiting for?&lt;/h2&gt;This "program" deadlocks.  The main method is optional ;)&lt;pre&gt;&lt;br /&gt;class Main {&lt;br /&gt;    static int value;&lt;br /&gt;    &lt;br /&gt;    static {&lt;br /&gt;        final Thread t = new Thread() {&lt;br /&gt;            @Override&lt;br /&gt;            public void run() {&lt;br /&gt;                value = 1;&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;        t.start();&lt;br /&gt;        System.out.println("Dead locking");&lt;br /&gt;        try {&lt;br /&gt;            t.join();&lt;br /&gt;        } catch (InterruptedException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;        System.out.println("Released");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Can you see why it deadlocks?&lt;p/&gt;The last two puzzles are based on puzzles from &lt;a href="http://www.javapuzzlers.com/"&gt;Java Puzzlers by Joshua Bloch and Neal Gafter&lt;/a&gt;  If you liked these, you will love this book. ;)&lt;p&gt;&lt;a href="http://vanillajava.blogspot.com/2011/12/solution-what-is-this-broken-code-doing.html"&gt;&lt;h2&gt;Sample Solutions&lt;/h2&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-429084662772951183?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/429084662772951183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/what-is-this-broken-code-doing.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/429084662772951183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/429084662772951183'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/what-is-this-broken-code-doing.html' title='What is this broken code doing'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4195914531122808290</id><published>2011-12-19T18:55:00.000Z</published><updated>2012-01-22T19:31:40.769Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Solutions: Testing an Anagram of a Palindrome</title><content type='html'>There are many solutions to this &lt;a href="http://vanillajava.blogspot.com/2011/12/java-interview-question-anagram-of.html"&gt;problem&lt;/a&gt;.  However, it is made simpler if you determine the number of letter with an odd number occurrences. As long as the text has no more than 1 odd numbered letter, you can make a palindrome from it.&lt;p/&gt;A straight forward solution&lt;pre&gt;&lt;br /&gt;public static boolean isPalindromeAnagram(String text) {&lt;br /&gt;    BitSet bs = new BitSet(27);&lt;br /&gt;    for (int i = 0; i &lt; text.length(); i++) {&lt;br /&gt;        char ch = text.charAt(i);&lt;br /&gt;        if (('A' &lt;= ch &amp;&amp; ch &lt;= 'Z') || ('a' &lt;= ch &amp;&amp; ch &lt;= 'z'))&lt;br /&gt;            bs.flip(ch % 32);&lt;br /&gt;    }&lt;br /&gt;    return bs.cardinality() &lt;= 1;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;A trickier solution&lt;pre&gt;&lt;br /&gt;public static boolean isPalindromeAnagram(String text) {&lt;br /&gt;    int count = 0;&lt;br /&gt;    for (int i = 0; i &lt; text.length(); i++) {&lt;br /&gt;        char ch = text.charAt(i);&lt;br /&gt;        if (ch + Integer.MIN_VALUE - 'A' &lt;= 'z' + Integer.MIN_VALUE - 'A')&lt;br /&gt;            count ^= 1 &lt;&lt; ch;&lt;br /&gt;    }&lt;br /&gt;    return Integer.bitCount(count % (1 &lt;&lt; 'z') &amp; ~1) &lt;= 1;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4195914531122808290?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4195914531122808290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/solutions-testing-anagram-of-palindrome.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4195914531122808290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4195914531122808290'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/solutions-testing-anagram-of-palindrome.html' title='Solutions: Testing an Anagram of a Palindrome'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7024918433222230730</id><published>2011-12-15T15:32:00.000Z</published><updated>2012-01-22T19:34:51.569Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>synchronized is slower but not worth worrying about</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Often developer jump through hoops to avoid synchronization.  There are justifications like; the application does lots of writes or reads. Without a clear idea of what "lots" means, they have no idea whether the optimisations they are using will help or just add complexity (and possibly make it slower)&lt;p/&gt;&lt;h2&gt;Vector is slower than ArrayList, but that's not a good reason to avoid it&lt;/h2&gt;I prefer to use lock free objects and collections in a single threaded context.  This is more for clarity than performance.  It makes it obvious this code was designed to be single threaded.  The performance difference by comparison is often trivial.&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;public static void main(String... args) throws IOException {&lt;br /&gt;    for (int i = 0; i &lt; 5; i++) {&lt;br /&gt;        perfTest(new ArrayList&lt;Integer&gt;());&lt;br /&gt;        perfTest(new Vector&lt;Integer&gt;());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static void perfTest(List&lt;Integer&gt; objects) {&lt;br /&gt;    long start = System.nanoTime();&lt;br /&gt;    final int runs = 100000000;&lt;br /&gt;    for (int i = 0; i &lt; runs; i += 20) {&lt;br /&gt;        // add items.&lt;br /&gt;        for (int j = 0; j &lt; 20; j+=2)&lt;br /&gt;            objects.add(i);&lt;br /&gt;        // remove from the end.&lt;br /&gt;        while (!objects.isEmpty())&lt;br /&gt;            objects.remove(objects.size() - 1);&lt;br /&gt;    }&lt;br /&gt;    long time = System.nanoTime() - start;&lt;br /&gt;    System.out.printf("%s each add/remove took an average of %.1f ns%n", objects.getClass().getSimpleName(),  (double) time/runs);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;ArrayList each add/remove took an average of 3.0 ns&lt;br /&gt;Vector each add/remove took an average of 38.5 ns&lt;br /&gt;ArrayList each add/remove took an average of 2.0 ns&lt;br /&gt;Vector each add/remove took an average of 4.4 ns&lt;br /&gt;ArrayList each add/remove took an average of 2.4 ns&lt;br /&gt;Vector each add/remove took an average of 4.6 ns&lt;br /&gt;ArrayList each add/remove took an average of 2.0 ns&lt;br /&gt;Vector each add/remove took an average of 4.6 ns&lt;br /&gt;ArrayList each add/remove took an average of 2.3 ns&lt;br /&gt;Vector each add/remove took an average of 4.5 ns&lt;br /&gt;&lt;/pre&gt;Using Vector is several times slower, and if all you application does is access the Vector it would make sense to use an ArrayList (and be glad you only have a trivial program to write)  For real-world applications, a number of operations are needed and the cost of any one of these is relatively small.&lt;p/&gt;The difference in time is only 2 ns (possibly more on some systems).  If you have a task which takes a micro-second (called one million times per second) that operation will take 0.5% slower.  If you have an operation which is used only 100,000 times per second, you might find you can't even measure the difference.&lt;p/&gt;In summary, don't worry about performance problems until you have measured the difference you believe it would make. Otherwise you can waste a lot of time "optimising" something which won't make any difference or worse, is slower but you don't know it. (Due to the added complexity in "optimising" the solution)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7024918433222230730?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7024918433222230730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/synchronized-is-slower-but-not-worth.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7024918433222230730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7024918433222230730'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/synchronized-is-slower-but-not-worth.html' title='synchronized is slower but not worth worrying about'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3550107167302969270</id><published>2011-12-13T15:18:00.004Z</published><updated>2012-01-26T15:17:51.393Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>DZone adds page view summary.</title><content type='html'>DZone have added page views to the summary of articles an individual has posted.  &lt;a href="http://java.dzone.com/users/peterlawrey-0"&gt;My articles on DZone&lt;/a&gt; This is interesting to me as the articles which are most popular on blogger and are not the same as those on DZone. (A factor for 2 one way or the other in many cases)&lt;p/&gt;Its is also interesting that the total number of pages views is currently 173K compared with on blogger its 163K page views. (Surprisingly similar)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3550107167302969270?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3550107167302969270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/dzone-add-page-view-summary.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3550107167302969270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3550107167302969270'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/dzone-add-page-view-summary.html' title='DZone adds page view summary.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3962562691354969687</id><published>2011-12-13T11:28:00.003Z</published><updated>2012-01-22T19:31:40.765Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java Interview Question; Anagram of a Palindrome</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;In many interview questions, what they are looking for is a simple solution to an apparently complex problem.  Unfortunately, the solutions are usually obvious if you know the solution, but very hard to come up with in an interview situation. ;)&lt;p/&gt;&lt;h2&gt;Anagram of Palindrome&lt;/h2&gt;Write a method to test if a String is an anagram of a palindrome.  The method should have O(n) time complexity and O(1) space complexity.  You can assume all letters are between ' ' (space) and 'z'.  Assume only letters matter and case is ignored.&lt;p/&gt;e.g.&lt;br/&gt;"kayak"&lt;br/&gt;"Rats live on no evil star"&lt;br/&gt;"A man, a plan, a canal, Panama"&lt;br/&gt;"Doc, note: I dissent. A fast never prevents a fatness. I diet on cod."&lt;br/&gt;&lt;p/&gt;&lt;h2&gt;The solution&lt;/h2&gt;A brute force approach is to generate anagrams and test if they are a palindromes.  This is not required. All you need to test is if the String is the sort of string which can be turned into a palindrome.&lt;p/&gt;Sample solution available &lt;a href="http://vanillajava.blogspot.com/2011/12/solutions-testing-anagram-of-palindrome.html"&gt;HERE&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3962562691354969687?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3962562691354969687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/java-interview-question-anagram-of.html#comment-form' title='33 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3962562691354969687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3962562691354969687'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/java-interview-question-anagram-of.html' title='Java Interview Question; Anagram of a Palindrome'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>33</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1264663349322823264</id><published>2011-12-13T08:16:00.001Z</published><updated>2012-01-22T19:37:34.732Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Thread Affinity library for Java.</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Locking critical thread to a CPU can improve throughput and reduce latency.  It can make a big difference to 99%, 99.9% and 99.99%tile latencies. &lt;p/&gt;Unfortunately there is no standard calls in the JDK to do this, so I wrote a simple library so you can manage and see how CPUs have been assigned.&lt;p/&gt;&lt;h2&gt;What does it look like running?&lt;/h2&gt;In the following example, there are four threads main, reader, writer and engine.  The main thread finishes before the engine starts so they end up using the same CPU.&lt;pre&gt;&lt;br /&gt;Estimated clock frequency was 3400 MHz&lt;br /&gt;Assigning cpu 7 to Thread[main,5,main]&lt;br /&gt;Assigning cpu 6 to Thread[reader,5,main]&lt;br /&gt;Assigning cpu 3 to Thread[writer,5,main]&lt;br /&gt;Releasing cpu 7 from Thread[main,5,main]&lt;br /&gt;Assigning cpu 7 to Thread[engine,5,main]&lt;br /&gt;&lt;br /&gt;The assignment of CPUs is&lt;br /&gt;0: General use CPU&lt;br /&gt;1: General use CPU&lt;br /&gt;2: Reserved for this application&lt;br /&gt;3: Thread[writer,5,main] alive=true&lt;br /&gt;4: General use CPU&lt;br /&gt;5: General use CPU&lt;br /&gt;6: Thread[reader,5,main] alive=true&lt;br /&gt;7: Thread[engine,5,main] alive=true&lt;br /&gt;&lt;br /&gt;Releasing cpu 6 from Thread[reader,5,main]&lt;br /&gt;Releasing cpu 3 from Thread[writer,5,main]&lt;br /&gt;Releasing cpu 7 from Thread[engine,5,main]&lt;br /&gt;&lt;/pre&gt;The code which produces this looks like&lt;pre&gt;&lt;br /&gt;public class AffinitySupportMain {&lt;br /&gt;    public static void main(String... args) {&lt;br /&gt;        AffinityLock al = AffinityLock.acquireLock();&lt;br /&gt;        try {&lt;br /&gt;            new Thread(new SleepRunnable(), "reader").start();&lt;br /&gt;            new Thread(new SleepRunnable(), "writer").start();&lt;br /&gt;            new Thread(new SleepRunnable(), "engine").start();&lt;br /&gt;        } finally {&lt;br /&gt;            al.release();&lt;br /&gt;        }&lt;br /&gt;        System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static class SleepRunnable implements Runnable {&lt;br /&gt;        public void run() {&lt;br /&gt;            AffinityLock al = AffinityLock.acquireLock();&lt;br /&gt;            try {&lt;br /&gt;                Thread.sleep(1000);&lt;br /&gt;            } catch (InterruptedException e) {&lt;br /&gt;            } finally {&lt;br /&gt;                al.release();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This library has been tested on Linux, and I believe it can be adapted to Windows and other OSes.&lt;p/&gt;&lt;a href="https://github.com/peter-lawrey/Java-Thread-Affinity"&gt;The Java Thread Affinity Library&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1264663349322823264?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1264663349322823264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java.html#comment-form' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1264663349322823264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1264663349322823264'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java.html' title='Thread Affinity library for Java.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6956750651679303500</id><published>2011-12-07T12:26:00.001Z</published><updated>2012-01-22T19:31:40.804Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java Puzzle operator confusion</title><content type='html'>Why does this &lt;pre&gt;&lt;br /&gt;int _=1, __=2;&lt;br /&gt;int j = __ ^_^ __, k = __-- -+- _ -+- --__;&lt;br /&gt;System.out.println(j + " " + k);&lt;br /&gt;&lt;/pre&gt;print the following?&lt;pre&gt;&lt;br /&gt;1 3&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6956750651679303500?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6956750651679303500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/java-puzzle-operator-confusion.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6956750651679303500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6956750651679303500'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/java-puzzle-operator-confusion.html' title='Java Puzzle operator confusion'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4806718572929614055</id><published>2011-12-06T08:25:00.001Z</published><updated>2012-01-22T19:31:40.777Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java puzzle System.exit and locks.</title><content type='html'>When you call System.exit() it will stop the execution of the thread at that point and not call any finally blocks.  &lt;pre&gt;&lt;br /&gt;private static final Object lock = new Object();&lt;br /&gt;&lt;br /&gt;public static void main(String... args) {&lt;br /&gt;    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {&lt;br /&gt;        @Override&lt;br /&gt;        public void run() {&lt;br /&gt;            System.out.println("Locking");&lt;br /&gt;            synchronized (lock) {&lt;br /&gt;                System.out.println("Locked");&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }));&lt;br /&gt;    synchronized (lock) {&lt;br /&gt;        System.exit(0);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;What does this program print?&lt;p/&gt;Replace System.exit(0) with Thread.currentThread().stop() and run again for comparison.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4806718572929614055?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4806718572929614055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/java-puzzle-systemexit-and-locks.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4806718572929614055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4806718572929614055'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/java-puzzle-systemexit-and-locks.html' title='Java puzzle System.exit and locks.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-8962888128015937793</id><published>2011-12-05T14:53:00.001Z</published><updated>2012-01-26T15:21:28.874Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>Test a complete failure of the JVM</title><content type='html'>Say you want to test that your application behaves correctly on restart even after the application crashes.  One approach is to trigger a crash in test code and check that data is in a correctable state on restart.&lt;pre&gt;&lt;br /&gt;Unsafe unsafe = getUnsafe(); // use reflection&lt;br /&gt;unsafe.setMemory(0, 1, (byte) 0);&lt;br /&gt;&lt;/pre&gt;This triggers a SIGSEGV&lt;pre&gt;&lt;br /&gt;#&lt;br /&gt;# A fatal error has been detected by the Java Runtime Environment:&lt;br /&gt;#&lt;br /&gt;#  SIGSEGV (0xb) at pc=0x00000032b967ae09, pid=17870, tid=1082034496&lt;br /&gt;#&lt;br /&gt;# JRE version: 7.0_01-b08&lt;br /&gt;# Java VM: Java HotSpot(TM) 64-Bit Server VM (21.1-b02 mixed mode linux-amd64 compressed oops)&lt;br /&gt;# Problematic frame:&lt;br /&gt;# C  [libc.so.6+0x7ae09]  memset+0x9&lt;br /&gt;#&lt;br /&gt;&lt;/pre&gt;If your tests still pass, you can be reasonably confident it is recoverable even on a complete failure of the JVM.&lt;p/&gt;&lt;h3&gt;For the code for getUnsafe().&lt;/h3&gt;&lt;p/&gt;&lt;b&gt;Warning:&lt;/b&gt; This class is appropriately named and misuse can result in a crash of the JVM. It can also change in future versions (It is more likely new methods will be added rather than removed)&lt;pre&gt;&lt;br /&gt;public static Unsafe getUnsafe() {&lt;br /&gt;    try {&lt;br /&gt;        Field field = Unsafe.class.getDeclaredField("theUnsafe");&lt;br /&gt;        field.setAccessible(true);&lt;br /&gt;        return (Unsafe) field.get(null);&lt;br /&gt;    } catch (Exception e) {&lt;br /&gt;        throw new AssertionError(e);&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-8962888128015937793?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/8962888128015937793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/12/test-complete-failure-of-jvm.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8962888128015937793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8962888128015937793'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/12/test-complete-failure-of-jvm.html' title='Test a complete failure of the JVM'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1336873475348796954</id><published>2011-11-28T20:45:00.001Z</published><updated>2012-01-22T19:31:40.750Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java puzzle, low latency queue</title><content type='html'>There a number of ways to use queues. A simple and very fast queue is to use AtomicReference. (It stores 0 or 1 element)&lt;p/&gt;1. Write a producer and consumer thread which communicates via an AtomicReference. &lt;script type="text/javascript" language="JavaScript"&gt;&lt;!--function InsertContent(tid) {if(document.getElementById(tid).style.display == "none") { document.getElementById(tid).style.display = ""; }else { document.getElementById(tid).style.display = "none"; }}//--&gt;&lt;/script&gt;&lt;a href="javascript:InsertContent('q1');"&gt;[Click for sample solution]&lt;/a&gt;&lt;div    id="q1"    style="display: none"&gt;&lt;hr/&gt;&lt;blockquote&gt;Took an average of 48 ns per object&lt;/blockquote&gt;&lt;pre&gt;&lt;br /&gt;public class Main {&lt;br /&gt;    public static void main(String... args) throws InterruptedException {&lt;br /&gt;        AtomicReference&amp;lt;Long&gt; queue = new AtomicReference&amp;lt;Long&gt;();&lt;br /&gt;        final Consumer&amp;lt;Long&gt; consumer = new Consumer&amp;lt;Long&gt;(queue);&lt;br /&gt;        Thread t = new Thread(new Runnable() {&lt;br /&gt;            @Override&lt;br /&gt;            public void run() {&lt;br /&gt;                while(consumer.take() &gt;= 0);&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;        t.start();&lt;br /&gt;&lt;br /&gt;        Producer&amp;lt;Long&gt; producer = new Producer&amp;lt;Long&gt;(queue);&lt;br /&gt;&lt;br /&gt;        long start = System.nanoTime();&lt;br /&gt;        int runs = 10*1000*1000;&lt;br /&gt;        for(long i=0;i&amp;lt;runs;i++)&lt;br /&gt;            producer.push(i);&lt;br /&gt;        producer.push(-1L); // poison pill&lt;br /&gt;        t.join();&lt;br /&gt;        long time = System.nanoTime() - start;&lt;br /&gt;        System.out.printf("Took an average of %,d ns per object%n", time/runs);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Producer&amp;lt;T&gt; {&lt;br /&gt;    final AtomicReference&amp;lt;T&gt; queue;&lt;br /&gt;&lt;br /&gt;    public Producer(AtomicReference&amp;lt;T&gt; queue) {&lt;br /&gt;        this.queue = queue;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void push(T l) {&lt;br /&gt;        while (!queue.compareAndSet(null, l)) ;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Consumer&amp;lt;T&gt; {&lt;br /&gt;    final AtomicReference&amp;lt;T&gt; queue;&lt;br /&gt;&lt;br /&gt;    public Consumer(AtomicReference&amp;lt;T&gt; queue) {&lt;br /&gt;        this.queue = queue;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public T take() {&lt;br /&gt;        T t;&lt;br /&gt;        do {&lt;br /&gt;            t = queue.getAndSet(null);&lt;br /&gt;        } while(t == null);&lt;br /&gt;        return t;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;hr/&gt;&lt;/div&gt;&lt;p/&gt;2. Have the consumer send messages back to the producer using another AtomicReference. [left as an exercise] &lt;br/&gt;The average round trip time taken was 156 ns if you have one message at a time, or 98 ns if you have two messages at a time.&lt;p/&gt;3. Time the throughput for one second repeatedly.  What variation do you see?&lt;p/&gt;4. Pad the AtomicReference to make sure they are at least 64 bytes apart in memory and measure again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1336873475348796954?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1336873475348796954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/java-puzzle-low-latency-queue.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1336873475348796954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1336873475348796954'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/java-puzzle-low-latency-queue.html' title='Java puzzle, low latency queue'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-8477281711178701616</id><published>2011-11-28T18:45:00.001Z</published><updated>2012-01-22T19:29:23.878Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Low Latency Slides</title><content type='html'>Last weekend was LJC Open Conference #4, and like many people I got a lot out of it.&lt;p/&gt;My talk was up first which meant I could relax for the rest of the day.&lt;p/&gt;Here are the slides&lt;iframe src="https://docs.google.com/present/embed?id=dc5w8383_1g4rfgvhr&amp;size=m" frameborder="0" width="555" height="451"&gt;&lt;/iframe&gt;&lt;p/&gt;Note: the message size was 16 longs or 128 bytes.  This makes a difference at higher throughputs.&lt;p/&gt;In answer to @aix's questions&lt;blockquote&gt;On slide 12; what are we measuring here, elapsed time from the message hitting the buffer to the "echo" reply showing up on the client socket?&lt;/blockquote&gt;In each message I add a timestamp as it is written. When each message is read, I compare the timestamp with the current time. I sort the results and take the middle / 50%tile as typical timings and the worst 0.01% as the 99.99%tile.&lt;blockquote&gt;What's causing the large difference between "nanoTime(), Normal" and "RDTSC, Normal" in the bottom half of the slide (2M/s)?&lt;/blockquote&gt;The reason for taking the RDTSC directly (9 ns) is that System.nanoTime() is quite slow on Centos 5.7 (180 ns) and the later is a system calls which may disturb the cache.  At modest message rate 200K/s (one message every 5000 ns) the difference is minor however as the message rates increase 2M/s (one message every 500 ns) the addition to latency is significant.  Its not possible to send messages over 5 M/s if I was using System.nanoTime() where as with RDTSC I got up to 12 M/s. Without timing each message, I got a throughput of 17 M/s.In answer to @Matt's questions&lt;blockquote&gt;Is that a safe way to call tsc on a multicore machine?  Is it consistent across cores?&lt;/blockquote&gt;Calling RDTSC on a multi-core system is safe as there is one counter per socket.  However, calling TSC on a multi-socket system is not safe and there will be difference and possibly a drift between sockets.&lt;p/&gt;This is not a problem if you have only one socket, or you do all you timing on one socket. e.g. You have used thread affinity and know the timings will all be on the same socket.&lt;blockquote&gt;Don't you need some sort of serialisation in the instruction stream to avoid out of order behaviour?&lt;/blockquote&gt;This is a potential problem. However, the total time taken with JNI is around 9 ns which is more than 40 instructions.  This is longer than the CPU pipeline can re-order. (typically around 32 instructions) If this instruction were embedded the way the some Unsafe methods are, it could be re-ordered with Java instruction.  However, provided this re-ordering is not random, the difference is likely to be a bias of &lt;&lt; 10 ns. If the re-ordering was random this could add up to 10 ns jitter.&lt;p/&gt;Given I am timing latencies to an accuracy of 100 ns, I decided it wasn't a problem for me.  It could be a problem if you want 10 ns accuracy.&lt;blockquote&gt;On the "reproducible results" theme, to be completely anal you need to repeat the test n times (20-30?) and examine the distribution of results. &lt;/blockquote&gt;What I do is repeatedly run the test for 5 seconds and print the results.  This will consist of a minimum of one million individual messages.  This is repeated 30 times and I print an aggregate distribution.  I compare the individual distributions with the aggregate to see if they are "close".  &lt;p/&gt;I will try to document how the test are done in more detail when I am happy with the reproducibility of the 99.99%tile values. :|&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-8477281711178701616?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/8477281711178701616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/low-latency-slides.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8477281711178701616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8477281711178701616'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/low-latency-slides.html' title='Low Latency Slides'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7085663225386775806</id><published>2011-11-25T08:47:00.001Z</published><updated>2012-01-22T19:34:51.578Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Ever decreasing cost of main memory</title><content type='html'>I have blogged about the relative cost of memory to the cost of your time.  Memory in servers is so cheap that for small amounts of memory, it just isn't worth your time to introduce complexity into your application to try to save it.&lt;p/&gt;The average salary for a developer in the UK is £40,000 and the average cost of memory is £5 per GB.  The cost to your organisation for both is higher and if you have many machines saving a 1 MB on 1000 machines saves 1 GB, however memory is so divisible you can quickly run into small amounts of memory which are not worth your time saving.&lt;p/&gt;Hard disk space is even cheaper and most people get its not worth keeping your disks completely clean all the time, because the cost of deleting a file you later need is high, but also the value of the space you save is not worth your time.  A typical 2 TB of mirrored disk in a network appliance costs about £300.&lt;table&gt;&lt;tr&gt;&lt;th&gt;Your time&lt;/th&gt;&lt;th&gt;Main memory to save in total&lt;/th&gt;&lt;th&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Disk space to save&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Blink of an eye (20 ms)&lt;/td&gt;&lt;td align="right"&gt;20 KB&lt;/td&gt;&lt;td align="right"&gt;1.7 MB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;One second&lt;/td&gt;&lt;td align="right"&gt;1 MB&lt;/td&gt;&lt;td align="right"&gt;33 MB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;One line of tested code (2 mins)&lt;/td&gt;&lt;td align="right"&gt;120 MB&lt;/td&gt;&lt;td align="right"&gt;3.5 GB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;A small sized well tested &lt;br/&gt;library, 100 lines (0.5 days)&lt;/td&gt;&lt;td align="right"&gt;14 GB&lt;/td&gt;&lt;td align="right"&gt;500 GB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;A medium sized well tested, &lt;br/&gt;documented library, 1000 lines (1 week)&lt;/td&gt;&lt;td align="right"&gt;140 GB&lt;/td&gt;&lt;td align="right"&gt;5 TB&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p/&gt;For self learning, interest or fun you might think about ways of saving small amounts of memory or disk.  But for work, the most efficient way to program may be to save your time and those who have to maintain your code, and waste some hardware resources in the process. BTW: hardware resources are more re-usable than your time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7085663225386775806?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7085663225386775806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/ever-decreasing-cost-of-main-memory.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7085663225386775806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7085663225386775806'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/ever-decreasing-cost-of-main-memory.html' title='Ever decreasing cost of main memory'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-8900023199307409615</id><published>2011-11-23T10:54:00.001Z</published><updated>2012-01-22T19:34:51.596Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Stupid performance trick in Java</title><content type='html'>ByteBuffer has a compact() method which is useful for re-using a buffer if it is not full consumed.  However, in the likely case it is consumed, it can perform surprising badly.&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;while (in.read(buf) &gt;= 0 || buf.position != 0) {&lt;br /&gt;     buf.flip();&lt;br /&gt;     out.write(buf);&lt;br /&gt;     buf.compact();    // In case of partial write&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;In my application, the throughput increased by 6% by replacing compact() with this method.&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;public static void compact(ByteBuffer bb) {&lt;br /&gt;    if (bb.remaining() == 0)&lt;br /&gt;        bb.clear();&lt;br /&gt;    else&lt;br /&gt;        bb.compact();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;Note: this is not the increase in a micro-benchmark, but across the entire application!&lt;p/&gt;Your Mileage May Vary of course&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-8900023199307409615?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/8900023199307409615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/stupid-performance-trick-in-java.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8900023199307409615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8900023199307409615'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/stupid-performance-trick-in-java.html' title='Stupid performance trick in Java'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1085409287992235412</id><published>2011-11-22T08:39:00.001Z</published><updated>2012-01-22T19:31:40.745Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java puzzle (Single threaded client server)</title><content type='html'>Without creating additional threads, create a ServerSocket on a random unused port, a client Socket connecting to localhost and a server Socket.&lt;p/&gt;Part 1) Send messages from client to server and back again. (This can be useful in unit tests)&lt;script type="text/javascript" language="JavaScript"&gt;&lt;!--function InsertContent(tid) {if(document.getElementById(tid).style.display == "none") { document.getElementById(tid).style.display = ""; }else { document.getElementById(tid).style.display = "none"; }}//--&gt;&lt;/script&gt;&lt;a href="javascript:InsertContent('c1');"&gt;[Click for sample solution]&lt;/a&gt;&lt;div    id="c1"    style="display: none"&gt;&lt;hr/&gt;&lt;pre&gt;&lt;br /&gt;ServerSocket ss = new ServerSocket(0);&lt;br /&gt;Socket c = new Socket("localhost", ss.getLocalPort());&lt;br /&gt;Socket s= ss.accept();&lt;br /&gt;ss.close();&lt;br /&gt;// sends one byte.&lt;br /&gt;c.getOutputStream().write(1);&lt;br /&gt;int num = s.getInputStream().read();&lt;br /&gt;s.getOutputStream().write(num+1);&lt;br /&gt;int num2 = c.getInputStream().read();&lt;br /&gt;&lt;br /&gt;s.close();&lt;br /&gt;c.close();&lt;br /&gt;&lt;/pre&gt;&lt;hr/&gt;&lt;/div&gt;&lt;p/&gt;Part 2) Do the same with blocking NIO.&lt;a href="javascript:InsertContent('c2');"&gt;[Click for sample solution]&lt;/a&gt;&lt;div    id="c2"    style="display: none"&gt;&lt;hr/&gt;&lt;pre&gt;&lt;br /&gt;ServerSocketChannel ss = ServerSocketChannel.open();&lt;br /&gt;ss.socket().bind(new InetSocketAddress(0));&lt;br /&gt;SocketChannel c = SocketChannel.open(new InetSocketAddress("localhost", ss.socket().getLocalPort()));&lt;br /&gt;SocketChannel s = ss.accept();&lt;br /&gt;ss.close();&lt;br /&gt;// sends one byte.&lt;br /&gt;ByteBuffer bb1 = ByteBuffer.allocateDirect(1);&lt;br /&gt;c.write(bb1);&lt;br /&gt;// read one byte.&lt;br /&gt;ByteBuffer bb2 = ByteBuffer.allocateDirect(1);&lt;br /&gt;int num = s.read(bb2);&lt;br /&gt;&lt;br /&gt;// sends it back.&lt;br /&gt;bb2.flip();&lt;br /&gt;s.write(bb2);&lt;br /&gt;&lt;br /&gt;// reads one byte.&lt;br /&gt;bb1.clear();&lt;br /&gt;c.read(bb1);&lt;br /&gt;&lt;br /&gt;s.close();&lt;br /&gt;c.close();&lt;br /&gt;&lt;/pre&gt;&lt;hr/&gt;&lt;/div&gt;&lt;p/&gt;Part 3) Benchmark how many GB/s per second you can transfer this way.&lt;a href="javascript:InsertContent('c3');"&gt;[Click for sample solution]&lt;/a&gt;&lt;div    id="c3"    style="display: none"&gt;&lt;hr/&gt;&lt;pre&gt;&lt;br /&gt;ServerSocketChannel ss = ServerSocketChannel.open();&lt;br /&gt;ss.socket().bind(new InetSocketAddress(0));&lt;br /&gt;SocketChannel c = SocketChannel.open(new InetSocketAddress("localhost", ss.socket().getLocalPort()));&lt;br /&gt;SocketChannel s = ss.accept();&lt;br /&gt;ss.close();&lt;br /&gt;&lt;br /&gt;final int bufferSize = 64 * 1024;&lt;br /&gt;final int runs = 10000;&lt;br /&gt;&lt;br /&gt;for (int j = 0; j &lt; 3; j++) {&lt;br /&gt;    ByteBuffer bb1 = ByteBuffer.allocateDirect(bufferSize);&lt;br /&gt;    ByteBuffer bb2 = ByteBuffer.allocateDirect(bufferSize);&lt;br /&gt;    long start = System.nanoTime();&lt;br /&gt;    for (int i = 0; i &lt; runs; i++) {&lt;br /&gt;// sends one buffer.&lt;br /&gt;        bb1.clear();&lt;br /&gt;        c.write(bb1);&lt;br /&gt;// read one buffer.&lt;br /&gt;        bb2.clear();&lt;br /&gt;        int num = s.read(bb2);&lt;br /&gt;&lt;br /&gt;// sends it back.&lt;br /&gt;        bb2.flip();&lt;br /&gt;        s.write(bb2);&lt;br /&gt;&lt;br /&gt;// reads one byte.&lt;br /&gt;        bb1.clear();&lt;br /&gt;        c.read(bb1);&lt;br /&gt;    }&lt;br /&gt;    long time = System.nanoTime() - start;&lt;br /&gt;    long rate = (long) (1e9 * bufferSize * runs / time / 1e6);&lt;br /&gt;    System.out.println("Transfer rate " + rate + " MB/s");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;s.close();&lt;br /&gt;c.close();&lt;br /&gt;&lt;/pre&gt;Prints on my machine&lt;pre&gt;&lt;br /&gt;Transfer rate 1963 MB/s&lt;br /&gt;Transfer rate 2330 MB/s&lt;br /&gt;Transfer rate 2365 MB/s&lt;br /&gt;&lt;/pre&gt;&lt;hr/&gt;&lt;/div&gt;&lt;p/&gt;Part 4) Measure the typical and 99.99% round trip latency, and estimate how much garbage is produced.&lt;p/&gt;For bonus points try the same with Async NIO2 in Java 7.&lt;p/&gt;I will add a solution Nov 29th (after a week)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1085409287992235412?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1085409287992235412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/java-puzzle-single-threaded-client.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1085409287992235412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1085409287992235412'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/java-puzzle-single-threaded-client.html' title='Java puzzle (Single threaded client server)'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6125533716460796771</id><published>2011-11-22T08:22:00.001Z</published><updated>2012-01-22T19:31:40.794Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java puzzle (Sum of even Fibonacci numbers)</title><content type='html'>Write a function which calculates the sum of even Fibonacci numbers.&lt;pre&gt;&lt;br /&gt;public static void main(String... args) {&lt;br /&gt;    for(int i=1;i&lt;22;i++)&lt;br /&gt;        System.out.print(sumEvenFibonacci(i) + " ");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static long sumEvenFibonacci(int n) {&lt;br /&gt;    // add code here.&lt;br /&gt;    return sum;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;0 0 2 2 2 10 10 10 44 44 44 188 188 188 798 798 798 3382 3382 3382 14328 &lt;br /&gt;&lt;/pre&gt;For bonus points, optimise the &lt;i&gt;sumEvenFibonacci&lt;/i&gt; method so it contains only one condition and doesn't test for even or odd.&lt;p/&gt;&lt;script type="text/javascript" language="JavaScript"&gt;&lt;!--function InsertContent(tid) {if(document.getElementById(tid).style.display == "none") { document.getElementById(tid).style.display = ""; }else { document.getElementById(tid).style.display = "none"; }}//--&gt;&lt;/script&gt;&lt;a href="javascript:InsertContent('f1');"&gt;[Click for sample solution]&lt;/a&gt;&lt;div    id="f1"    style="display: none"&gt;&lt;hr/&gt;&lt;pre&gt;&lt;br /&gt;public static long sumEvenFibonacci(int n) {&lt;br /&gt;  long a = 1, b = 1, sum = 0;&lt;br /&gt;  for (int i = n; i &gt; 2; i -= 3) {&lt;br /&gt;    long c = a + b;&lt;br /&gt;    sum += c;&lt;br /&gt;    a = b + c;&lt;br /&gt;    b = a + c;&lt;br /&gt;  }&lt;br /&gt;  return sum;&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;hr/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6125533716460796771?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6125533716460796771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/java-puzzle.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6125533716460796771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6125533716460796771'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/java-puzzle.html' title='Java puzzle (Sum of even Fibonacci numbers)'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-771094400390011239</id><published>2011-11-21T09:42:00.001Z</published><updated>2012-01-22T19:34:51.585Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>How arbitary is the start of System.nanoTime()?</title><content type='html'>System.nanoTime() is defined as having an arbitrary start time.  However, there is no reason to make it random and it is based on an unspecified system call.  On Centos 5.7 and other Linuxes I have tried, this appears to be based on the uptime.&lt;pre&gt;&lt;br /&gt;System.out.println("/proc/uptime    " + new Scanner(new FileInputStream("/proc/uptime")).next());&lt;br /&gt;System.out.println("System.nanoTime " + System.nanoTime() / 1e9);&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;/proc/uptime    265671.85&lt;br /&gt;System.nanoTime 265671.854834206&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-771094400390011239?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/771094400390011239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/how-arbitary-is-start-of-systemnanotime.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/771094400390011239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/771094400390011239'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/how-arbitary-is-start-of-systemnanotime.html' title='How arbitary is the start of System.nanoTime()?'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5703023497975957412</id><published>2011-11-07T11:04:00.000Z</published><updated>2012-01-22T19:37:34.759Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Why Concurrency examples are confusing</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;I was recently at a talk were the audience was asked who used concurrency and who found it confusing.  Nearly all who use concurrency found it confusing.&lt;p/&gt;This was a little surprising to me, and I was left wondering what the reason might be.  &lt;p/&gt;I have been thinking about writing a book, so I have been watching a number of web talks and reading a number of books which talk about concurrency and I think I know at least one reason.&lt;p/&gt;&lt;h2&gt;Bad Examples&lt;/h2&gt;The problem is; in a talk or a book you need a simple, easily understood example.  Unfortunately, simple and easily understood examples almost always make very BAD examples for concurrency.&lt;p/&gt;What makes them bad examples is that concurrency code comes with an overhead both to the developer in terms of complexity of the code and in CPU performance.  Simple examples are likely to have far more overhead than the work done making the performance of the concurrent example far worse than just writing it single threaded and also the code more confusing.&lt;p/&gt;&lt;h2&gt;Account transfer example&lt;/h2&gt;A common example used to illustrate how to avoid dead lock between two objects, is the account transfer problem.  The problem is that to transfer between two accounts, you must lock both accounts (assuming you lock individual accounts).  However, unless you lock them in the same order, you can get a deadlock where two threads hold the one of the accounts the other thread needs.&lt;pre&gt;&lt;br /&gt;Took an average of 30.7 ns to transfer money with a lock on each Account.&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;Using synchronized improves performance synchronized is marginally faster for un-contended locks. (i.e. the same threadkeep acquiring the lock)&lt;pre&gt;&lt;br /&gt;Took an average of 28.9 ns to transfer money with a lock on each Account.&lt;br /&gt;&lt;/pre&gt;This is the speed of using a thread safe account with one thread.  In theory, this should scale very well and using two threads would halve this time. You might get good scalability up to the number of cores you have. &lt;p/&gt;But the awkward question is, what if we didn't have one lock per account and just had one global lock.  The code would be simpler, but not as scalable.  But what is the cost of scalability?&lt;h3&gt;What if I used just one global lock&lt;/h3&gt;&lt;pre&gt;&lt;br /&gt;Took an average of 9.7 ns to transfer money with a one global lock.&lt;br /&gt;&lt;/pre&gt;This means we would need to have at least 7 threads trying to transfer money to be as fast as using one global lock. (Assuming we achieved the theoretically best scalability)  Given a real application has a lot other things to do, it is highly unlikely that you will average more than 7 thread in this section of code.&lt;p/&gt;&lt;h3&gt;What if I just make the code single threaded?&lt;/h3&gt;&lt;pre&gt;&lt;br /&gt;Took an average of 1.8 ns to transfer money, single threaded&lt;br /&gt;&lt;/pre&gt;This implies that we need to average over 56 cores (not just threads) in the account transfer block of code, to break even.  In this unlikely scenario, I would suggest you need to rethink your application. e.g. if you are working for an Uber-Bank performing one billion transfers per second, why are you using just one machine to do it?&lt;p/&gt;&lt;h2&gt;A Really Bad Example&lt;/h2&gt;A pet hate of mine is using the Fibonacci series in examples of concurrency.  This example has the advantage of being easy to define recursively and translate the code to being concurrent.  It also an amazingly, staggeringly BAD idea.&lt;p/&gt;This is run on a 4.6 GHz i7 2600K with 16 GB of memory.  The code stops when there isn't enough resources to start any more threads.&lt;pre&gt;&lt;br /&gt;Fibonacci 2 was 2, took 1,665 us, Time ratio=832.5 &lt;br /&gt;Fibonacci 3 was 3, took 123 us, Time ratio=41.0 &lt;br /&gt;Fibonacci 4 was 5, took 126 us, Time ratio=25.2 &lt;br /&gt;Fibonacci 5 was 8, took 154 us, Time ratio=19.3 &lt;br /&gt;Fibonacci 6 was 13, took 291 us, Time ratio=22.4 &lt;br /&gt;Fibonacci 7 was 21, took 359 us, Time ratio=17.1 &lt;br /&gt;Fibonacci 8 was 34, took 646 us, Time ratio=19.0 &lt;br /&gt;Fibonacci 9 was 55, took 544 us, Time ratio=9.9 &lt;br /&gt;Fibonacci 10 was 89, took 471 us, Time ratio=5.3 &lt;br /&gt;Fibonacci 11 was 144, took 1,417 us, Time ratio=9.8 &lt;br /&gt;Fibonacci 12 was 233, took 3,516 us, Time ratio=15.1 &lt;br /&gt;Fibonacci 13 was 377, took 3,120 us, Time ratio=8.3 &lt;br /&gt;Fibonacci 14 was 610, took 2,143 us, Time ratio=3.5 &lt;br /&gt;Fibonacci 15 was 987, took 7,949 us, Time ratio=8.1 &lt;br /&gt;Fibonacci 16 was 1,597, took 17,539 us, Time ratio=11.0 &lt;br /&gt;Fibonacci 17 was 2,584, took 7,639 us, Time ratio=3.0 &lt;br /&gt;Fibonacci 18 was 4,181, took 28,766 us, Time ratio=6.9 &lt;br /&gt;Fibonacci 19 was 6,765, took 28,838 us, Time ratio=4.3 &lt;br /&gt;Fibonacci 20 was 10,946, took 18,460 us, Time ratio=1.7 &lt;br /&gt;Fibonacci 21 was 17,711, took 85,533 us, Time ratio=4.8 &lt;br /&gt;Fibonacci 22 was 28,657, took 67,250 us, Time ratio=2.3 &lt;br /&gt;Fibonacci 23 was 46,368, took 194,481 us, Time ratio=4.2 &lt;br /&gt;Fibonacci 24 was 75,025, took 122,891 us, Time ratio=1.6 &lt;br /&gt;Fibonacci 25 was 121,393, took 283,110 us, Time ratio=2.3 &lt;br /&gt;Fibonacci 26 was 196,418, took 403,611 us, Time ratio=2.1 &lt;br /&gt;Fibonacci 27 was 317,811, took 2,476,695 us, Time ratio=7.8 &lt;br /&gt;Fibonacci 28 was 514,229, took 7,661,490 us, Time ratio=14.9 &lt;br /&gt;Exception in thread "main" java.lang.AssertionError: java.util.concurrent.ExecutionException: java.lang.AssertionError: java.util.concurrent.ExecutionException: java.lang.AssertionError: java.util.concurrent.ExecutionException: java.lang.AssertionError: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: unable to create new native thread&lt;br /&gt;&lt;/pre&gt;The time ratio is the ratio of the time taken in micro-seconds and the solution.  This is interesting because the time taken is proportional to the final value, something which rises exponentially.  Unfortunately it also consumes more resources, exponentially.&lt;p/&gt;Now compare this with the single threaded looping solution with -XX:+PrintCompilation turned on.&lt;pre&gt;&lt;br /&gt;     30    1             java.lang.String::hashCode (67 bytes)&lt;br /&gt;     36    2             sun.nio.cs.UTF_8$Encoder::encode (361 bytes)&lt;br /&gt;Fibonacci 2 was 2, took 1 us&lt;br /&gt;Fibonacci 3 was 3, took 1 us&lt;br /&gt;Fibonacci 4 was 5, took 1 us&lt;br /&gt;Fibonacci 5 was 8, took 1 us&lt;br /&gt;Fibonacci 6 was 13, took 1 us&lt;br /&gt;Fibonacci 7 was 21, took 1 us&lt;br /&gt;Fibonacci 8 was 34, took 0 us&lt;br /&gt;Fibonacci 9 was 55, took 0 us&lt;br /&gt;Fibonacci 10 was 89, took 1 us&lt;br /&gt;Fibonacci 11 was 144, took 1 us&lt;br /&gt;Fibonacci 12 was 233, took 1 us&lt;br /&gt;Fibonacci 13 was 377, took 1 us&lt;br /&gt;Fibonacci 14 was 610, took      42    3             java.lang.String::indexOf (87 bytes)&lt;br /&gt;1 us&lt;br /&gt;Fibonacci 15 was 987, took 1 us&lt;br /&gt;Fibonacci 16 was 1,597, took 1 us&lt;br /&gt;Fibonacci 17 was 2,584, took 0 us&lt;br /&gt;     42    4             java.lang.String::charAt (33 bytes)&lt;br /&gt;Fibonacci 18 was 4,181, took 1 us&lt;br /&gt;Fibonacci 19 was 6,765, took 1 us&lt;br /&gt;Fibonacci 20 was 10,946, took 1 us&lt;br /&gt;Fibonacci 21 was 17,711, took 1 us&lt;br /&gt;Fibonacci 22 was 28,657, took 1 us&lt;br /&gt;Fibonacci 23 was 46,368, took 1 us&lt;br /&gt;Fibonacci 24 was 75,025, took 1 us&lt;br /&gt;Fibonacci 25 was 121,393, took 0 us&lt;br /&gt;Fibonacci 26 was 196,418, took 1 us&lt;br /&gt;Fibonacci 27 was 317,811, took 1 us&lt;br /&gt;Fibonacci 28 was 514,229, took 1 us&lt;br /&gt;Fibonacci 29 was 832,040, took 1 us&lt;br /&gt;Fibonacci 30 was 1,346,269, took 0 us&lt;br /&gt;Fibonacci 31 was 2,178,309, took 1 us&lt;br /&gt;Fibonacci 32 was 3,524,578, took 1 us&lt;br /&gt;Fibonacci 33 was 5,702,887, took 1 us&lt;br /&gt;Fibonacci 34 was 9,227,465, took 1 us&lt;br /&gt;Fibonacci 35 was 14,930,352, took 1 us&lt;br /&gt;Fibonacci 36 was 24,157,817, took 0 us&lt;br /&gt;Fibonacci 37 was 39,088,169, took 1 us&lt;br /&gt;Fibonacci 38 was 63,245,986, took 1 us&lt;br /&gt;Fibonacci 39 was 102,334,155, took 1 us&lt;br /&gt;Fibonacci 40 was 165,580,141, took 3 us&lt;br /&gt;Fibonacci 41 was 267,914,296, took 0 us&lt;br /&gt;Fibonacci 42 was 433,494,437, took 1 us&lt;br /&gt;Fibonacci 43 was 701,408,733, took 1 us&lt;br /&gt;Fibonacci 44 was 1,134,903,170, took 1 us&lt;br /&gt;Fibonacci 45 was 1,836,311,903, took 1 us&lt;br /&gt;Fibonacci 46 was 2,971,215,073, took 1 us&lt;br /&gt;Fibonacci 47 was 4,807,526,976, took 1 us&lt;br /&gt;Fibonacci 48 was 7,778,742,049, took 1 us&lt;br /&gt;Fibonacci 49 was 12,586,269,025, took 1 us&lt;br /&gt;Fibonacci 50 was 20,365,011,074, took 1 us&lt;br /&gt;Fibonacci 51 was 32,951,280,099, took 1 us&lt;br /&gt;Fibonacci 52 was 53,316,291,173, took 1 us&lt;br /&gt;Fibonacci 53 was 86,267,571,272, took 1 us&lt;br /&gt;Fibonacci 54 was 139,583,862,445, took 1 us&lt;br /&gt;Fibonacci 55 was 225,851,433,717, took 1 us&lt;br /&gt;Fibonacci 56 was 365,435,296,162, took 1 us&lt;br /&gt;Fibonacci 57 was 591,286,729,879, took 1 us&lt;br /&gt;Fibonacci 58 was 956,722,026,041, took 1 us&lt;br /&gt;Fibonacci 59 was 1,548,008,755,920, took 1 us&lt;br /&gt;Fibonacci 60 was 2,504,730,781,961, took 1 us&lt;br /&gt;Fibonacci 61 was 4,052,739,537,881, took 1 us&lt;br /&gt;Fibonacci 62 was 6,557,470,319,842, took 2 us&lt;br /&gt;Fibonacci 63 was 10,610,209,857,723, took 2 us&lt;br /&gt;Fibonacci 64 was 17,167,680,177,565, took 2 us&lt;br /&gt;Fibonacci 65 was 27,777,890,035,288, took 1 us&lt;br /&gt;Fibonacci 66 was 44,945,570,212,853, took 1 us&lt;br /&gt;Fibonacci 67 was 72,723,460,248,141, took 1 us&lt;br /&gt;Fibonacci 68 was 117,669,030,460,994, took 2 us&lt;br /&gt;Fibonacci 69 was 190,392,490,709,135, took 2 us&lt;br /&gt;Fibonacci 70 was 308,061,521,170,129, took 1 us&lt;br /&gt;Fibonacci 71 was 498,454,011,879,264, took 1 us&lt;br /&gt;Fibonacci 72 was 806,515,533,049,393, took 1 us&lt;br /&gt;Fibonacci 73 was 1,304,969,544,928,657, took 1 us&lt;br /&gt;Fibonacci 74 was 2,111,485,077,978,050, took 1 us&lt;br /&gt;Fibonacci 75 was 3,416,454,622,906,707, took 1 us&lt;br /&gt;Fibonacci 76 was 5,527,939,700,884,757, took 1 us&lt;br /&gt;Fibonacci      49    5             java.util.regex.Matcher::77reset (83 bytes)&lt;br /&gt; was 8,944,394,323,791,464, took 1 us&lt;br /&gt;Fibonacci 78 was 14,472,334,024,676,221, took 1 us&lt;br /&gt;Fibonacci 79 was 23,416,728,348,467,685, took 1 us&lt;br /&gt;Fibonacci 80 was 37,889,062,373,143,906, took 2 us&lt;br /&gt;Fibonacci 81 was 61,305,790,721,611,591, took 3 us&lt;br /&gt;Fibonacci 82 was 99,194,853,094,755,497, took 2 us&lt;br /&gt;Fibonacci 83 was 160,500,643,816,367,088, took 1 us&lt;br /&gt;Fibonacci 84 was 259,695,496,911,122,585, took 2 us&lt;br /&gt;Fibonacci 85 was 420,196,140,727,489,673, took 2 us&lt;br /&gt;Fibonacci 86 was 679,891,637,638,612,258, took 1 us&lt;br /&gt;Fibonacci 87 was 1,100,087,778,366,101,931, took 2 us&lt;br /&gt;Fibonacci 88 was 1,779,979,416,004,714,189, took 2 us&lt;br /&gt;Fibonacci 89 was 2,880,067,194,370,816,120, took 1 us&lt;br /&gt;Fibonacci 90 was 4,660,046,610,375,530,309, took 1 us&lt;br /&gt;Fibonacci 91 was 7,540,113,804,746,346,429, took 2 us&lt;br /&gt;&lt;/pre&gt;Note: the method calculating Fibonacci values is not even compiled and is still running in the relatively slow  interpreter.Yet it barely uses more than 2 micro-seconds. When compiled to native code it takes around 40 nano-seconds.&lt;/p&gt;If the multi-threaded Fibonacci took 2 micro-second per result value, implying "Fibonacci 91" might take around 180 million years.  Unfortunately, the number of threads required is also proportional to the result value, requiring in the order of a trillion trillion threads.&lt;h2&gt;Conclusion&lt;/h2&gt;When considering multi-threading a section of an application, you should take a single threaded, lock free implementation as a base line.  If you can't make the multi-threaded, thread safe implementation faster, don't make it multi-threaded.&lt;p/&gt;Put another way, if you are using concurrency to improve performance, make sure you are dealing with a problem which can be made concurrent and a solution which is faster than using one thread.&lt;h2&gt;The Code&lt;/h2&gt;For Accounts, look at the ThreadedAccountMain, ThreadedAccountLockMain, ThreadedAccountOneLockMain and UnthreadedAccountMain.&lt;p/&gt;For Fibonaccii, look at the ThreadedFibonacciMain and UnthreadedFibonacciMain&lt;p/&gt;&lt;h3&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/#svn%2Ftrunk%2Fsrc%2Ftest%2Fjava%2Fcom%2Fgoogle%2Fcode%2Fjava%2Fcore%2Fthreads"&gt;Threads code&lt;/a&gt;&lt;/h3&gt;I would like to thank Roger Lindsjö for &lt;a href="http://java.dzone.com/articles/why-concurrency-examples-are"&gt;his suggestions on DZone&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5703023497975957412?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5703023497975957412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/11/why-concurency-examples-are-confusing.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5703023497975957412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5703023497975957412'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/11/why-concurency-examples-are-confusing.html' title='Why Concurrency examples are confusing'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6932046514633504492</id><published>2011-10-30T12:06:00.000Z</published><updated>2012-01-22T19:34:51.565Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Recycling objects to improve performance</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;In a previous article I stated that the reason the deserialisation of objects was faster was due to using recycled objects.  This is potentially surprising for two reasons, 1) the belief that creating objects is so fast these days, it doesn't matter or is just as fast as recycling yourself, 2) None of the serialisation libraries use recycling by default.&lt;p /&gt;This article explores deserialisation with and without recycling objects. How it not only is slower to create objects, but it slows down the rest of your program by pushing data out of your CPU caches.&lt;p /&gt;While this talks about deserialisaton, the same applies to parsing text or reading binary files, as the actions being performed are the same.&lt;br /&gt;&lt;h2&gt;The test&lt;/h2&gt;In this test, I deserialise 1000 Price objects, but also time how long it takes to copy a block of data.  The copy represents work which the application might have to perform after deserialising.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ETl0Cqr4ZOI/Tq0H4F8Ij6I/AAAAAAAAAFs/_OLXzqPujRQ/s1600/deserialise1000prices.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-ETl0Cqr4ZOI/Tq0H4F8Ij6I/AAAAAAAAAFs/_OLXzqPujRQ/s1600/deserialise1000prices.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Gvc85RY_6RU/Tq0H8-SJMMI/AAAAAAAAAF4/bwtejjhuoiw/s1600/copyAfterDeserialisation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Gvc85RY_6RU/Tq0H8-SJMMI/AAAAAAAAAF4/bwtejjhuoiw/s1600/copyAfterDeserialisation.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p/&gt;The test is timed one million times and those results sorted.  The X-Axis shows the percentile timing. e.g. the 90% values is the 90% worst value. (or 10% of values are higher)&lt;p/&gt;As you can see, the deserialisation take longer if it has to create objects as it goes, however sometimes it takes much much long.  This is perhaps not so surprising as creating objects means doing more work and possibly being delayed by a GC.  However, it is the increase in the time to copy a block of data which is surprising.  This demonstrates that not only is the deserialisation slower, but any work which needs the data cache is also slower as a result. (Which is just about anything you might do in a real application)&lt;br /&gt;Performances tests rarely show you the impact on the rest of your application.&lt;p /&gt;&lt;h2&gt;In more detail&lt;/h2&gt;Examining the higher percentile (longest times) you can see that the performance consistently bad if the deserialisation has to wait for the GC.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-L62uTJYlxP8/Tq0IXxOB28I/AAAAAAAAAGE/DTem0L_Jo2I/s1600/deserialise1000prices95.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-L62uTJYlxP8/Tq0IXxOB28I/AAAAAAAAAGE/DTem0L_Jo2I/s1600/deserialise1000prices95.png" /&gt;&lt;/a&gt;&lt;/div&gt;And the performance of the copy increases significantly in the worst case.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-X6VwAb4pnzw/Tq0IaxSa0jI/AAAAAAAAAGQ/FB-OD_phLc4/s1600/copyAfterDeserialisation95.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-X6VwAb4pnzw/Tq0IaxSa0jI/AAAAAAAAAGQ/FB-OD_phLc4/s1600/copyAfterDeserialisation95.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h2&gt;The code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/#svn%2Ftrunk%2Fsrc%2Ftest%2Fjava%2Fcom%2Fgoogle%2Fcode%2Fjava%2Fcore%2Frecycling"&gt;Recycling example code&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6932046514633504492?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6932046514633504492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/10/recycling-objects-to-improve.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6932046514633504492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6932046514633504492'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/10/recycling-objects-to-improve.html' title='Recycling objects to improve performance'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-ETl0Cqr4ZOI/Tq0H4F8Ij6I/AAAAAAAAAFs/_OLXzqPujRQ/s72-c/deserialise1000prices.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4156698105715240675</id><published>2011-10-27T14:51:00.000+01:00</published><updated>2012-01-22T19:34:51.504Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Serialization using ByteBuffer and recycled objects</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;I have always been of the view that using recycled objects is faster for serialization.&lt;p/&gt;So I wrote a test based on &lt;a href="http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking"&gt;Thrift Protobuf Compare&lt;/a&gt; to see where it does well or poorly.&lt;p/&gt;The benchmark suggest that serialization/deserialization is fast with ByteBuffer and recycled objects, but creating new objects is relatively expensive.&lt;p/&gt;This suggests that provided you have a simple strategy for reusing objects, it may be worth using this approach.  However, if you can't recycle objects I suspect it won't be worth the extra effort.&lt;p/&gt;&lt;h2&gt;Total Serailization time&lt;/h2&gt;&lt;img src='http://chart.apis.google.com/chart?chtt=totalTime&amp;chf=c||lg||0||FFFFFF||1||76A4FB||0|bg||s||EFEFEF&amp;chs=689x430&amp;chd=t:374.5,1317.0,1547.5,1802.5,1945.5,1970.0,2137.5,2144.0,2482.0,2565.0,2931.0,3672.5,4292.0,4359.5,5113.0,5934.0,6966.0,8805.0,10414.5,12887.0,13312.0,18425.5,28931.0&amp;chds=0,31824.100000000002&amp;chxt=y&amp;chxl=0:|java|json/jackson-databind|JsonMarshaller|xstream (stax with conv)|binaryxml/FI|hessian|javolution xmlformat|stax/woodstox|stax/aalto|protostuff-numeric-json|protostuff-json|json (jackson)|thrift|avro-generic|sbinary|avro-specific|activemq protobuf|protobuf|kryo|kryo-optimized|MessagePack (buggy)|java (externalizable)|ByteBuffer-specific&amp;chm=N *f*,000000,0,-1,10&amp;lklk&amp;chdlp=t&amp;chco=660000|660033|660066|660099|6600CC|6600FF|663300|663333|663366|663399|6633CC|6633FF|666600|666633|666666&amp;cht=bhg&amp;chbh=10&amp;nonsense=aaa.png'/&gt;&lt;h2&gt;All results&lt;/h2&gt;Note: the creation time for a recyclable object is much higher, but the serialization/deserialization times are much better.&lt;pre STYLE="width: 800px;overflow-x: scroll"&gt;&lt;br /&gt;Starting&lt;br /&gt;                        ,   Object create,       Serialize,  /w Same Object,     Deserialize, and Check Media,   and Check All,      Total Time, Serialized Size&lt;br /&gt;ByteBuffer-specific     ,       154.98000,       242.50000,       303.00000,       132.00000,       132.00000,       132.00000,       374.50000,        213&lt;br /&gt;avro-generic            ,       791.64500,      1675.00000,      1024.00000,       890.00000,       890.00000,       890.00000,      2565.00000,        211&lt;br /&gt;avro-specific           ,       460.89500,      1089.00000,       756.50000,      1055.00000,      1055.00000,      1055.00000,      2144.00000,        211&lt;br /&gt;activemq protobuf       ,        49.61000,      1203.50000,       186.00000,         7.00000,       612.50000,       934.00000,      2137.50000,        231&lt;br /&gt;protobuf                ,        61.55500,      1130.50000,       762.50000,       579.00000,       797.00000,       839.50000,      1970.00000,        231&lt;br /&gt;thrift                  ,        62.97000,      1401.00000,      1502.00000,      1530.00000,      1530.00000,      1530.00000,      2931.00000,        353&lt;br /&gt;hessian                 ,        34.69000,      3208.00000,      3186.00000,      5597.00000,      5597.00000,      5597.00000,      8805.00000,        526&lt;br /&gt;kryo                    ,        35.33000,       988.50000,      1132.50000,       957.00000,       957.00000,       957.00000,      1945.50000,        226&lt;br /&gt;kryo-optimized          ,        36.00000,       887.50000,      1051.00000,       915.00000,       915.00000,       915.00000,      1802.50000,        207&lt;br /&gt;MessagePack (buggy)     ,        34.93000,       873.50000,       960.00000,       674.00000,       674.00000,       674.00000,      1547.50000,        216&lt;br /&gt;java                    ,        38.50000,      5012.50000,      4705.50000,     23918.50000,     23918.50000,     23918.50000,     28931.00000,        919&lt;br /&gt;java (externalizable)   ,        38.99000,       707.00000,       839.50000,       610.00000,       610.00000,       610.00000,      1317.00000,        264&lt;br /&gt;scala                   ,        33.98000,     11184.50000,     10630.50000,     63917.00000,     63917.00000,     63917.00000,     75101.50000,       2024&lt;br /&gt;json (jackson)          ,        37.69000,      1934.50000,      2196.00000,      1738.00000,      1738.00000,      1738.00000,      3672.50000,        378&lt;br /&gt;json/jackson-databind   ,        38.55500,      8888.00000,      9277.00000,      9537.50000,      9537.50000,      9537.50000,     18425.50000,       1815&lt;br /&gt;JsonMarshaller          ,        40.04500,      4856.00000,      5127.00000,      8456.00000,      8456.00000,      8456.00000,     13312.00000,        370&lt;br /&gt;protostuff-json         ,        67.91000,      2153.00000,      2361.00000,      2139.00000,      2139.00000,      2139.00000,      4292.00000,        448&lt;br /&gt;protostuff-numeric-json ,        65.95000,      2171.00000,      2220.50000,      2188.50000,      2188.50000,      2188.50000,      4359.50000,        359&lt;br /&gt;json/google-gson        ,        40.13000,    102987.00000,    103714.00000,    123158.00000,    123158.00000,    123158.00000,    226145.00000,        470&lt;br /&gt;stax/woodstox           ,        39.84500,      2357.50000,      2651.00000,      3576.50000,      3576.50000,      3576.50000,      5934.00000,        475&lt;br /&gt;stax/aalto              ,        37.01500,      2008.50000,      2220.00000,      3104.50000,      3104.50000,      3104.50000,      5113.00000,        475&lt;br /&gt;binaryxml/FI            ,        40.43000,      5322.00000,      5639.50000,      5092.50000,      5092.50000,      5092.50000,     10414.50000,        300&lt;br /&gt;xstream (stax with conv),        41.80500,      4512.50000,      4276.50000,      8374.50000,      8374.50000,      8374.50000,     12887.00000,        399&lt;br /&gt;javolution xmlformat    ,        36.89000,      3197.00000,      3309.00000,      3769.00000,      3769.00000,      3769.00000,      6966.00000,        419&lt;br /&gt;sbinary                 ,        33.50000,      1510.00000,      1690.00000,       972.00000,       972.00000,       972.00000,      2482.00000,        264&lt;br /&gt;&lt;/pre&gt;The main advantage over Java Externalizable is the option to re-use objects rather than create them each time. There is also a small advantage in being able to read/write a long as a single native read/write instead or 8 bytes with bit shift operations. (Similar for int)&lt;p/&gt;&lt;h2&gt;The Code&lt;/h2&gt;Note: You have to write more code yourself if you are going to use ByteBuffers, but not much more than custom Java Externalisable.  The main shift of thinking required is creating recycleable structures.  In a multi-threaded context this ia made additionally difficult, however if you use these with care or model you application as a series of independant single threaded processes, this doesn't have to be a problem.&lt;p/&gt;ByteBuffers are builtin to Java so no additional library is required to use them, however a small number of helper methods are useful.&lt;p/&gt;Using ByteBuffers for serialization can also improve IO performance as the data is in the "C" space already. A byte[] is not required.&lt;p/&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/#svn%2Ftrunk%2Fsrc%2Fmain%2Fjava%2Fcom%2Fgoogle%2Fcode%2Fjava%2Fcore%2Fbytebuffer"&gt;ByteBuffer serialization example code&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4156698105715240675?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4156698105715240675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/10/serialization-using-bytebuffer-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4156698105715240675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4156698105715240675'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/10/serialization-using-bytebuffer-and.html' title='Serialization using ByteBuffer and recycled objects'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4332868268828009300</id><published>2011-10-27T09:24:00.000+01:00</published><updated>2012-01-22T19:34:51.520Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Serialization benchmarks and charts</title><content type='html'>I was looking at this serialization benchmark &lt;a href="http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking"&gt;Thrift Protobuf Compare&lt;/a&gt; and saw at the end oif the report it spits out a series of HTML. One of these reads.&lt;p/&gt;&amp;lt;img src='http://chart.apis.google.com/chart?chtt=totalTime&amp;chf=c||lg||0||FFFFFF||1||76A4FB||0|bg||s||EFEFEF&amp;chs=689x430&amp;chd=t:1263.0,1552.0,1747.0,1878.0,1966.5,2119.0,2203.0,2559.5,2706.0,2963.0,3585.5,3912.5,4182.5,4186.5,5948.5,7337.5,9050.5,10078.0,12404.0,12931.0,18031.0,28068.5&amp;chds=0,30875.350000000002&amp;chxt=y&amp;chxl=0:|java|json/jackson-databind|JsonMarshaller|xstream (stax with conv)|binaryxml/FI|hessian|javolution xmlformat|stax/woodstox|protostuff-json|stax/aalto|protostuff-numeric-json|json (jackson)|thrift|avro-generic|sbinary|avro-specific|activemq protobuf|protobuf|kryo|kryo-optimized|MessagePack (buggy)|java (externalizable)&amp;chm=N *f*,000000,0,-1,10&amp;lklk&amp;chdlp=t&amp;chco=660000|660033|660066|660099|6600CC|6600FF|663300|663333|663366|663399|6633CC|6633FF|666600|666633|666666&amp;cht=bhg&amp;chbh=10&amp;nonsense=aaa.png'/&gt;&lt;p/&gt;Which when displays looks like.&lt;p/&gt;&lt;img src='http://chart.apis.google.com/chart?chtt=totalTime&amp;chf=c||lg||0||FFFFFF||1||76A4FB||0|bg||s||EFEFEF&amp;chs=689x430&amp;chd=t:1263.0,1552.0,1747.0,1878.0,1966.5,2119.0,2203.0,2559.5,2706.0,2963.0,3585.5,3912.5,4182.5,4186.5,5948.5,7337.5,9050.5,10078.0,12404.0,12931.0,18031.0,28068.5&amp;chds=0,30875.350000000002&amp;chxt=y&amp;chxl=0:|java|json/jackson-databind|JsonMarshaller|xstream (stax with conv)|binaryxml/FI|hessian|javolution xmlformat|stax/woodstox|protostuff-json|stax/aalto|protostuff-numeric-json|json (jackson)|thrift|avro-generic|sbinary|avro-specific|activemq protobuf|protobuf|kryo|kryo-optimized|MessagePack (buggy)|java (externalizable)&amp;chm=N *f*,000000,0,-1,10&amp;lklk&amp;chdlp=t&amp;chco=660000|660033|660066|660099|6600CC|6600FF|663300|663333|663366|663399|6633CC|6633FF|666600|666633|666666&amp;cht=bhg&amp;chbh=10&amp;nonsense=aaa.png'/&gt;&lt;p/&gt;A simple way to generate charts in web pages.&lt;p/&gt;BTW: The application was run using Java 7 update 1 64-bit on an i7 2600K 4.6 GHz.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4332868268828009300?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4332868268828009300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/10/serialization-benchmarks-and-charts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4332868268828009300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4332868268828009300'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/10/serialization-benchmarks-and-charts.html' title='Serialization benchmarks and charts'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2414365501558495734</id><published>2011-10-26T13:58:00.002+01:00</published><updated>2012-01-26T15:16:51.856Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Strine translator</title><content type='html'>Translating to Strine ;)&lt;pre&gt;&lt;br /&gt;    public static void main(String... args) {&lt;br /&gt;        System.out.println("Hello World");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    static {&lt;br /&gt;        try {&lt;br /&gt;            Field value = String.class.getDeclaredField("value");&lt;br /&gt;            value.setAccessible(true);&lt;br /&gt;            value.set("Hello World", value.get("G'Day Mate."));&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            throw new AssertionError(e);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;G'Day Mate.&lt;br /&gt;&lt;/pre&gt;BTW: Strine is the Australian Dialect of English.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2414365501558495734?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2414365501558495734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/10/strine-translator.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2414365501558495734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2414365501558495734'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/10/strine-translator.html' title='Strine translator'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2699579383169552839</id><published>2011-10-26T13:25:00.001+01:00</published><updated>2012-01-22T19:31:40.757Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Randomly not so random</title><content type='html'>In a random sequence, all sequences are equally likely, even not so random ones.&lt;pre&gt;&lt;br /&gt;    Random random = new Random(441287210);&lt;br /&gt;    for(int i=0;i&lt;10;i++)&lt;br /&gt;        System.out.print(random.nextInt(10)+" ");&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;1 1 1 1 1 1 1 1 1 1&lt;br /&gt;&lt;/pre&gt; and&lt;pre&gt;&lt;br /&gt;    Random random = new Random(-6732303926L);&lt;br /&gt;    for(int i=0;i&lt;10;i++)&lt;br /&gt;        System.out.println(random.nextInt(10)+" ");&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;0 1 2 3 4 5 6 7 8 9&lt;br /&gt;&lt;/pre&gt;Lastly&lt;pre&gt;&lt;br /&gt;public static void main(String ... args) {&lt;br /&gt;    System.out.println(randomString(-229985452)+' '+randomString(-147909649));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static String randomString(int seed) {&lt;br /&gt;    Random rand = new Random(seed);&lt;br /&gt;    StringBuilder sb = new StringBuilder();&lt;br /&gt;    for(int i=0;;i++) {&lt;br /&gt;        int n = rand.nextInt(27);&lt;br /&gt;        if (n == 0) break;&lt;br /&gt;        sb.append((char) ('`' + n));&lt;br /&gt;    }&lt;br /&gt;    return sb.toString();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;hello world&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2699579383169552839?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2699579383169552839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/10/randomly-no-so-random.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2699579383169552839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2699579383169552839'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/10/randomly-no-so-random.html' title='Randomly not so random'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7052490026883710729</id><published>2011-10-26T11:36:00.003+01:00</published><updated>2012-01-22T19:31:40.808Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Java plus</title><content type='html'>A confusing piece of code here for you to parse. ;)&lt;br/&gt;&lt;pre&gt;&lt;br /&gt;int i = (byte) + (char) - (int) + (long) - 1;&lt;br /&gt;System.out.println(i);&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;prints&lt;br/&gt;&lt;pre&gt;&lt;br /&gt;1&lt;br /&gt;&lt;/pre&gt;&lt;a href="http://stackoverflow.com/questions/7924961/weird-java-behavior-with-casts-to-primitive-types"&gt;Later discussed on Stack Overflow here.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7052490026883710729?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7052490026883710729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/10/java-plus.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7052490026883710729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7052490026883710729'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/10/java-plus.html' title='Java plus'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1962895317897162085</id><published>2011-09-26T13:05:00.001+01:00</published><updated>2012-01-22T19:34:51.417Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>HugeCollections moved to github</title><content type='html'>HugeCollections has been moved to github. to support easier forking and collaboration.&lt;p/&gt;&lt;a href="https://github.com/HugeCollections/Collections"&gt;https://github.com/HugeCollections/Collections&lt;/a&gt;&lt;p/&gt;Its a pain to &lt;a href="http://help.github.com/"&gt;setup&lt;/a&gt;, but once that is done it makes working on the code and merging changes much easier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1962895317897162085?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1962895317897162085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/hugecollections-moved-to-github.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1962895317897162085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1962895317897162085'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/hugecollections-moved-to-github.html' title='HugeCollections moved to github'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4867918780346183662</id><published>2011-09-20T08:53:00.001+01:00</published><updated>2012-01-22T19:34:51.527Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>New Contributors to HugeCollections</title><content type='html'>&lt;h2&gt;What is the HugeCollection library&lt;/h2&gt;The objectives of HugeCollections for the first release are fairly ambitious.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Scale to massive collections i.e. sizes much larger than 2 billion without significant heap foot print or GC impact. i.e. using heap-less memory&lt;/li&gt;&lt;li&gt;Be faster and more efficient that using plain JavaBeans with an ArrayList or Map and a vector or unordered_map in C++.&lt;/li&gt;&lt;li&gt;Support durability (transparently saved and loaded from disk)&lt;/li&gt;&lt;li&gt;Support thread safety (with no overhead if not required) and using multiple threads implicitly. i.e. large operations are automatically distributed.&lt;/li&gt;&lt;li&gt;Be faster and more efficient than using a database. Transactions will NOT be in this release.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Support in one application what might have to be distributed otherwise.&lt;/li&gt;&lt;li&gt;Dynamic code generation as required (no need to pre-generate code in the build)&lt;/li&gt;&lt;/ul&gt;A prototype has been built which shows these objectives are possible, however to turn this library in to a usable release, will take some help.&lt;br /&gt;&lt;p /&gt;Note: I am open to people working on the things they find most interesting, even if this means some areas are more developed than others.&lt;p/&gt;To have a look at the code start with &lt;a href="http://code.google.com/p/vanilla-java/source/checkout&gt;http://code.google.com/p/vanilla-java/source/checkout&lt;/a&gt; This code is still being patched to fix issues.  The area we are re-developing the library is a sandbox area &lt;a href="http://vanilla-java.googlecode.com/svn/sandbox/"&gt;http://vanilla-java.googlecode.com/svn/sandbox/&lt;/a&gt; which you can also checkout.&lt;h2&gt;Myself&lt;/h2&gt;Peter Lawrey - I have been working with Java for 12 years and on high performance systems for 15 years. I have worked at Investment Banks, a prop trading firm and Sun Microsystems.&lt;br /&gt;&lt;h2&gt;Two new contributors&lt;/h2&gt;Rob Austin currently contracting for a large investment bank, working on a low latency pricing and trading platform. Over 10 years of Java experience.&lt;br /&gt;&lt;br /&gt;Costantino Cerbo is a certified Java developer (SCJP and SCBCD) and software consultant with more than 6 years experience. He has worked for one of the Italy's largest banks. He is an Italian native speaker, fluent in German and strong in English (TOEFL: 607 points).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;More contributors welcome&lt;/h2&gt;I am looking for additional contributors to....&lt;br /&gt;- document the high level approach used and its advantages.&lt;br /&gt;- proper documentation and pier review of the design.&lt;br /&gt;- code review of the hand coded collections for list and hash map (These are templates for the auto-generated classes)- tool to assist the conversion of the template into the code generation.&lt;br /&gt;- Test cases for correct functionality.&lt;br /&gt;- Performance and scalability tests.&lt;br /&gt;- Comparison tests for performance and scalability.&lt;br /&gt;- a comparison with the features of similar products like ehCache BigMemory, javolution, trove4j (also find other products worth comparing) and C++.&lt;br /&gt;&lt;br /&gt;- Documentation and blog of the comparison.&lt;br /&gt;- Examine thread safety support and tests.&lt;br /&gt;- Auto multi-threading for filter() and visit() methods.&lt;br /&gt;- Examine integration and examples of use in JVM languages like Scala, Groovy, Jython, JRuby and see what support can be given. i.e. are there simple things which can be done to make it simpler/more natural to use.&lt;br /&gt;- Produce a JTable GUI demo with one billion rows.&lt;br /&gt;&lt;br /&gt;Later&lt;br /&gt;- Add queue/dispatcher support.&lt;br /&gt;- Add sorted index (a la TreeMap or map in C++) support.&lt;br /&gt;- Add non-unique indexes.&lt;br /&gt;- Simple remote support. RMI/RPC&lt;br /&gt;- Distributed copies of data and partitioning.&lt;br /&gt;&lt;br /&gt;Any suggestions welcome.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;My email&lt;/h2&gt;You can contact me as peter.lawrey on gmail.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4867918780346183662?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4867918780346183662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/new-contributors-to-hugecollections.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4867918780346183662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4867918780346183662'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/new-contributors-to-hugecollections.html' title='New Contributors to HugeCollections'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4393882404848259869</id><published>2011-09-17T15:53:00.000+01:00</published><updated>2012-01-26T15:15:47.240Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Forum for ideas</title><content type='html'>Someone recently asked me if had a forum to include suggestions for articles to add.&lt;br /&gt;&lt;br /&gt;Does anyone have&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a forum to work well with blogger.&lt;/li&gt;&lt;li&gt;suggestions for articles.&lt;/li&gt;&lt;/ul&gt;Please comment with your ideas. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4393882404848259869?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4393882404848259869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/forum-for-ideas.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4393882404848259869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4393882404848259869'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/forum-for-ideas.html' title='Forum for ideas'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3922997151815575424</id><published>2011-09-12T17:37:00.001+01:00</published><updated>2012-01-22T19:34:51.496Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>The Exchanger and GC-less Java</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The &lt;a href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html"&gt;Exchanger&lt;/a&gt; class is very efficient at passing work between thread and recycling the objects used.  AFAIK, It is also one of the least used Concurrency classes.&lt;br /&gt;As @Marksim Sipos points out, if you don't need GC less logging using an ArrayBlockingQueue is much simpler.&lt;br /&gt;&lt;h2&gt;Exchanger class&lt;/h2&gt;The Exchanger class is useful for passing data back and forth between two threads. e.g. Producer/Consumer.  It has the property of naturally recycling the data structures used to pass the work and supports GC-less sharing of work in an efficient manner.&lt;br /&gt;Here is an example, passing logs to a background logger.&lt;br /&gt;Work (a log entry) is batched into LogEntries and passed to a background thread which later passes it back to the thread so it can add more work.  Provided the background thread is always finished before the batch is full, it is almost transparent.  Increasing the size of the batch reduces how often the batch is full but increase the number of unprocessed entries waiting at any one time. Calling flush() can push out the data.&lt;br /&gt;The key line is the following which exchanges the batch in the current thread with the batch in the other thread.  The producer fills up the batch while the consumer is emptying it.&lt;br /&gt;The exchange when it occurs typically takes 1-4 micro-seconds. In this case, once every 64 lines.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;entries = logEntriesExchanger.exchange(entries);&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;How does this compare to the LMAX disruptor pattern&lt;/h2&gt;This approach has similar principles to the &lt;a href="http://code.google.com/p/disruptor/"&gt;Disruptor&lt;/a&gt;.  No GC using recycled, pre-allocated buffers and lock free operations (The Exchanger not completely lock free and doesn't busy wait, but it could)&lt;br /&gt;Two keys difference are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; there is only one producer/consumer in this case, the disruptor supports multiple consumers.&amp;nbsp;&lt;/li&gt;&lt;li&gt;this approach re-uses a much smaller buffer efficiently. If you are using ByteBuffer (as I have in the past) an optimal size might be 32 KB.&amp;nbsp; The disruptor library was designed to exploit large amounts of memory on the assumption it is relative cheap and can use medium sized (MBs) to very large buffers (GBs). e.g. it was design for servers with 144 GB.&amp;nbsp; I am sure it works well on much smaller servers. ;)&lt;/li&gt;&lt;/ul&gt;Thank you @Doug, for reminding me to mention the Disruptor pattern.&lt;br /&gt; &lt;br /&gt; If you have dozen logs files (for different purposes) and you want to minimise memory foot print and you prefer the consuming thread to be blocking rather than busy waiting which consumes 100% of a thread (which adds a small latency of up to 10 us) then the Exchanger is better suited.&lt;br /&gt;&lt;h2&gt;Exchanger example&lt;/h2&gt;&lt;pre&gt;import java.util.concurrent.Exchanger;&lt;br /&gt;import java.util.concurrent.ExecutorService;&lt;br /&gt;import java.util.concurrent.Executors;&lt;br /&gt;&lt;br /&gt;public class BackgroundLogger implements Runnable {&lt;br /&gt;  static final int ENTRIES = 64;&lt;br /&gt;&lt;br /&gt;  static class LogEntry {&lt;br /&gt;    long time;&lt;br /&gt;    int level;&lt;br /&gt;    final StringBuilder text = new StringBuilder();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  static class LogEntries {&lt;br /&gt;    final LogEntry[] lines = new LogEntry[ENTRIES];&lt;br /&gt;    int used = 0;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private final ExecutorService executor = Executors.newSingleThreadExecutor();&lt;br /&gt;  final Exchanger&amp;lt;LogEntries&amp;gt; logEntriesExchanger = new Exchanger&amp;lt;LogEntries&amp;gt;();&lt;br /&gt;  LogEntries entries = new LogEntries();&lt;br /&gt;&lt;br /&gt;  BackgroundLogger() {&lt;br /&gt;    executor.submit(this);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public StringBuilder log(int level) {&lt;br /&gt;    try {&lt;br /&gt;      if (entries.used == ENTRIES)&lt;br /&gt;        entries = logEntriesExchanger.exchange(entries);&lt;br /&gt;      LogEntry le = entries.lines[entries.used++];&lt;br /&gt;      le.time = System.currentTimeMillis();&lt;br /&gt;      le.level = level;&lt;br /&gt;      return le.text;&lt;br /&gt;&lt;br /&gt;    } catch (InterruptedException e) {&lt;br /&gt;      throw new RuntimeException(e);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void flush() throws InterruptedException {&lt;br /&gt;    if(entries.used &amp;gt; 0)&lt;br /&gt;        entries = logEntriesExchanger.exchange(entries);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void stop() {&lt;br /&gt;    try {&lt;br /&gt;      flush();&lt;br /&gt;    } catch (InterruptedException e) {&lt;br /&gt;      e.printStackTrace(); // use standard logging.&lt;br /&gt;    }&lt;br /&gt;    executor.shutdownNow();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void run() {&lt;br /&gt;    LogEntries entries = new LogEntries();&lt;br /&gt;    try {&lt;br /&gt;      while (!Thread.interrupted()) {&lt;br /&gt;        entries = logEntriesExchanger.exchange(entries);&lt;br /&gt;            for (int i = 0; i &amp;lt; entries.used; i++) {&lt;br /&gt;              bgLog(entries.lines[i]);&lt;br /&gt;              entries.lines[i].text.delete(0, entries.lines[i].text.length());&lt;br /&gt;        }&lt;br /&gt;        entries.used = 0;&lt;br /&gt;      }&lt;br /&gt;    } catch (InterruptedException ignored) {&lt;br /&gt;&lt;br /&gt;    } finally {&lt;br /&gt;      System.out.println("Warn: logger stopping."); // use standard logging.&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private void bgLog(LogEntry line) {&lt;br /&gt;    // log the entry to a file.&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3922997151815575424?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3922997151815575424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/exchange-and-gc-less-java.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3922997151815575424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3922997151815575424'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/exchange-and-gc-less-java.html' title='The Exchanger and GC-less Java'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5590322336733572929</id><published>2011-09-12T12:54:00.000+01:00</published><updated>2012-01-26T15:15:47.246Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Is making Boost more like Java a good idea?</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;I was reading a question StackOverflow about &lt;a href="http://stackoverflow.com/questions/374147/what-is-boost-missing"&gt;What is Boost missing?&lt;/a&gt; and I was wondering how many of these features are available in Java already and whether making boost more like Java is good idea.&lt;p/&gt;&lt;h2&gt;Top suggestions&lt;/h2&gt;&lt;table cellpadiing="12"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Suggestion&lt;/th&gt;&lt;th&gt;What is in Java&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SQL support&lt;/td&gt;&lt;td&gt;JDBC&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JSon&lt;/td&gt;&lt;td&gt;Requires an additional library like XStream, Possibly should be in core Java&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Audio&lt;/td&gt;&lt;td&gt;Java has basic support.  Don't know if it much good.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;logging&lt;/td&gt;&lt;td&gt;Logger&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;callstack, a standard API&lt;/td&gt;&lt;td&gt;Throwable.getStackTrace() and Thread.getStackTrace()&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Support for archives&lt;/td&gt;&lt;td&gt;Support ZIP and JAR&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Redeveloped collections&lt;/td&gt;&lt;td&gt;The same could be said for Java Collections&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Standard XML parsing for UTF-8 text&lt;/td&gt;&lt;td&gt;SAX (event driven) and DOM (Document object model) parsers for XML&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Platform independent GUI&lt;/td&gt;&lt;td&gt;Swing&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Concurrency with lock free collections and atomic operations&lt;/td&gt;&lt;td&gt;Concurrency library&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Arbitrary precision floating point and decimal&lt;/td&gt;&lt;td&gt;BigDecimal and BigInteger&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Python, Ruby and Lua support&lt;/td&gt;&lt;td&gt;Not built in, but there is Jython, JRuby and LuaJava&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High performance (sub micro-second) timers&lt;/td&gt;&lt;td&gt;System.nanoTime()&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Better concept support&lt;/td&gt;&lt;td&gt;This looks like staticly defined duck typing and Java is a long way from having anything like this. ;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Atomic&lt;/td&gt;&lt;td&gt;AtomicBoolean, AtomicInteger, AtomicLong, AtomicReference, AtomicIntegerArray and AtomicLongArray&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Thread pools&lt;/td&gt;&lt;td&gt;ExecutorService and ScheduledExecutorService&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RPC&lt;/td&gt;&lt;td&gt;RMI&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Character encoding&lt;/td&gt;&lt;td&gt;CharSet&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GPU support&lt;/td&gt;&lt;td&gt;I would love Java to have this as well. There is JoCL but its not exactly transparent or close to the Write One, Run Anywhere model.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Hashing/Checksums&lt;/td&gt;&lt;td&gt;MessageDigest and CRC32&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;OS performance measures&lt;/td&gt;&lt;td&gt;This is poor in Java. You can get the load average but its always 0 on windows.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Co-routines&lt;/td&gt;&lt;td&gt;The closest is fork/join with anonymous classes. In Java 8 methods will become first class objects which is a little closer.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fixed size strings&lt;/td&gt;&lt;td&gt;You can have this in Java. However I assume the point of this is efficiency, which Java is unlikely to match, ever.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Message Queues&lt;/td&gt;&lt;td&gt;JMS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cryptography&lt;/td&gt;&lt;td&gt;Java SE Security&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extend GC to trigger a GC and handle when an object is cleaned up.&lt;/td&gt;&lt;td&gt;System.gc(), finaliser() and PhantomReferences&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;A overflow/underflow safe integer&lt;/td&gt;&lt;td&gt;This would be useful if language support was included, but I doubt that will happen, (like unsigned int)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;unification and backtracking&lt;/td&gt;&lt;td&gt;This could be added in the far future. I imagine after Java 8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Singletons&lt;/td&gt;&lt;td&gt;An &lt;i&gt;enum&lt;/i&gt; with one instance (enum are Objects in Java not int values)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;A Persistent Collections Library.&lt;/td&gt;&lt;td&gt;Java doesn't have much support for functional programming.  This is something which it could have, but I don't imagine it being any time soon.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p/&gt;IMHO, The best suggestions which are missing or could be better in Java are&lt;br /&gt;&lt;p/&gt;&lt;ul&gt;&lt;li&gt;persisted collections&lt;/li&gt;&lt;li&gt;JSon serializaton/deserialization&lt;/li&gt;&lt;li&gt;GPU support&lt;/li&gt;&lt;li&gt;Good OS performance measures&lt;/li&gt;&lt;/ul&gt;&lt;p/&gt;Even more useful would be a common interface and basic support for collections which are distributed and persisted. e.g. standardised/simplified Hazelcast, Terracotta and Hibernate.  @Vyadh points out this is not what is meant by a &lt;i&gt;persisted collection&lt;/i&gt; in functional programming&lt;p/&gt;&lt;h2&gt;Last thoughts&lt;/h2&gt;While I really like Java, but I have never looked at C++ &amp; Boost and thought; if only it were more like Java. (Some of the limitations of the C syntax are a bit backward IMHO)  I have thought this about the refactoring tools in IDEs e.g extracting a method from a body of code (and have it replace any duplicates)&lt;p/&gt;Is making C++ &amp; Boost more like the relatively heavy weight Java a good thing? Or is it better to use a language for it strengths?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5590322336733572929?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5590322336733572929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/is-making-boost-more-like-java-good.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5590322336733572929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5590322336733572929'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/is-making-boost-more-like-java-good.html' title='Is making Boost more like Java a good idea?'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7025935943674473435</id><published>2011-09-10T11:41:00.000+01:00</published><updated>2012-01-22T19:34:51.572Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Memory alignment in C, C++ and Java</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;You might assume that reducing the size of a struct or class saves the same amount of memory. &amp;nbsp;&amp;nbsp; However due to memory alignment in memory allocators it can make no difference, or perhaps more difference than you might expect. &amp;nbsp;&amp;nbsp; This is because the the amount of memory reserved is usually a multiple of the memory alignment. For Java and C this can 8 or 16 bytes.&lt;p/&gt;&lt;h2&gt;Size of memory reserved&lt;/h2&gt;These tests were performed in a 64-bit C program (gcc 4.5.2)  and a 64 JVM (Oracle Java 7) In Java, direct memory is largely a wrapper for malloc and free.&lt;table cellspacing="8" align="center"&gt;&lt;tr&gt;&lt;th&gt;Bytes&lt;/th&gt;&lt;th&gt;C malloc() reserved&lt;/th&gt;&lt;th&gt;Java ByteBuffer.allocateDirect()&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;0 to 24&lt;/td&gt;&lt;td align="center"&gt;32 bytes&lt;/td&gt;&lt;td align="center"&gt;32 bytes + a ByteBuffer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25 to 40&lt;/td&gt;&lt;td align="center"&gt;48 bytes&lt;/td&gt;&lt;td align="center"&gt;48 bytes + a ByteBuffer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;41 to 56&lt;/td&gt;&lt;td align="center"&gt;64 bytes&lt;/td&gt;&lt;td align="center"&gt;64 bytes + a ByteBuffer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;57 to 72&lt;/td&gt;&lt;td align="center"&gt;80 bytes&lt;/td&gt;&lt;td align="center"&gt;80 bytes + a ByteBuffer&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p/&gt;Constructing objects is a similar story&lt;p/&gt;&lt;table cellspacing="8" align="center"&gt;&lt;tr&gt;&lt;th&gt;Number of fields&lt;/th&gt;&lt;th&gt;C class of int&lt;br/&gt;(heap/stack)&lt;/th&gt;&lt;th&gt;C class of void *&lt;br/&gt; (heap/stack)&lt;/th&gt;&lt;th&gt;&amp;nbsp;Java class&amp;nbsp;&lt;br/&gt;&amp;nbsp;with int&amp;nbsp;&lt;/th&gt;&lt;th&gt;Java class&lt;br/&gt; with Object references&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;1&lt;/td&gt;&lt;td&gt;32/16 bytes&lt;/td&gt;&lt;td&gt;32/16 bytes&lt;/td&gt;&lt;td&gt;16 bytes&lt;/td&gt;&lt;td&gt;16 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;2&lt;/td&gt;&lt;td&gt;32/16 bytes&lt;/td&gt;&lt;td&gt;32/16 bytes&lt;/td&gt;&lt;td&gt;24 bytes&lt;/td&gt;&lt;td&gt;24 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;3&lt;/td&gt;&lt;td&gt;32/16 bytes&lt;/td&gt;&lt;td&gt;32/32 bytes&lt;/td&gt;&lt;td&gt;24 bytes&lt;/td&gt;&lt;td&gt;24 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;4&lt;/td&gt;&lt;td&gt;32/16 bytes&lt;/td&gt;&lt;td&gt;48/32 bytes&lt;/td&gt;&lt;td&gt;32 bytes&lt;/td&gt;&lt;td&gt;32 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;5&lt;/td&gt;&lt;td&gt;32/32 bytes&lt;/td&gt;&lt;td&gt;48/48 bytes&lt;/td&gt;&lt;td&gt;32 bytes&lt;/td&gt;&lt;td&gt;32 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;6&lt;/td&gt;&lt;td&gt;32/32 bytes&lt;/td&gt;&lt;td&gt;64/48 bytes&lt;/td&gt;&lt;td&gt;40 bytes&lt;/td&gt;&lt;td&gt;40 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;7&lt;/td&gt;&lt;td&gt;48/32 bytes&lt;/td&gt;&lt;td&gt;64/64 bytes&lt;/td&gt;&lt;td&gt;40 bytes&lt;/td&gt;&lt;td&gt;40 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="center"&gt;8&lt;/td&gt;&lt;td&gt;48/32 bytes&lt;/td&gt;&lt;td&gt;80/64 bytes&lt;/td&gt;&lt;td&gt;48 bytes&lt;/td&gt;&lt;td&gt;48 bytes&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p/&gt;Using a C struct/class on the stack is more efficient than the other approaches for a number of reasons, two of them being that there is no memory management header and no additional pointer/reference (not shown in the table).&lt;p/&gt;Sun/Oracle and OpenJDK 6 and 7 JVMs will use 32-bit references and the 8 byte memory aligned and to support up to 32 GB (8 * 4 G) &amp;nbsp;&amp;nbsp; Most JVMs are less than 32 GB in size making this a useful optimisation. &amp;nbsp;&amp;nbsp;Note: Part of the reason that JVMs are usually 1 to 4 GB in size is that the worst case Full GC time is typically 1 second per GB of heap and a 30 second full CG time is to long for most applications.&amp;nbsp;&amp;nbsp;  The typical way around this full GC time problem is to keep the working size of the heap to a few GB and use an external database or  heapless "direct" and "memory mapped" memory.&lt;p/&gt;Another solution for Java is to use a pause less concurrent collector such as that provided by Azul. &amp;nbsp;&amp;nbsp;They claim excellent scalability beyond 40 GB of heap, but don't openly list their costs ;)&lt;p/&gt;&lt;h2&gt;Why does this matter?&lt;/h2&gt;Say you have a class like this&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;class MyClass {&lt;br /&gt;    int num;&lt;br /&gt;    short value;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;In C, how much memory is saved by changing &lt;i&gt;num&lt;/i&gt; to a &lt;i&gt;short&lt;/i&gt; or how much more is consumed of with make it &lt;i&gt;long long&lt;/i&gt;. &amp;nbsp;&amp;nbsp; The answer is likely to be none at all (unless you have an array of these)In Java, it could make a difference as the alignment size is different.Conversely, if the C class/struct is 16 or 17 bytes, it can make the size on the stack be 16 or 32 bytes. Similarly being 24 or 25 bytes can make the malloc'ed size used 32 or 48 bytes long.&lt;h2&gt;The code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/cpp/MemoryAlignment/main.cpp"&gt;&lt;b&gt;MemoryAlignment/main.cpp&lt;/b&gt;&lt;/a&gt; and  &lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/memory/MemoryAlignment.java"&gt;&lt;b&gt;MemoryAlignment.java&lt;/b&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7025935943674473435?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7025935943674473435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/memory-alignment-in-c-c-and-java.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7025935943674473435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7025935943674473435'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/memory-alignment-in-c-c-and-java.html' title='Memory alignment in C, C++ and Java'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6498140260981439018</id><published>2011-09-08T18:33:00.002+01:00</published><updated>2012-01-22T19:37:34.770Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Why thread priority rarely matters</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Its is tempting to use the Thread.setPriority() option in Java.  However for many applications this is more a comment for the developer than something which will make a measurable difference. esp. with multi-core systems.&lt;p/&gt;&lt;h2&gt;Why it usually doesn't matter&lt;/h2&gt;If you have plenty of free CPU, every thread which can run will run. The OS has no reason not to run a low priority thread or process when it has free resources.&lt;p/&gt;If your system is close to 100% of CPU on &lt;b&gt;every core&lt;/b&gt;, the OS has to make a choice as to how much time each thread or process gets on the CPU and it is likely to give favour to higher priority threads over lower priority threads, (many OSes ignore the hint) and other factors are likely to matter as well.&lt;p/&gt;This priority only extends to raw CPU. Threads compete equally for CPU cache, heap space, CPU to memory bandwidth, file cache, disk IO, network IO and everything else. If any of these resource are in competition, they are all equal.&lt;p/&gt;To set a high priority on Windows you need to be an administrator and on Linux you need to be root to set the priority of a thread. Different Implementations and OSes can ignore this hint.&lt;p/&gt;&lt;h2&gt;Summary&lt;/h2&gt;If your application is heavily CPU bound, using every core, not using any other system resources significantly like IO or memory and your OS doesn't ignore the hint, the thread priority might make a difference.&lt;p/&gt;If in doubt, I wouldn't bother setting it because someone might think it does something. ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6498140260981439018?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6498140260981439018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/why-thread-priority-rarely-matters.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6498140260981439018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6498140260981439018'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/why-thread-priority-rarely-matters.html' title='Why thread priority rarely matters'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-606745495385573781</id><published>2011-09-07T14:26:00.002+01:00</published><updated>2012-01-26T15:16:51.860Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Order of elements in a hash collection</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;While is it generally understood that keys or elements in a HashMap or HashSet occur in a pseudo random order, what is not obvious is that two collections with the same elements can be in different orders.  This is because the capacity of the collection also determines the order the elements appear.&lt;p/&gt;This can be important if you have only an Iterator to a Set.  It is easy to assume the order will be the same and most of the time it will work (you can write unit tests with this assumption which will  pass) However, if the Set has a different capacity (something you don't normally know or worry about) the order will change.&lt;p/&gt;&lt;h2&gt;Find what order elements can appear in&lt;/h2&gt;The following test adds the same 11 elements to a HashSet, each time with a different collection and prints out all the combinations it finds.&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;@Test&lt;br /&gt;public void testSetOrder() {&lt;br /&gt;  Set&amp;lt;String&gt; order = new HashSet&amp;lt;String&gt;();&lt;br /&gt;  Collection&amp;lt;String&gt; elements = Arrays.asList(&lt;br /&gt;                     "zero, one, two, three, four, five, six, seven, eight, nine, ten".split(", "));&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;  for(int i=1;i &gt; 0;i*=2) {&lt;br /&gt;    Set&lt;String&gt; set = new HashSet&amp;lt;String&gt;(i, 100.0f);&lt;br /&gt;    set.addAll(elements);&lt;br /&gt;    String str = set.toString();&lt;br /&gt;    if (order.add(str))&lt;br /&gt;      System.out.println("HashSet("+i+") order was "+str);&lt;br /&gt;  }&lt;br /&gt;  } catch(OutOfMemoryError ignored) { }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;prints this output&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;HashSet(1) order was [ten, nine, eight, seven, six, five, four, three, two, one, zero]&lt;br /&gt;HashSet(2) order was [eight, three, zero, ten, nine, seven, six, five, four, two, one]&lt;br /&gt;HashSet(4) order was [three, zero, ten, two, eight, nine, seven, six, five, four, one]&lt;br /&gt;HashSet(8) order was [three, ten, two, seven, five, four, zero, eight, nine, six, one]&lt;br /&gt;HashSet(16) order was [ten, two, seven, five, nine, one, three, four, zero, eight, six]&lt;br /&gt;HashSet(32) order was [ten, five, nine, one, zero, eight, six, two, seven, three, four]&lt;br /&gt;HashSet(64) order was [ten, nine, one, zero, eight, six, three, four, five, two, seven]&lt;br /&gt;HashSet(128) order was [ten, nine, zero, eight, three, one, six, four, five, two, seven]&lt;br /&gt;HashSet(256) order was [nine, zero, six, ten, eight, three, one, four, five, two, seven]&lt;br /&gt;HashSet(512) order was [six, four, five, seven, nine, zero, ten, eight, three, one, two]&lt;br /&gt;HashSet(1024) order was [six, five, nine, eight, two, four, seven, zero, ten, three, one]&lt;br /&gt;HashSet(2048) order was [eight, seven, zero, six, five, nine, two, four, ten, three, one]&lt;br /&gt;HashSet(4096) order was [eight, seven, zero, six, five, nine, three, one, two, four, ten]&lt;br /&gt;HashSet(8192) order was [eight, seven, zero, six, nine, four, five, three, one, two, ten]&lt;br /&gt;HashSet(16384) order was [eight, zero, nine, five, three, two, ten, seven, six, four, one]&lt;br /&gt;HashSet(32768) order was [zero, six, one, eight, nine, five, three, two, ten, seven, four]&lt;br /&gt;HashSet(65536) order was [zero, eight, five, seven, four, six, one, nine, three, two, ten]&lt;br /&gt;HashSet(131072) order was [nine, zero, eight, five, seven, four, six, one, three, two, ten]&lt;br /&gt;HashSet(262144) order was [nine, five, seven, six, one, two, ten, zero, eight, four, three]&lt;br /&gt;HashSet(524288) order was [nine, seven, six, one, two, ten, zero, four, five, eight, three]&lt;br /&gt;HashSet(1048576) order was [nine, seven, six, one, two, ten, four, eight, three, zero, five]&lt;br /&gt;HashSet(2097152) order was [seven, six, one, two, ten, five, nine, four, eight, three, zero]&lt;br /&gt;HashSet(4194304) order was [six, one, two, ten, eight, seven, five, nine, four, three, zero]&lt;br /&gt;HashSet(8388608) order was [six, one, two, ten, eight, five, nine, four, zero, seven, three]&lt;br /&gt;HashSet(16777216) order was [six, one, two, ten, five, nine, four, zero, eight, seven, three]&lt;br /&gt;HashSet(33554432) order was [six, one, two, ten, five, nine, four, zero, seven, three, eight]&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;As you can see almost every initial capacity has a different order (even for a relatively small number of elements)&lt;p/&gt;Single note: with a capacity of 1 and a large load factor (to prevent it resizing the capacity), the HashSet becomes a linked list which shows object in reverse order. i.e. as there is 100% collisions.&lt;p/&gt;&lt;hr/&gt;As @Alex Zhang, notes, if you have small positive numbers (Byte, Short, Integer, Long) and you allow the capacity to grow naturally, you will get those numbers in order.  However if you vary this a little the pattern breaks up.&lt;pre&gt;&lt;br /&gt;Collection&amp;lt;Integer&gt; col = Arrays.asList(-1, 1, 10, 100, 1000, 10000, 100000, 1000000);&lt;br /&gt;for (int i = 1; i &lt; 5000000; i *= 2) {&lt;br /&gt;    Set&amp;lt;Integer&gt; set = new HashSet&amp;lt;Integer&gt;(i, 100f);&lt;br /&gt;    set.addAll(col);&lt;br /&gt;    System.out.println("HashSet(" + i + ") " + set);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints&lt;pre&gt;&lt;br /&gt;HashSet(1) [1000000, 100000, 10000, 1000, 100, 10, 1, -1]&lt;br /&gt;HashSet(2) [1000000, 100000, 100, 10, 10000, 1000, 1, -1]&lt;br /&gt;HashSet(4) [10000, 1000, 1, 1000000, 100000, 100, 10, -1]&lt;br /&gt;HashSet(8) [1000, 1, 1000000, 100, 10, 10000, 100000, -1]&lt;br /&gt;HashSet(16) [1000, 1, 100, 1000000, 10, 10000, 100000, -1]&lt;br /&gt;HashSet(32) [1, 100, 10, 10000, 1000, 1000000, 100000, -1]&lt;br /&gt;HashSet(64) [1, 10, 1000, 1000000, 100000, -1, 100, 10000]&lt;br /&gt;HashSet(128) [1, 10, 1000000, -1, 10000, 1000, 100000, 100]&lt;br /&gt;HashSet(256) [1, 10, 1000000, -1, 10000, 100, 1000, 100000]&lt;br /&gt;HashSet(512) [1, 10, 1000000, 100, -1, 10000, 1000, 100000]&lt;br /&gt;HashSet(1024) [1, 10, 1000000, 100, 10000, 100000, -1, 1000]&lt;br /&gt;HashSet(2048) [1, 10, 1000000, 100, 1000, 10000, 100000, -1]&lt;br /&gt;HashSet(4096) [1, 10, 100, 1000, 10000, 1000000, 100000, -1]&lt;br /&gt;HashSet(8192) [1, 10, 100, 1000, 10000, 1000000, -1, 100000]&lt;br /&gt;HashSet(16384) [1, 10, 100, 1000, 100000, 10000, 1000000, -1]&lt;br /&gt;HashSet(32768) [1, 10, 100, 1000, 100000, 10000, 1000000, -1]&lt;br /&gt;HashSet(65536) [1, 10, 100, 1000, 10000, 100000, 1000000, -1]&lt;br /&gt;HashSet(131072) [1, 10, 100, 1000, 10000, -1, 100000, 1000000]&lt;br /&gt;HashSet(262144) [1, 10, 100, 1000, 10000, -1, 100000, 1000000]&lt;br /&gt;HashSet(524288) [1, 10, 100, 1000, 10000, -1, 100000, 1000000]&lt;br /&gt;HashSet(1048576) [1, 10, 100, 1000, 10000, -1, 100000, 1000000]&lt;br /&gt;HashSet(2097152) [1, 10, 100, 1000, 10000, 100000, 1000000, -1]&lt;br /&gt;HashSet(4194304) [1, 10, 100, 1000, 10000, 100000, 1000000, -1]&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/collections/OrdersOfHashSet.java"&gt;&lt;h2&gt;The Code&lt;/h2&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-606745495385573781?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/606745495385573781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/order-of-elements-in-hash-collection.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/606745495385573781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/606745495385573781'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/order-of-elements-in-hash-collection.html' title='Order of elements in a hash collection'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7983566157904747958</id><published>2011-09-02T10:33:00.000+01:00</published><updated>2012-01-26T15:15:47.250Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>The importance of innovation</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;In a recent article I wrote about how you do things can make a big difference. &lt;a href="http://vanillajava.blogspot.com/2011/08/java-can-be-significantly-faster-than-c.html"&gt;Java can be significantly faster than C&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The aim was to show how you can use the same algorithm (the what), implemented with a different approach (the how) and make significant improvement in performance.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What I have learnt&lt;/h2&gt;I now understand that the purpose of the web site is compare languages and remove the developer from the equation by making "the how" as similar to what has been written before as possible.  I see this is legitimate approach to have a fair comparison of languages.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Importance of Innovation&lt;/h2&gt;To me it shows you what can happen when you deliberately limit innovation, even if you have good reasons to do so. If you prescribe one way of implementing a requirement, it can make a big difference to the solution you can achieve.&lt;br /&gt;&lt;br /&gt;In the case of this benchmark, following the requirements as closely as I could, but admittedly disregarding how these requirements had been achieved before resulted in a solution which was 2.2x faster than the previous C solutions and 4.6x faster than the previous Java solution.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7983566157904747958?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7983566157904747958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/09/importance-of-innovation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7983566157904747958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7983566157904747958'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/09/importance-of-innovation.html' title='The importance of innovation'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-9156196552658425805</id><published>2011-08-31T21:19:00.007+01:00</published><updated>2012-01-22T19:34:51.600Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Java can be significantly faster than C</title><content type='html'>&lt;h2&gt;Preface&lt;/h2&gt;When I wrote this article it was to comment on how writing the same algorithm implement a different way can make a major difference.  I now believe this is not the point of the web site perhaps shouldn't be the point of this article either.  I have written a follow up article.&lt;br /&gt;&lt;a href="http://vanillajava.blogspot.com/2011/09/importance-of-innovation.html"&gt;&lt;br /&gt;&lt;b&gt;The importance of innovation&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Overview&lt;/h2&gt;Whether you use Java or C is not always as important as the approach you use. By "approach" I mean; algorithms not specified in the requirements or "the how" to do something.&lt;br /&gt;&lt;br /&gt;You might not see this as a fair test of Java vs C, but in the real world human factors are matter.  There is no point saying C is faster in theory but there isn't anyone available to make it so.  Its like getting a very cheap price on an item which is not in stock. ;)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Benchmark Shootout&lt;/h2&gt;Java is temporarily the fastest for this particular &lt;a href="http://shootout.alioth.debian.org/u64q/benchmark.php?test=knucleotide&amp;amp;lang=all"&gt;knucleotide benchmark.&lt;/a&gt; It is quite likely that if the algorithm I used is translated to C it would be faster again. But for the moment Java is fastest because it uses a different approach in a number of key places.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Tal-tYJz4As/Tl6Xo4wo2OI/AAAAAAAAAFM/LEsv5BbS-zY/s1600/k-nucleotide-benchmark.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Tal-tYJz4As/Tl6Xo4wo2OI/AAAAAAAAAFM/LEsv5BbS-zY/s1600/k-nucleotide-benchmark.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Benchmark results at Wed 31st August 2011.&lt;br /&gt;&lt;br /&gt;If anyone is interested in translating it to C, I would like to know how much faster it is. ;) &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Making it faster again&lt;/h2&gt;On my home PC it only takes 0.684 ms, a gain of 2.5x.  My PC uses newer hardware (and an over clocked CPU)&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;&lt;a href="http://shootout.alioth.debian.org/u64q/program.php?test=knucleotide&amp;amp;lang=java&amp;amp;id=4"&gt;The code &lt;/a&gt;&lt;/h1&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-9156196552658425805?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/9156196552658425805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/java-can-be-significantly-faster-than-c.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/9156196552658425805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/9156196552658425805'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/java-can-be-significantly-faster-than-c.html' title='Java can be significantly faster than C'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-Tal-tYJz4As/Tl6Xo4wo2OI/AAAAAAAAAFM/LEsv5BbS-zY/s72-c/k-nucleotide-benchmark.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4181612871936779646</id><published>2011-08-30T16:49:00.001+01:00</published><updated>2012-01-22T19:34:51.508Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>MethodHandle performance in Java 7</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;A new feature in Java 7 provides a MethodHandle which "is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values"&lt;br /&gt;&lt;br /&gt;This supports currying methods and many other features lambda based languages take for granted.&lt;br /&gt;&lt;br /&gt;Note: this method compares invoke() in reflections and MethodHandles.  I couldn't get invokeExact to work when returning a primitive (it got confused between &lt;i&gt;int&lt;/i&gt; and &lt;i&gt;Integer&lt;/i&gt;) However another benchmark &lt;a href="http://andrewtill.blogspot.com/2011/08/using-method-handles.html"&gt;Using Method Handles by Andrew Till&lt;/a&gt; indicated using invokeExact is much faster than using Method.invoke() with reflections.Thank you &lt;a href="http://wensveen.wordpress.com/"&gt;wensveen&lt;/a&gt; for the link.&lt;h2&gt;Example&lt;/h2&gt;Say you have two method&lt;br /&gt;&lt;pre&gt;public static int multiply(int i, int j) {&lt;br /&gt;    return i * j;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static int subtract(int i, int j) {&lt;br /&gt;    return i - j;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;With MethodHandle you can not only get a reference to the Method (like in reflection) but you can construct new MethodHandles. For example, you can bind the Object concerned or one of the arguments.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;final Lookup lookup = lookup();&lt;br /&gt;MethodHandle multiply = lookup.findStatic(MethodHandleMain.class, &lt;br /&gt;                          "multiply", methodType(int.class, int.class, int.class));&lt;br /&gt;MethodHandle quadruple = insertArguments(multiply, 1, 4);&lt;br /&gt;&lt;br /&gt;System.out.println(multiply.invoke(3, 2)); // prints 6&lt;br /&gt;System.out.println(quadruple.invoke(5)); // prints 20&lt;br /&gt;&lt;br /&gt;MethodHandle subtract = lookup.findStatic(MethodHandleMain.class, &lt;br /&gt;                         "subtract", methodType(int.class, int.class, int.class));&lt;br /&gt;MethodHandle subtractFromFour = insertArguments(subtract, 0, 4);&lt;br /&gt;MethodHandle fourLess = insertArguments(subtract, 1, 4);&lt;br /&gt;System.out.println(subtract.invoke(10, 5)); // prints 5&lt;br /&gt;System.out.println(subtractFromFour.invoke(10)); // prints -6&lt;br /&gt;System.out.println(fourLess.invoke(10)); // prints 6&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Performance&lt;/h2&gt;This is very cool, but how does it perform? ;)&lt;br /&gt;&lt;br /&gt;There is a lot of potential for it to perform very well and the interface is cleaner than plain reflections however when comparing the alternatives, it doesn't perform as well as the alternatives in Java 7 (update 0)&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Call method&lt;/th&gt;&lt;th&gt;Average time per call&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Direct Method calls&lt;/td&gt;&lt;td&gt;31 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Reflections&lt;/td&gt;&lt;td&gt;353 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MethodHandle.invoke()&lt;/td&gt;&lt;td&gt;5,378 ns&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;It is a very cool API and hopefully it will perform much better in the future. ;)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/methodhandles/MethodHandleMain.java"&gt;&lt;b&gt;MethodHandleTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4181612871936779646?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4181612871936779646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/methodhandle-performance-in-java-7.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4181612871936779646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4181612871936779646'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/methodhandle-performance-in-java-7.html' title='MethodHandle performance in Java 7'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6073534200818935219</id><published>2011-08-30T14:00:00.005+01:00</published><updated>2012-01-22T19:34:51.553Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Added Memory Mapped support to HugeCollections</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The Huge collections library is designed to support large collections on data in memory efficiently without GC impact. It does this using heap less memory and generated code for efficiency.&lt;br /&gt;&lt;br /&gt;One of the benefits of this approach is memory mapped files can be larger than the available memory, use trivial heap and no direct memory.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Memory mapping&lt;/h2&gt;Loading large amounts of data is time consuming so being able to re-use a store persisted to disk can improve efficiency.  With the use of SSD drives the amount of "memory" a Java system can access is effectively extended provided it can be used.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;How does it perform&lt;/h2&gt;Adding an object with 12 fields and reading objects sequentially takes about 110 ns for one billion elements. It takes less than two minutes to add all the entries, and the same to read all the elements. &lt;br /&gt;&lt;br /&gt;Random access is much more expensive until all the data is in memory, with a fast SSD drive it takes about 600 ns when most of the data is in cache, slower if this is not the case.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-8xUmT-t_krs/TlzteSoO8EI/AAAAAAAAAE8/WY3exCEqW6s/s1600/top.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-8xUmT-t_krs/TlzteSoO8EI/AAAAAAAAAE8/WY3exCEqW6s/s1600/top.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Java has a collection with one billion elements. (Top)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;As you can see the machine has only 24 GB and yet it the Java process is using 37.6G of virtual memory as this includes 33 GB of mapped files.&amp;nbsp; The actual memory used is 3.4 GB as this is how much is kept in memory.&lt;br /&gt;&lt;br /&gt;The shared memory is the same as the memory mapped files can be shared with other processes (however writing to them in a safe manner is not supported)&lt;br /&gt;&lt;h2&gt;Creating the huge collection&lt;/h2&gt;Like previous huge collections, an anonymous sub-class of the builder is used to create the collection.  The &lt;i&gt;baseDirectory&lt;/i&gt; is the base directory of where the list is stored.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;HugeArrayList&lt;mutabletypes&gt; list = new HugeArrayBuilder&lt;mutabletypes&gt;() {{&lt;br /&gt;    baseDirectory = TEMPORARY_SPACE;&lt;br /&gt;    capacity = length;&lt;br /&gt;    allocationSize = 32 * 1024 * 1024;&lt;br /&gt;}}.create();&lt;br /&gt;&lt;br /&gt;// update or lookup the collection&lt;br /&gt;list.add(...);&lt;br /&gt;&lt;br /&gt;MutableType mt = list.get(900*1000*1000);&lt;br /&gt;&lt;br /&gt;// close to flush the data, close files and un-map the collection.&lt;br /&gt;list.close();&lt;br /&gt;&lt;/mutabletypes&gt;&lt;/mutabletypes&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Links&lt;/h2&gt;&lt;a href="http://code.google.com/p/vanilla-java/wiki/HugeCollections"&gt;Wiki&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/vanilla-java/downloads/list"&gt;Downloads&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/vanilla-java/source/browse/#svn%2Ftrunk%2Fcollections%2Fsrc%2Ftest%2Fjava%2Fvanilla%2Fjava%2Fcollections"&gt;Unit Tests and examples&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;To follow&lt;/h2&gt;Support for a Huge Map with one index under development. Additional non-unique indexes also planned.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6073534200818935219?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6073534200818935219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/added-memory-mapped-support-to.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6073534200818935219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6073534200818935219'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/added-memory-mapped-support-to.html' title='Added Memory Mapped support to HugeCollections'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-8xUmT-t_krs/TlzteSoO8EI/AAAAAAAAAE8/WY3exCEqW6s/s72-c/top.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-476682504163934440</id><published>2011-08-28T18:08:00.001+01:00</published><updated>2012-01-26T15:17:51.402Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>Writing to stdin</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;System.in or stdin is usually used as an InputStream. However on Linux you can access this stream in other ways.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Accessing file descriptor 0&lt;/h2&gt;In linux, each file descriptor is accessible via &lt;i&gt;/proc/{process-id}/fd/{file-id}&lt;/i&gt;  You can use this to see what files a process has open but also see the contents of a file.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Writing and memory mapping&lt;/h2&gt;Getting the process id in Java is obscure, but once you have this you can re-open existing file descriptors such as stdin, file descriptor 0.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;int processId = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);&lt;br /&gt;RandomAccessFile raf = new RandomAccessFile("/proc/" + processId + "/fd/0", "rw");&lt;br /&gt;final FileChannel fc = raf.getChannel();&lt;br /&gt;final MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());&lt;br /&gt;bb.putLong(System.nanoTime());&lt;br /&gt;bb.force();&lt;br /&gt;raf.close();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This opens the &lt;i&gt;System.in&lt;/i&gt; is a read-write mode and memory maps it before changing its contents.&lt;br /&gt;&lt;br /&gt;When you run this program it looks like&lt;br /&gt;&lt;pre&gt;$ echo "        " &gt; file.dat&lt;br /&gt;$ od -xc file.dat&lt;br /&gt;0000000    2020    2020    2020    2020    000a&lt;br /&gt;                                         \n&lt;br /&gt;0000011&lt;br /&gt;$ java -cp . Main &lt; file.dat&lt;br /&gt;$ od -xc file.dat&lt;br /&gt;0000000    0000    5522    11a9    79c6    000a&lt;br /&gt;         \0  \0   "   U 251 021 306   y  \n&lt;br /&gt;0000011&lt;br /&gt;&lt;/pre&gt;At first is rather surprising you can write to stdin or even memory map it. What happens if stdin is not a real file.&lt;pre&gt;$ echo "        " | java -cp . Main&lt;br /&gt;Exception in thread "main" java.io.FileNotFoundException: /proc/7935/fd/0 (Text file busy)&lt;br /&gt;	at java.io.RandomAccessFile.open(Native Method)&lt;br /&gt;	at java.io.RandomAccessFile.&lt;init&gt;(RandomAccessFile.java:233)&lt;br /&gt;	at java.io.RandomAccessFile.&lt;init&gt;(RandomAccessFile.java:118)&lt;br /&gt;	at Main.main(Main.java:10)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-476682504163934440?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/476682504163934440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/writing-to-stdin.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/476682504163934440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/476682504163934440'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/writing-to-stdin.html' title='Writing to stdin'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4880912981731584822</id><published>2011-08-18T12:07:00.011+01:00</published><updated>2012-01-22T19:34:51.534Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Avoiding Java Serialization to increase performance</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Many frameworks for storing objects in an off-line or cached manner, use standard Java Serialization to encode the object as bytes which can be turned back into the original object.&lt;br /&gt;&lt;br /&gt;Java Serialization is generic and can serialise just about any type of object.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Why avoid it&lt;/h2&gt;The main problem with Java Serialization is performance and efficiency.  Java serialization is &lt;b&gt;much&lt;/b&gt; slower than using in memory stores and tends to significantly expand the size of the object. Java Serialization also creates a lot of garbage.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Access performance&lt;/h2&gt;Say you have a collection and you want to update a field of many elements. Something like&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;for (MutableTypes mt : mts) {&lt;br /&gt;   mt.setInt(mt.getInt());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you update one million elements for about five seconds how long does each one take.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Collection&lt;/th&gt;&lt;th&gt;Fast PC&lt;/th&gt;&lt;th&gt;Labtop&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Huge Collection&lt;/td&gt;&lt;td align="right"&gt;5.1 ns&lt;/td&gt;&lt;td align="right"&gt;33 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;JavaBean&gt;&lt;/td&gt;&lt;td align="right"&gt;6.5 ns&lt;/td&gt;&lt;td align="right"&gt;54 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;byte[]&gt; with Externalizable&lt;/td&gt;&lt;td align="right"&gt;5,841 ns&lt;/td&gt;&lt;td align="right"&gt;17,508 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;byte[]&gt; with Serializable&lt;/td&gt;&lt;td align="right"&gt;23,217 ns&lt;/td&gt;&lt;td align="right"&gt;60,947 ns&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;If you update ten million elements for five seconds or more&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Collection&lt;/th&gt;&lt;th&gt;Fast PC&lt;/th&gt;&lt;th&gt;Labtop&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Huge Collection&lt;/td&gt;&lt;td align="right"&gt;5.4 ns&lt;/td&gt;&lt;td align="right"&gt;33 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;JavaBean&gt;&lt;/td&gt;&lt;td align="right"&gt;6.6 ns&lt;/td&gt;&lt;td align="right"&gt;60 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;byte[]&gt; with Externalizable&lt;/td&gt;&lt;td align="right"&gt;6,073 ns&lt;/td&gt;&lt;td align="right"&gt;71,691 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;byte[]&gt; with Serializable&lt;/td&gt;&lt;td align="right"&gt;22,943 ns&lt;/td&gt;&lt;td align="right"&gt;failed&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;* Fast PC - 3.8 GHz i7 with 24 GB of memory.&lt;br /&gt;* Labtop - 2.3 GHz Core Duo with 4 GB of memory.&lt;br /&gt;&lt;br /&gt;Huge Collection stores information in a column based based, so accessing just one field is much more CPU cache efficient than using JavaBeans. If you were to update every field, it would be about 2x or more times slower.&lt;br /&gt;&lt;br /&gt;Using an optimised Externalizable is much faster than the default Serializable, however is it 400x slower than using a a JavaBean&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Memory efficiency&lt;/h2&gt;The per object memory used is also important as it impacts how many object you can store and the performance of accessing those objects.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Collection type&lt;/th&gt;&lt;th&gt;Heap used&lt;br /&gt;per million&lt;/th&gt;&lt;th&gt;Direct memory&lt;br /&gt;per million&lt;/th&gt;&lt;th&gt;Garbage produced&lt;br /&gt;per million&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Huge Collection&lt;/td&gt;&lt;td align="right"&gt;0.09 MB&lt;/td&gt;&lt;td align="right"&gt;34 MB&lt;/td&gt;&lt;td align="right"&gt;80 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;JavaBean&gt;&lt;/td&gt;&lt;td align="right"&gt;68 MB&lt;/td&gt;&lt;td align="right"&gt;none&lt;/td&gt;&lt;td align="right"&gt;30 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;byte[]&gt; using Externalizable&lt;/td&gt;&lt;td align="right"&gt;140 MB&lt;/td&gt;&lt;td align="right"&gt;none&lt;/td&gt;&lt;td align="right"&gt;5,941 MB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;byte[]&gt;&lt;/td&gt;&lt;td align="right"&gt;506 MB&lt;/td&gt;&lt;td align="right"&gt;none&lt;/td&gt;&lt;td align="right"&gt;16,746 MB&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;This test was performed on a collection of one million elements. &lt;br /&gt;&lt;br /&gt;To test the amount of garbage produced I set the Eden size target greater than 17 GB so no GC would be performed.&lt;br /&gt;&lt;pre&gt;-mx22g -XX:NewSize=20g -XX:-UseTLAB -verbosegc&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;Having an optimised readExternal/writeExternal can improve performance and the size of a serialised object by 2-4 times, however if you need to maximise performance and efficiency you can gain much more by not using it.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related Links&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/08/collections-library-for-millions-of.html"&gt;&lt;b&gt;Collections Library for millions of elements&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ehcache.org/documentation/user-guide/bigmemory#performance-comparisons"&gt;&lt;b&gt;Ehcache BigMemory performance&lt;/b&gt;&lt;/a&gt; typical latency is around 200 &amp;mu;s for huge caches, indicating that serialization might not be the only bottleneck.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/vanilla-java/source/browse/trunk/collections/src/test/java/vanilla/java/collections/HugeArrayVsSerializationTest.java"&gt;HugeArrayVsSerializationTest.java&lt;/a&gt; The test code&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/vanilla-java/source/browse/trunk/collections/src/test/java/vanilla/java/collections/MutableTypes.java"&gt;MutableTypes.java&lt;/a&gt; The data type used for testing different implementations.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4880912981731584822?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4880912981731584822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/avoiding-java-serialization-to-increase.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4880912981731584822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4880912981731584822'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/avoiding-java-serialization-to-increase.html' title='Avoiding Java Serialization to increase performance'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1499441893414609380</id><published>2011-08-18T10:06:00.000+01:00</published><updated>2012-01-26T15:17:51.382Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>Generating ASCII Banners</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Generating ASCII banners can be tedious. However there is a simple short cut, use an image to display the text.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Creating an invisible image&lt;/h2&gt;You don't have to have a GUI to create images. The following code creates an image in memory without a GUI.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;BufferedImage image = new BufferedImage(144, 32, BufferedImage.TYPE_INT_RGB);&lt;br /&gt;Graphics g = image.getGraphics();&lt;br /&gt;g.setFont(new Font("Dialog", Font.PLAIN, 24));&lt;br /&gt;Graphics2D graphics = (Graphics2D) g;&lt;br /&gt;graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,&lt;br /&gt;        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);&lt;br /&gt;graphics.drawString("Hello World!", 6, 24);&lt;br /&gt;ImageIO.write(image, "png", new File("text.png"));&lt;br /&gt;&lt;br /&gt;for (int y = 0; y &amp;lt; 32; y++) {&lt;br /&gt;    StringBuilder sb = new StringBuilder();&lt;br /&gt;    for (int x = 0; x &amp;lt; 144; x++)&lt;br /&gt;        sb.append(image.getRGB(x, y) == -16777216 ? " " : image.getRGB(x, y) == -1 ? "#" : "*");&lt;br /&gt;    if (sb.toString().trim().isEmpty()) continue;&lt;br /&gt;    System.out.println(sb);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;it display the image  &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://i.stack.imgur.com/n0lMV.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://i.stack.imgur.com/n0lMV.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;By scanning this image you can create text like.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;##         ##                 ##    ##                      *#*      *##**      *#*                       ##            ##     ##       &lt;br /&gt;##         ##                 ##    ##                      *#*      *###*      *#*                       ##            ##     ##       &lt;br /&gt;##         ##                 ##    ##                      *#*      *#*#*      *#*                       ##            ##     ##       &lt;br /&gt;##         ##                 ##    ##                      *#*     *******     *#*                       ##            ##     ##       &lt;br /&gt;##         ##     *******     ##    ##     *******           *#*    *#* *#*    *#*    *******     ##****  ##     ****** ##     ##       &lt;br /&gt;##         ##    **#####**    ##    ##    **#####**          *#*    *#* *#*    *#*   **#####**    ##*##*  ##    **#####*##     ##       &lt;br /&gt;##         ##   **#*****#**   ##    ##   **#** **#**         *#*   **#* *#*    *#*  **#** **#**   ##****  ##   **#** ***##     ##       &lt;br /&gt;#############   *#*     *#*   ##    ##   *#*     *#*         *#*   *#*   *#*   *#*  *#*     *#*   ##*     ##   *#*     *##     ##       &lt;br /&gt;#############   *#*     *#*   ##    ##   *#*     *#*         ****  *#*   *#*  ****  *#*     *#*   ##*     ##   *#*     *##     ##       &lt;br /&gt;##         ##   *#########*   ##    ##   *#*     *#*          *#*  *#*   *#*  *#*   *#*     *#*   ##      ##   *#*     *##     ##       &lt;br /&gt;##         ##   *#########*   ##    ##   *#       #*          *#* *#*     *#* *#*   *#       #*   ##      ##   *#       ##     ##       &lt;br /&gt;##         ##   *#*           ##    ##   *#*     *#*          *#* *#*     *#* *#*   *#*     *#*   ##      ##   *#*     *##     ##       &lt;br /&gt;##         ##   *#*           ##    ##   *#*     *#*          *****#*     *#*****   *#*     *#*   ##      ##   *#*     *##     ##       &lt;br /&gt;##         ##   *#*     *#*   ##    ##   *#*     *#*           *#*#*       *#*#*    *#*     *#*   ##      ##   *#*     *##              &lt;br /&gt;##         ##   **#** *****   ##    ##   **#** **#**           *#*#*       *#*#*    **#** **#**   ##      ##   **#** ***##              &lt;br /&gt;##         ##    **######*    ##    ##    **#####**            *###*       *###*     **#####**    ##      ##    **#####*##     ##       &lt;br /&gt;##         ##     *******     ##    ##     *******             *##**       **##*      *******     ##      ##     ****** ##     ##    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;change to BOLD&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;###       ###                 ###    ###                        *##*     *###*     *##*                          ###            ###    #&lt;br /&gt;###       ###                 ###    ###                        *##*     *###*     *##*                          ###            ###    #&lt;br /&gt;###       ###                 ###    ###                        *##*     *###*     *##*                          ###            ###    #&lt;br /&gt;###       ###                 ###    ###                        **##*   **###**   *##**                          ###            ###    #&lt;br /&gt;###       ###     *******     ###    ###      *******            *##*   *##*##*   *##*     *******      ###****  ###     ****** ###    *&lt;br /&gt;###       ###    **#####**    ###    ###    **#######**          *##*   *##*##*   *##*   **#######**    ###*##*  ###    **#####*###    *&lt;br /&gt;###       ###   **#######**   ###    ###    *#########*          *##**  *#* *#*  **#**   *#########*    #####**  ###   **##########    *&lt;br /&gt;#############   *##** **##*   ###    ###   *###** **###*          *##* *##* *##* *##*   *###** **###*   ###**    ###   *##******###    *&lt;br /&gt;#############   *##*   *##*   ###    ###   *##*     *##*          *##* *##* *##* *##*   *##*     *##*   ###*     ###   *##*    *###    *&lt;br /&gt;#############   *#########*   ###    ###   *##*     *##*          *##* *##* **#* *##*   *##*     *##*   ###*     ###   *##*    *###    *&lt;br /&gt;###       ###   *#########*   ###    ###   ###       ##*           *##*##*   *#**##*    ###       ##*   ###*     ###   *##      ###    *&lt;br /&gt;###       ###   *##*          ###    ###   *##*     *##*           *##*##*   *##*##*    *##*     *##*   ###      ###   *##*    *###    *&lt;br /&gt;###       ###   *##*          ###    ###   *##*     *##*           *#####*   *#####*    *##*     *##*   ###      ###   *##*    *###    *&lt;br /&gt;###       ###   *##*****##*   ###    ###   *###** **###*           **###**    *###**    *###** **###*   ###      ###   *##******###     &lt;br /&gt;###       ###   **########*   ###    ###    *#########*             *###*     *###*      *#########*    ###      ###   **##########    #&lt;br /&gt;###       ###    **######*    ###    ###    **#######**             *###*     *###*      **#######**    ###      ###    **#####*###    #&lt;br /&gt;###       ###     *******     ###    ###      *******               *###*     *###*        *******      ###      ###     *******###    #&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;in ITALIC&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;*#*        *#*                *#*   *#*                      *#*       *##*      **#*                      *#*          *#*  *#*      &lt;br /&gt;   *#*        *#*                *#*   *#*                      *#*      *###*      *#*                       *#*          *#*  *#*      &lt;br /&gt;   *#*        *#*                *#*   *#*                      *#*      *###*     **#*                       *#*          *#*  *#*      &lt;br /&gt;   *#*        *#*                *#*   *#*                      *#*     *#**#*     *#*                        *#*          *#*  *#*      &lt;br /&gt;  ****       *#*    *******     ****  ****   *******            *#*     *#**#*    ****   *******    *#* **#* ****   ********#*  *#*      &lt;br /&gt;  *#*        *#*   **######*    *#*   *#*   **######*           *#*    *#***#*    *#*   **######*   *#**###* *#*   **####**#**  **       &lt;br /&gt;  *#*        *#*  **#******#*   *#*   *#*  **#******#*          *#*   **#* *#*   ****  **#******#*  *#****   *#*  *##** **##*  *#*       &lt;br /&gt;  *############* **#*     *#*   *#*   *#* **#*     *#*          *#*   *#*  *#*   *#*  **#*     *#*  *#**     *#* **#*    **#*  *#*       &lt;br /&gt; **###########** *#*       #*  ****  **** *#*      *#*          *#*  **#*  *#*  ****  *#*      *#* **#*     **** *#*      *#*  *#*       &lt;br /&gt; *#*        *#*  *##########*  *#*   *#*  *#*       #*          *#*  *#*   *#*  *#*   *#*       #* *#**     *#*  *#*      *#*  **        &lt;br /&gt; *#*        *#*  *##########*  *#*   *#*  *#*      *#*          *#* ****   *#* *#**   *#*      *#* *#*      *#*  *#*      *#*  **        &lt;br /&gt; *#*        *#*  *#            *#*   *#*  *#       *#*          *#* *#*    *#* *#*    *#       *#* *#*      *#*  *#      ***   **        &lt;br /&gt; *#*        *#*  *#*           *#*   *#*  *#*     **#*          *#**#**    *#**#**    *#*     **#* *#*      *#*  *#*     *#*   **        &lt;br /&gt;*#*        *#*   *#*     **** *#*   *#*   *#*     *#**          *#**#*     *#**#*     *#*     *#***#*      *#*   *#*    **#*             &lt;br /&gt;*#*        *#*   *#*******#*  *#*   *#*   *#*** **##*           *###**     *###**     *#*** **##* *#*      *#*   *#******##*             &lt;br /&gt;*#*        *#*    *######**   *#*   *#*    *######**            *###*      *###*       *######**  *#*      *#*   **#####**#*  *#*        &lt;br /&gt;*#*        *#*     *******    *#*   *#*     *******              ##*       *##*         *******   *#*      *#*    ********#*  *#*        &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Change the Font to SERIF BOLD&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#######   #######             ####   ####                   *######* *######*   ####*                       ####         ####    ***     &lt;br /&gt; *###*     *###*              *###   *###                    **##**   **##**    ****                        *###         *###    *#*     &lt;br /&gt;  ###       ###                ###    ###                     *##**    **##*     **                          ###          ###    *#*     &lt;br /&gt;  ###       ###                ###    ###                      *##*     *##*    ***                          ###          ###    *#*     &lt;br /&gt;  ###       ###                ###    ###                      *##*     **#**   **                           ###          ###    *#*     &lt;br /&gt;  ###       ###      ******    ###    ###     ******           **##*   ***##*   **     ******    #### ****   ###     *****###    *#*     &lt;br /&gt;  ###       ###     *#***#**   ###    ###    *#****#*           *##*   ***##*   **    *#****#*   *###*###*   ###    *#****###    *#*     &lt;br /&gt;  #############    *##* *##*   ###    ###   *##*  *##*          *##*   ****#** **    *##*  *##*   ###*****   ###   *##*  *###    *#*     &lt;br /&gt;  ###       ###    *##   ##*   ###    ###   *##*  *##*           *##* **  *##* **    *##*  *##*   ###*       ###   *##*   ###    *#*     &lt;br /&gt;  ###       ###    *#######*   ###    ###   *##    ##*           *##* **  *##* **    *##    ##*   ###*       ###   *##    ###    *#*     &lt;br /&gt;  ###       ###    *##*        ###    ###   *##    ##*           *##***   **##**     *##    ##*   ###        ###   *##    ###    *#      &lt;br /&gt;  ###       ###    *##*        ###    ###   *##    ##*            *##**    *##**     *##    ##*   ###        ###   *##    ###            &lt;br /&gt;  ###       ###    *##*   **   ###    ###   *##*  *##*            *##**    *###*     *##*  *##*   ###        ###   *##*   ###            &lt;br /&gt;  ###       ###    *##** ***   ###    ###   *##*  *##*            **#*      *#*      *##*  *##*   ###        ###   *##*  *###*   ***     &lt;br /&gt; *###*     *###*    *#####*   *###*  *###*   *#****#*              *#*      *#*       *#****#*   *###*      *###*  **#****####   *#*     &lt;br /&gt;#######   #######   ******    #####  #####    ******               ***      *#*        ******    #####      #####   **********   ***     &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1499441893414609380?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1499441893414609380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/generating-ascii-banners.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1499441893414609380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1499441893414609380'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/generating-ascii-banners.html' title='Generating ASCII Banners'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2228550114495234417</id><published>2011-08-17T10:42:00.004+01:00</published><updated>2012-01-26T15:15:47.231Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Double your money again</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;A long time ago I wrote an article on using &lt;i&gt;double &lt;/i&gt;for money. However, it is still a common fear for many developers when the solution is fairly simple.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Why not use BigDecimal&lt;/h2&gt;@myfear (Markus) asks a good question, doesn't BigDecimal do rounding already, (and with more options)&lt;br /&gt;&lt;br /&gt;IMHO, There are two reason you may want to avoid BigDecimal&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Clarity.&amp;nbsp; This may be a matter of option but I find &lt;i&gt;x * y / z&lt;/i&gt; clearer than &lt;i&gt;x.multiply(y).divide(z, 10, BigDecimal.ROUND_HALF_UP)&lt;/i&gt;&lt;/li&gt;&lt;li&gt;Performance. BigDecimal is often 100x slower.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;pre&gt;Took an average of 6 ns for rounding using cast&lt;br /&gt;Took an average of 17 ns for rounding using Math.round&lt;br /&gt;Took an average of 932 ns for rounding using BigDecimal.setScale&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You might like to test the difference on your machine.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The code&lt;/h3&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/math/RoundingPerformanceMain.java"&gt;&lt;b&gt;RoundingPerformanceMain.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;When to use BigDecimal&lt;/h2&gt;&lt;br /&gt;The better question is why would you ever use BigDecimal? &lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Arbitary precision. If you want more than 15 decimal places of precision, use BigDecimal.&lt;/li&gt;&lt;li&gt;Precise rounding. If you need to have full control over rounding options, it will be simpler using BigDecimal&lt;/li&gt;&lt;li&gt;The project standard is to use BigDecimal. Human factors can be more important than technical arguments.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h2&gt;The problem with using double for money&lt;/h2&gt;&lt;i&gt;double &lt;/i&gt;has two types of errors.  It have representation error. i.e. it cannot represent all possible decimal values exactly. Even 0.1 is not exactly this value. It also has rounding error from calculations. i.e. as you perform calculations, the error increases.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;double[] ds = {&lt;br /&gt;        0.1,&lt;br /&gt;        0.2,&lt;br /&gt;        -0.3,&lt;br /&gt;        0.1 + 0.2 - 0.3};&lt;br /&gt;for (double d : ds) {&lt;br /&gt;    System.out.println(d + " =&amp;gt; " + new BigDecimal(d));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints&lt;br /&gt;&lt;pre&gt;0.1 =&amp;gt; 0.1000000000000000055511151231257827021181583404541015625&lt;br /&gt;0.2 =&amp;gt; 0.200000000000000011102230246251565404236316680908203125&lt;br /&gt;-0.3 =&amp;gt; -0.299999999999999988897769753748434595763683319091796875&lt;br /&gt;5.551115123125783E-17 =&amp;gt; 5.5511151231257827021181583404541015625E-17&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can see that the representation for 0.1 and 0.2 is slightly higher than those values, and -0.3 is also slightly higher. When you print them, you get the nicer 0.1 instead of the actual value represented 0.1000000000000000055511151231257827021181583404541015625&lt;br /&gt;&lt;br /&gt;However, when you add these values together, you get a value which is slightly higher than 0.&lt;br /&gt;&lt;br /&gt;The important thing to remember is that these errors are not &lt;b&gt;random &lt;/b&gt;errors.  They are manageable and bounded.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Correcting for rounding error&lt;/h2&gt;Like many data types, such as date, you have an internal representation for a value and how you represent this as a string.&lt;br /&gt;&lt;br /&gt;This is true for &lt;i&gt;double&lt;/i&gt;. You need to control how the value is represented as a string.  This can can be surprise as Java does a small amount of rounding for  representation error is not obvious, however once you have rounding error for operations as well, it can some as a shock.&lt;br /&gt;&lt;br /&gt;A common reaction is to assume, there is nothing you can do about it, the error is uncontrollable, unknowable and dangerous.  Abandon &lt;i&gt;double &lt;/i&gt; and use &lt;i&gt;BigDecimal &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;However, the error is limited in the IEE-754 standards and accumulate slowly.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Round the result&lt;/h2&gt;&lt;br /&gt;And just like the need to use a TimeZone and Local for dates, you need to determine the precision of the result before converting to a String. &lt;br /&gt;&lt;br /&gt;To resolve this issue, you need to provide appropriate rounding. With money this is easy as you know how many decimal places are appropriate and unless you have $70 trillion you won't get a rounding error large enough you cannot correct it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;// uses round half up, or bankers' rounding&lt;br /&gt;public static double roundToTwoPlaces(double d) {&lt;br /&gt;    return Math.round(d * 100) / 100.0;&lt;br /&gt;}&lt;br /&gt;// OR&lt;br /&gt;public static double roundToTwoPlaces(double d) {&lt;br /&gt;    return ((long) (d &amp;lt; 0 ? d * 100 - 0.5 : d * 100 + 0.5)) / 100.0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;If you add this into the result, there is still a small representation error, however it is not large enough that the Double.toString(d) cannot correct for it.  &lt;br /&gt;&lt;pre&gt;double[] ds = {&lt;br /&gt;        0.1,&lt;br /&gt;        0.2,&lt;br /&gt;        -0.3,&lt;br /&gt;        0.1 + 0.2 - 0.3};&lt;br /&gt;for (double d : ds) {&lt;br /&gt;    System.out.println(d + " to two places " + roundToTwoPlaces(d) + " =&amp;gt; " + new BigDecimal(roundToTwoPlaces(d)));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;prints &lt;br /&gt;&lt;pre&gt;0.1 to two places 0.1 =&amp;gt; 0.1000000000000000055511151231257827021181583404541015625&lt;br /&gt;0.2 to two places 0.2 =&amp;gt; 0.200000000000000011102230246251565404236316680908203125&lt;br /&gt;-0.3 to two places -0.3 =&amp;gt; -0.299999999999999988897769753748434595763683319091796875&lt;br /&gt;5.551115123125783E-17 to two places 0.0 =&amp;gt; 0&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;If you have a project standard which says you should use BigDecimal or double, that is what you should follow.  However, there is not a good technical reason to fear using double for money.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related Links&lt;/h2&gt;&lt;a href="http://java.dzone.com/articles/working-money-java"&gt;&lt;br /&gt;Working with Money&lt;/a&gt; - In favour of BigDecimal. A comment which has a good suggestion that a generic Money wrapper be used if performance allows it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://joda-money.sourceforge.net/"&gt;JodaMoney&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2228550114495234417?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2228550114495234417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/double-your-money-again.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2228550114495234417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2228550114495234417'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/double-your-money-again.html' title='Double your money again'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3115158715817148086</id><published>2011-08-13T09:18:00.003+01:00</published><updated>2012-01-26T15:21:28.871Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Why testing code for thread safety is flawed</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;We know that ++ is not thread safe, even for volatile field, however there is a trick to proving this.&lt;br /&gt;&lt;br /&gt;The problem with testing code for thread safety is that it can happen to work repeatedly, but still be unsafe.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;An example&lt;/h2&gt;I wrote a lock free ring buffer which passed multi-threaded tests of one billion entries repeatedly. However, a couple of days later the test consistently failed.  What was the difference?  There was a couple of CPU intensive processes also running on the same box.  When these processes finished, the test passed again.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The problem&lt;/h2&gt;If you try to prove that incremental volatile variable is not thread safe, you can get a result like this.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public static void main(String... args) throws InterruptedException {&lt;br /&gt;    for (int nThreads = 1; nThreads &lt;= 64; nThreads*=2)&lt;br /&gt;        doThreadSafeTest(nThreads);&lt;br /&gt;}&lt;br /&gt;static class VolatileInt {&lt;br /&gt;    volatile int num = 0;&lt;br /&gt;}&lt;br /&gt;private static void doThreadSafeTest(final int nThreads) throws InterruptedException {&lt;br /&gt;    final int count = 32 * 1000;&lt;br /&gt;&lt;br /&gt;    ExecutorService es = Executors.newFixedThreadPool(nThreads);&lt;br /&gt;    final VolatileInt vi = new VolatileInt();&lt;br /&gt;    for (int i = 0; i &lt; nThreads; i++)&lt;br /&gt;        es.submit(new Runnable() {&lt;br /&gt;            public void run() {&lt;br /&gt;                for (int j = 0; j &lt; count; j += nThreads)&lt;br /&gt;                    vi.num++;&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;    es.shutdown();&lt;br /&gt;    es.awaitTermination(10, TimeUnit.SECONDS);&lt;br /&gt;    System.out.printf("With %,d threads should total %,d but was %,d%n", nThreads, count, vi.num);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;On my machine with 8 logical threads prints&lt;pre&gt;With 1 threads should total 32,000 but was 32,000&lt;br /&gt;With 2 threads should total 32,000 but was 32,000&lt;br /&gt;With 4 threads should total 32,000 but was 32,000&lt;br /&gt;With 8 threads should total 32,000 but was 32,000&lt;br /&gt;With 16 threads should total 32,000 but was 32,000&lt;br /&gt;With 32 threads should total 32,000 but was 32,000&lt;br /&gt;With 64 threads should total 32,000 but was 32,000&lt;br /&gt;&lt;/pre&gt;There doesn't appear to be a problem. Why?This is because it takes time to start each thread, and each thread doesn't take long to complete so even though many tasks are started, each completes before the next one starts. i.e. it is effectively single threaded.&lt;h2&gt;Thread safety bugs can hide&lt;/h2&gt;In a more complex test, you might not know what subtle thing to change which causes your code to break.In fact you can deploy your application into production and it can work for years. One day something changes like you add another application, increasing the load, a version of Java or your machine is upgraded and suddenly it fails intermittently. It is tempting to assume that the most recent change is the cause of the problem when actually the bug has always been there, it just hasn't shown itself.&lt;h2&gt;Changing the test&lt;/h2&gt;When we run the test long enough to have multiple threads running at once, we see a different pattern.  We see that the single threaded test behaves as expected, without losing any counts, however the multi-threaded test runs start dropping incremented values.&lt;pre&gt;With 1 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;With 2 threads should total 100,000,000 but was 75,127,690&lt;br /&gt;With 4 threads should total 100,000,000 but was 51,338,289&lt;br /&gt;With 8 threads should total 100,000,000 but was 35,177,375&lt;br /&gt;With 16 threads should total 100,000,000 but was 15,264,270&lt;br /&gt;With 32 threads should total 100,000,000 but was 14,385,095&lt;br /&gt;With 64 threads should total 100,000,000 but was 15,818,747&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Fixing the test&lt;/h2&gt;If you replace a &lt;i&gt;volatile int&lt;/i&gt; with &lt;i&gt;AtomicInteger&lt;/i&gt; you get the following result.&lt;pre&gt;With 1 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;With 2 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;With 4 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;With 8 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;With 16 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;With 32 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;With 64 threads should total 100,000,000 but was 100,000,000&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;When trying to prove a multi-threaded test fails by experimentation is it not easy, even for trivial examples.  This is why understanding the thread safety guarantees Java provides is important. This way you will know code is thread safe.&lt;h2&gt;Work around&lt;/h2&gt;What can you do if you can't read all the code to guarantee thread safety?I would suggest loading up the box until everything is busy. Create processes so every thread is busy and create disk and network activity so they are always busy. While this is happening run your test.  If it passes, your application is less likely to fail under load.  This is no guarantee but it is better than testing your application without load.&lt;h2&gt;The Code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/threads/IncrementNotThreadSafeMain.java"&gt;&lt;b&gt;IncrementNotThreadSafeMain.java&lt;/b&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3115158715817148086?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3115158715817148086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/why-testing-code-for-thread-safety-is.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3115158715817148086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3115158715817148086'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/why-testing-code-for-thread-safety-is.html' title='Why testing code for thread safety is flawed'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-879032388368537698</id><published>2011-08-09T15:06:00.011+01:00</published><updated>2012-01-22T19:34:51.592Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Collections Library for millions of elements</title><content type='html'>&lt;h2&gt;When to use this library&lt;/h2&gt;&lt;br /&gt;If you want to efficiently store large collections of data in memory. This library can dramatically reduce Full GC times and reduce memory consumption as well.&lt;br /&gt;&lt;br /&gt;When you have a data type which can be represented by an interface and you want a List for this type.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;List&amp;lt;Iinterfacetype&gt; list = new HugeArrayBuilder&amp;lt;Interfacetype&gt;() {}.create();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The type needs to be described using an interface so its represented can be changed. (Using generated byte code)&lt;br /&gt;&lt;br /&gt;The HugeArrayBuilder builds generated classes for the InterfaceType on demand. The builder can be configured to change how the HugeArrayList is created. &lt;br /&gt;&lt;br /&gt;A more complex example is&lt;br /&gt;&lt;pre&gt;HugeArrayList&amp;lt;Mutabletypes&gt; hugeList = new HugeArrayBuilder&amp;lt;Mutabletypes&gt;() {{&lt;br /&gt;        allocationSize = 1024*1024;&lt;br /&gt;        classLoader = myClassLoader;&lt;br /&gt;    }}.create();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;How does the library differ&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Uses long for sizes and indecies.&lt;/li&gt;&lt;li&gt;Uses column based data making the per element overhead minimal and speed up scans over a single or small set of attributes. This reduces memory usages by 2x or more.&lt;/li&gt;&lt;li&gt;Stores attributes in direct memory as much as possible, reducing heap usage dramatically, 10x or more. &lt;/li&gt;&lt;li&gt;Allocates blocks of data for consistent add() times, rather than exponentially growing an underlying store (with exponentially increasing delays on a grow of capacity) &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;Performance comparison&lt;/h2&gt;This test compares using HugeCollection vs ArrayList of JavaBeans. The class has 12 fields of various types which can be converted to primitives in different ways. By storing these primitives (or objects encoded as primitives), the time to perform GCs is almost eliminated. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-IfBovJRmUco/TkE8582ynTI/AAAAAAAAAEk/8OPZ1oUXO9k/s1600/huge-collection-gc-times.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-IfBovJRmUco/TkE8582ynTI/AAAAAAAAAEk/8OPZ1oUXO9k/s1600/huge-collection-gc-times.png" /&gt;&lt;/a&gt;&lt;/div&gt;With 20 GB of free memory, only 250 million JavaBeans could be created and a HugeCollection can store 500 million elements.&lt;br /&gt;&lt;br /&gt;Classes with fields which cannot be encoded as primitives are supported in version 0.1.1 and still show an improvement in GC times.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-20NvCnQwC9Y/TkE-uIBUgEI/AAAAAAAAAE0/A3SXbHVon0s/s1600/huge-collection-object-gc-times.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-20NvCnQwC9Y/TkE-uIBUgEI/AAAAAAAAAE0/A3SXbHVon0s/s1600/huge-collection-object-gc-times.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In both cases, the amount of memory used was halved.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The project web site&lt;/h2&gt;&lt;a href="http://code.google.com/p/vanilla-java/wiki/HugeCollections"&gt;&lt;b&gt;HugeCollections on Google Code&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The source&lt;/h2&gt;The best way to get the whole source, including tests is to use subversion.&lt;br /&gt;&lt;pre&gt;svn co http://vanilla-java.googlecode.com/svn/trunk/collections/ vanilla-java-collections&lt;br /&gt;cd vanilla-java-collections&lt;br /&gt;mvn test&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-879032388368537698?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/879032388368537698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/collections-library-for-millions-of.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/879032388368537698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/879032388368537698'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/collections-library-for-millions-of.html' title='Collections Library for millions of elements'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-IfBovJRmUco/TkE8582ynTI/AAAAAAAAAEk/8OPZ1oUXO9k/s72-c/huge-collection-gc-times.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3399962274793482166</id><published>2011-08-05T13:21:00.003+01:00</published><updated>2012-01-22T19:34:51.450Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Tuning buffer sizes</title><content type='html'>&lt;h2&gt;&lt;br /&gt;Overview&lt;/h2&gt;&lt;br /&gt;When the typical read/write size is small, using a buffer can make a significant improvement in performance. However when reading/writing large amounts of data, additional buffered doesn't help and can add a small amount of overhead.&lt;br /&gt;&lt;br /&gt;Additionally, it can be tempting to assume; the larger the buffer the better. However is appears a more modest buffer size, around the size of your L1 cache could be better. e.g 8 KB to 32 KB.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;The test&lt;/h2&gt;&lt;br /&gt;In the following test I compared using buffered and unbuffered reads and writes to a temporary file on a &lt;i&gt;tmpfs&lt;/i&gt; filesystem (ram disk)&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Size of&lt;br /&gt;read/write&lt;/th&gt;&lt;th&gt;Unbuffered&lt;br /&gt;Writes&lt;/th&gt;&lt;th&gt;&amp;nbsp;&amp;nbsp;Buffered&lt;br /&gt;Writes&lt;/th&gt;&lt;th&gt;Unbuffered&lt;br /&gt;Reads&lt;/th&gt;&lt;th&gt;&amp;nbsp;&amp;nbsp;Buffered&lt;br /&gt;Reads&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;1&lt;/td&gt;&lt;td align="right"&gt;2 MB/s&lt;/td&gt;&lt;td align="right"&gt;86 MB/s&lt;/td&gt;&lt;td align="right"&gt;3 MB/s&lt;/td&gt;&lt;td align="right"&gt;72 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;2&lt;/td&gt;&lt;td align="right"&gt;4 MB/s&lt;/td&gt;&lt;td align="right"&gt;165 MB/s&lt;/td&gt;&lt;td align="right"&gt;6 MB/s&lt;/td&gt;&lt;td align="right"&gt;147 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;4&lt;/td&gt;&lt;td align="right"&gt;8 MB/s&lt;/td&gt;&lt;td align="right"&gt;333 MB/s&lt;/td&gt;&lt;td align="right"&gt;11 MB/s&lt;/td&gt;&lt;td align="right"&gt;291 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;8&lt;/td&gt;&lt;td align="right"&gt;17 MB/s&lt;/td&gt;&lt;td align="right"&gt;578 MB/s&lt;/td&gt;&lt;td align="right"&gt;24 MB/s&lt;/td&gt;&lt;td align="right"&gt;560 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;16&lt;/td&gt;&lt;td align="right"&gt;34 MB/s&lt;/td&gt;&lt;td align="right"&gt;920 MB/s&lt;/td&gt;&lt;td align="right"&gt;49 MB/s&lt;/td&gt;&lt;td align="right"&gt;983 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;32&lt;/td&gt;&lt;td align="right"&gt;67 MB/s&lt;/td&gt;&lt;td align="right"&gt;1,345 MB/s&lt;/td&gt;&lt;td align="right"&gt;99 MB/s&lt;/td&gt;&lt;td align="right"&gt;1,679 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;64&lt;/td&gt;&lt;td align="right"&gt;133 MB/s&lt;/td&gt;&lt;td align="right"&gt;1,746 MB/s&lt;/td&gt;&lt;td align="right"&gt;198 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,518 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;128&lt;/td&gt;&lt;td align="right"&gt;254 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,024 MB/s&lt;/td&gt;&lt;td align="right"&gt;391 MB/s&lt;/td&gt;&lt;td align="right"&gt;3,387 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;256&lt;/td&gt;&lt;td align="right"&gt;463 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,172 MB/s&lt;/td&gt;&lt;td align="right"&gt;742 MB/s&lt;/td&gt;&lt;td align="right"&gt;4,104 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;512&lt;/td&gt;&lt;td align="right"&gt;798 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,270 MB/s&lt;/td&gt;&lt;td align="right"&gt;1,334 MB/s&lt;/td&gt;&lt;td align="right"&gt;4,549 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;1,024&lt;/td&gt;&lt;td align="right"&gt;1,270 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,299 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,355 MB/s&lt;/td&gt;&lt;td align="right"&gt;4,752 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;2,048&lt;/td&gt;&lt;td align="right"&gt;1,789 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,310 MB/s&lt;/td&gt;&lt;td align="right"&gt;3,704 MB/s&lt;/td&gt;&lt;td align="right"&gt;4,923 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;4,096&lt;/td&gt;&lt;td align="right"&gt;2,287 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,301 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,324 MB/s&lt;/td&gt;&lt;td align="right"&gt;4,859 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;8,192&lt;/td&gt;&lt;td align="right"&gt;2,589 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,497 MB/s&lt;/td&gt;&lt;td align="right"&gt;6,346 MB/s&lt;/td&gt;&lt;td align="right"&gt;6,142 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;16,384&lt;/td&gt;&lt;td align="right"&gt;2,534 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,559 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,764 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,697 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;32,768&lt;/td&gt;&lt;td align="right"&gt;2,591 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,561 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,793 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,723 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;65,536&lt;/td&gt;&lt;td align="right"&gt;2,613 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,581 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,861 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,883 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;131,072&lt;/td&gt;&lt;td align="right"&gt;2,580 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,581 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,401 MB/s&lt;/td&gt;&lt;td align="right"&gt;5,405 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;262,144&lt;/td&gt;&lt;td align="right"&gt;1,918 MB/s&lt;/td&gt;&lt;td align="right"&gt;1,907 MB/s&lt;/td&gt;&lt;td align="right"&gt;3,269 MB/s&lt;/td&gt;&lt;td align="right"&gt;3,262 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;524,288&lt;/td&gt;&lt;td align="right"&gt;1,749 MB/s&lt;/td&gt;&lt;td align="right"&gt;1,734 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,845 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,851 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;1,048,576&lt;/td&gt;&lt;td align="right"&gt;1,471 MB/s&lt;/td&gt;&lt;td align="right"&gt;1,469 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,501 MB/s&lt;/td&gt;&lt;td align="right"&gt;2,502 MB/s&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;The default size of a BufferedInputStream and BufferedOutputStream is 8KB. This is part of the reason why they don't help at this point and larger.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;The code&lt;/h2&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/io/BufferTest.java"&gt;&lt;b&gt;BufferTest.java&lt;/b&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3399962274793482166?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3399962274793482166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/tuning-buffer-sizes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3399962274793482166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3399962274793482166'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/tuning-buffer-sizes.html' title='Tuning buffer sizes'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2519712005195764184</id><published>2011-08-04T21:39:00.001+01:00</published><updated>2012-01-22T19:34:51.421Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Comparing Collections speeds</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The speed of different collections tends to depend on their usage pattern however it can be useful to have an idea of their relative performance.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The test&lt;/h2&gt;In this test I compare both single thread and thread safe collections of different sizes.&lt;br /&gt;&lt;br /&gt;Adding is from lowest to highest values. Removal is from start and end, finishing with the middle value. This disadvantages ArrayList and LinkedList relatively equally.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Collection&lt;/th&gt;&lt;th&gt;Size&lt;/th&gt;&lt;th&gt;Adding&lt;/th&gt;&lt;th&gt;Iterating&lt;/th&gt;&lt;th&gt;Removing&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;30.1&lt;/td&gt;&lt;td aligned="right"&gt;14.5&lt;/td&gt;&lt;td aligned="right"&gt;67,359&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;8.3&lt;/td&gt;&lt;td aligned="right"&gt;11.2&lt;/td&gt;&lt;td aligned="right"&gt;6,323&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;6.4&lt;/td&gt;&lt;td aligned="right"&gt;9.4&lt;/td&gt;&lt;td aligned="right"&gt;585&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;6.8&lt;/td&gt;&lt;td aligned="right"&gt;9.5&lt;/td&gt;&lt;td aligned="right"&gt;92.9&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;9.7&lt;/td&gt;&lt;td aligned="right"&gt;13.2&lt;/td&gt;&lt;td aligned="right"&gt;36.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;46.4&lt;/td&gt;&lt;td aligned="right"&gt;41.4&lt;/td&gt;&lt;td aligned="right"&gt;139,326&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;9.3&lt;/td&gt;&lt;td aligned="right"&gt;30.3&lt;/td&gt;&lt;td aligned="right"&gt;13,413&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;8.7&lt;/td&gt;&lt;td aligned="right"&gt;27.6&lt;/td&gt;&lt;td aligned="right"&gt;1,025&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;7.8&lt;/td&gt;&lt;td aligned="right"&gt;19.8&lt;/td&gt;&lt;td aligned="right"&gt;110&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;11.2&lt;/td&gt;&lt;td aligned="right"&gt;30.3&lt;/td&gt;&lt;td aligned="right"&gt;38.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HashSet&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;28.6&lt;/td&gt;&lt;td aligned="right"&gt;115&lt;/td&gt;&lt;td aligned="right"&gt;69.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HashSet&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;25.7&lt;/td&gt;&lt;td aligned="right"&gt;324&lt;/td&gt;&lt;td aligned="right"&gt;58.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HashSet&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;26.0&lt;/td&gt;&lt;td aligned="right"&gt;2,521&lt;/td&gt;&lt;td aligned="right"&gt;59.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HashSet&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;30.0&lt;/td&gt;&lt;td aligned="right"&gt;24,490&lt;/td&gt;&lt;td aligned="right"&gt;64.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HashSet&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;51.7&lt;/td&gt;&lt;td aligned="right"&gt;244,045&lt;/td&gt;&lt;td aligned="right"&gt;131&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;35.9&lt;/td&gt;&lt;td aligned="right"&gt;103&lt;/td&gt;&lt;td aligned="right"&gt;69.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;30.3&lt;/td&gt;&lt;td aligned="right"&gt;101&lt;/td&gt;&lt;td aligned="right"&gt;65.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;29.2&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;65.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;31.5&lt;/td&gt;&lt;td aligned="right"&gt;98.8&lt;/td&gt;&lt;td aligned="right"&gt;60.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;45.4&lt;/td&gt;&lt;td aligned="right"&gt;110&lt;/td&gt;&lt;td aligned="right"&gt;69.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;159&lt;/td&gt;&lt;td aligned="right"&gt;106&lt;/td&gt;&lt;td aligned="right"&gt;187&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;99.6&lt;/td&gt;&lt;td aligned="right"&gt;77.6&lt;/td&gt;&lt;td aligned="right"&gt;111&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;78.5&lt;/td&gt;&lt;td aligned="right"&gt;57.5&lt;/td&gt;&lt;td aligned="right"&gt;93.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;54.0&lt;/td&gt;&lt;td aligned="right"&gt;47.9&lt;/td&gt;&lt;td aligned="right"&gt;83.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;30.2&lt;/td&gt;&lt;td aligned="right"&gt;51.0&lt;/td&gt;&lt;td aligned="right"&gt;49.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap IdentityHashMap&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;74.1&lt;/td&gt;&lt;td aligned="right"&gt;216&lt;/td&gt;&lt;td aligned="right"&gt;153&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap IdentityHashMap&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;65.5&lt;/td&gt;&lt;td aligned="right"&gt;370&lt;/td&gt;&lt;td aligned="right"&gt;126&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap IdentityHashMap&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;60.4&lt;/td&gt;&lt;td aligned="right"&gt;1,644&lt;/td&gt;&lt;td aligned="right"&gt;115&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap IdentityHashMap&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;21.1&lt;/td&gt;&lt;td aligned="right"&gt;14,216&lt;/td&gt;&lt;td aligned="right"&gt;48.9&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap IdentityHashMap&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;46.7&lt;/td&gt;&lt;td aligned="right"&gt;140,162&lt;/td&gt;&lt;td aligned="right"&gt;109&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap WeakHashMap&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;52.4&lt;/td&gt;&lt;td aligned="right"&gt;148&lt;/td&gt;&lt;td aligned="right"&gt;87.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap WeakHashMap&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;33.5&lt;/td&gt;&lt;td aligned="right"&gt;217&lt;/td&gt;&lt;td aligned="right"&gt;71.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap WeakHashMap&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;32.9&lt;/td&gt;&lt;td aligned="right"&gt;1,088&lt;/td&gt;&lt;td aligned="right"&gt;72.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap WeakHashMap&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;32.1&lt;/td&gt;&lt;td aligned="right"&gt;9,717&lt;/td&gt;&lt;td aligned="right"&gt;64.3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap WeakHashMap&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;48.0&lt;/td&gt;&lt;td aligned="right"&gt;98,769&lt;/td&gt;&lt;td aligned="right"&gt;93.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Thread Safe Collections&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;22.6&lt;/td&gt;&lt;td aligned="right"&gt;101&lt;/td&gt;&lt;td aligned="right"&gt;98,735&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;12.1&lt;/td&gt;&lt;td aligned="right"&gt;101&lt;/td&gt;&lt;td aligned="right"&gt;10,084&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;11.5&lt;/td&gt;&lt;td aligned="right"&gt;99.5&lt;/td&gt;&lt;td aligned="right"&gt;1,023&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;11.4&lt;/td&gt;&lt;td aligned="right"&gt;101&lt;/td&gt;&lt;td aligned="right"&gt;144&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized ArrayList&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;14.0&lt;/td&gt;&lt;td aligned="right"&gt;111&lt;/td&gt;&lt;td aligned="right"&gt;54.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Vector&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;23.9&lt;/td&gt;&lt;td aligned="right"&gt;298&lt;/td&gt;&lt;td aligned="right"&gt;64,333&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Vector&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;20.4&lt;/td&gt;&lt;td aligned="right"&gt;372&lt;/td&gt;&lt;td aligned="right"&gt;5,919&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Vector&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;19.4&lt;/td&gt;&lt;td aligned="right"&gt;372&lt;/td&gt;&lt;td aligned="right"&gt;612&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Vector&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;19.3&lt;/td&gt;&lt;td aligned="right"&gt;375&lt;/td&gt;&lt;td aligned="right"&gt;145&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Vector&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;22.9&lt;/td&gt;&lt;td aligned="right"&gt;397&lt;/td&gt;&lt;td aligned="right"&gt;97.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;37.6&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;132,660&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;19.2&lt;/td&gt;&lt;td aligned="right"&gt;99.6&lt;/td&gt;&lt;td aligned="right"&gt;13,049&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;22.2&lt;/td&gt;&lt;td aligned="right"&gt;99.1&lt;/td&gt;&lt;td aligned="right"&gt;1,005&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;23.7&lt;/td&gt;&lt;td aligned="right"&gt;102&lt;/td&gt;&lt;td aligned="right"&gt;134&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedList&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;26.1&lt;/td&gt;&lt;td aligned="right"&gt;115&lt;/td&gt;&lt;td aligned="right"&gt;62.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized HashSet&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;50.1&lt;/td&gt;&lt;td aligned="right"&gt;138&lt;/td&gt;&lt;td aligned="right"&gt;95.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized HashSet&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;43.0&lt;/td&gt;&lt;td aligned="right"&gt;347&lt;/td&gt;&lt;td aligned="right"&gt;93.1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized HashSet&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;42.7&lt;/td&gt;&lt;td aligned="right"&gt;2,555&lt;/td&gt;&lt;td aligned="right"&gt;95.3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized HashSet&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;47.0&lt;/td&gt;&lt;td aligned="right"&gt;24,608&lt;/td&gt;&lt;td aligned="right"&gt;97.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized HashSet&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;85.7&lt;/td&gt;&lt;td aligned="right"&gt;245,343&lt;/td&gt;&lt;td aligned="right"&gt;204&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;48.6&lt;/td&gt;&lt;td aligned="right"&gt;103&lt;/td&gt;&lt;td aligned="right"&gt;93.1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;45.6&lt;/td&gt;&lt;td aligned="right"&gt;101&lt;/td&gt;&lt;td aligned="right"&gt;88.1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;48.7&lt;/td&gt;&lt;td aligned="right"&gt;106&lt;/td&gt;&lt;td aligned="right"&gt;94.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;48.1&lt;/td&gt;&lt;td aligned="right"&gt;101&lt;/td&gt;&lt;td aligned="right"&gt;86.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized LinkedHashSet&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;57.8&lt;/td&gt;&lt;td aligned="right"&gt;114&lt;/td&gt;&lt;td aligned="right"&gt;93.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;116&lt;/td&gt;&lt;td aligned="right"&gt;105&lt;/td&gt;&lt;td aligned="right"&gt;179&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;74.1&lt;/td&gt;&lt;td aligned="right"&gt;75.4&lt;/td&gt;&lt;td aligned="right"&gt;122&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;63.5&lt;/td&gt;&lt;td aligned="right"&gt;53.9&lt;/td&gt;&lt;td aligned="right"&gt;103&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;50.8&lt;/td&gt;&lt;td aligned="right"&gt;46.2&lt;/td&gt;&lt;td aligned="right"&gt;90.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchronized TreeSet&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;29.1&lt;/td&gt;&lt;td aligned="right"&gt;49.1&lt;/td&gt;&lt;td aligned="right"&gt;57.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArrayList&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;35,354&lt;/td&gt;&lt;td aligned="right"&gt;65.8&lt;/td&gt;&lt;td aligned="right"&gt;165,197&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArrayList&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;2,115&lt;/td&gt;&lt;td aligned="right"&gt;97.7&lt;/td&gt;&lt;td aligned="right"&gt;36,269&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArrayList&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;217&lt;/td&gt;&lt;td aligned="right"&gt;75.1&lt;/td&gt;&lt;td aligned="right"&gt;1,828&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArrayList&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;60.0&lt;/td&gt;&lt;td aligned="right"&gt;63.4&lt;/td&gt;&lt;td aligned="right"&gt;227&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArrayList&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;48.2&lt;/td&gt;&lt;td aligned="right"&gt;71.0&lt;/td&gt;&lt;td aligned="right"&gt;103&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArraySet&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;106,116&lt;/td&gt;&lt;td aligned="right"&gt;63.3&lt;/td&gt;&lt;td aligned="right"&gt;165,708&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArraySet&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;28,736&lt;/td&gt;&lt;td aligned="right"&gt;91.2&lt;/td&gt;&lt;td aligned="right"&gt;29,820&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArraySet&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;1,143&lt;/td&gt;&lt;td aligned="right"&gt;75.1&lt;/td&gt;&lt;td aligned="right"&gt;1,852&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArraySet&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;134&lt;/td&gt;&lt;td aligned="right"&gt;63.4&lt;/td&gt;&lt;td aligned="right"&gt;233&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CopyOnWriteArraySet&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;55.3&lt;/td&gt;&lt;td aligned="right"&gt;73.0&lt;/td&gt;&lt;td aligned="right"&gt;109&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentHashMap&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;70.6&lt;/td&gt;&lt;td aligned="right"&gt;291&lt;/td&gt;&lt;td aligned="right"&gt;149&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentHashMap&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;57.2&lt;/td&gt;&lt;td aligned="right"&gt;485&lt;/td&gt;&lt;td aligned="right"&gt;120&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentHashMap&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;53.4&lt;/td&gt;&lt;td aligned="right"&gt;2,869&lt;/td&gt;&lt;td aligned="right"&gt;121&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentHashMap&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;54.7&lt;/td&gt;&lt;td aligned="right"&gt;24,150&lt;/td&gt;&lt;td aligned="right"&gt;140&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentHashMap&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;68.7&lt;/td&gt;&lt;td aligned="right"&gt;93,921&lt;/td&gt;&lt;td aligned="right"&gt;197&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentSkipListMap&lt;/td&gt;&lt;td aligned="right"&gt;100,000&lt;/td&gt;&lt;td aligned="right"&gt;135&lt;/td&gt;&lt;td aligned="right"&gt;96.8&lt;/td&gt;&lt;td aligned="right"&gt;365&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentSkipListMap&lt;/td&gt;&lt;td aligned="right"&gt;10,000&lt;/td&gt;&lt;td aligned="right"&gt;113&lt;/td&gt;&lt;td aligned="right"&gt;95.1&lt;/td&gt;&lt;td aligned="right"&gt;285&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentSkipListMap&lt;/td&gt;&lt;td aligned="right"&gt;1,000&lt;/td&gt;&lt;td aligned="right"&gt;97.8&lt;/td&gt;&lt;td aligned="right"&gt;94.7&lt;/td&gt;&lt;td aligned="right"&gt;234&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentSkipListMap&lt;/td&gt;&lt;td aligned="right"&gt;100&lt;/td&gt;&lt;td aligned="right"&gt;83.3&lt;/td&gt;&lt;td aligned="right"&gt;95.2&lt;/td&gt;&lt;td aligned="right"&gt;192&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;newSetFromMap ConcurrentSkipListMap&lt;/td&gt;&lt;td aligned="right"&gt;10&lt;/td&gt;&lt;td aligned="right"&gt;64.2&lt;/td&gt;&lt;td aligned="right"&gt;112&lt;/td&gt;&lt;td aligned="right"&gt;151&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;h2&gt;The code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/collections/AddIterateRemoveTest.java"&gt;AddIterateRemoveTest.java&lt;/a&gt;&lt;br /&gt;Timings are in nano-seconds per element.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related Article&lt;/h2&gt;&lt;h3 class="post-title entry-title"&gt;&lt;a href="http://vanillajava.blogspot.com/2011/08/collections-library-for-millions-of.html"&gt;Collections Library for millions of elements&lt;/a&gt;&lt;/h3&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2519712005195764184?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2519712005195764184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/comparing-collections-speeds.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2519712005195764184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2519712005195764184'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/comparing-collections-speeds.html' title='Comparing Collections speeds'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-487836453847052491</id><published>2011-08-04T15:54:00.005+01:00</published><updated>2012-01-22T19:34:51.530Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Reading/writing GC-less memory</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;How you access data can make a difference to the speed.  Whether you use manual loop unrolling or let the JIT do it for you can also make a difference to performance.&lt;br /&gt;&lt;br /&gt;I have included C++ and Java tests doing the same thing for comparison.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Tests&lt;/h2&gt;In each case, different approaches to storing 16 GB of data were compared.&lt;br /&gt;&lt;br /&gt;In the following tests I compared storing data&lt;br /&gt;&lt;ul&gt;&lt;li&gt;allocating, writing to, reading from and total GC times&lt;/li&gt;&lt;li&gt;byte[] (smallest primitive) and long[] (largest primitive)&lt;/li&gt;&lt;li&gt;arrays, direct ByteBuffer and Unsafe&lt;/li&gt;&lt;li&gt;JIT optimised and hand unrolled four times&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;store&lt;/th&gt;&lt;th&gt;type&lt;/th&gt;&lt;th&gt;size&lt;/th&gt;&lt;th&gt;unrolled&lt;/th&gt;&lt;th&gt;allocate&lt;/th&gt;&lt;th&gt;writing&lt;/th&gt;&lt;th&gt;reading&lt;/th&gt;&lt;th&gt;GC time&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++ char[]&lt;/td&gt;&lt;td&gt;native&lt;/td&gt;&lt;td&gt;8-bit char&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;31 μs&lt;/td&gt;&lt;td align="right"&gt;12.0 s&lt;/td&gt;&lt;td align="right"&gt;8.7 s&lt;/td&gt;&lt;td align="right"&gt;N/A&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++ char[]&lt;/td&gt;&lt;td&gt;native&lt;/td&gt;&lt;td&gt;8-bit char&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;5 μs&lt;/td&gt;&lt;td align="right"&gt;8.8 s&lt;/td&gt;&lt;td align="right"&gt;6.6 s&lt;/td&gt;&lt;td align="right"&gt;N/A&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++ long long[]&lt;/td&gt;&lt;td&gt;native&lt;/td&gt;&lt;td&gt;64-bit int&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;11 μs&lt;/td&gt;&lt;td align="right"&gt;4.6 s&lt;/td&gt;&lt;td align="right"&gt;1.4 s&lt;/td&gt;&lt;td align="right"&gt;N/A&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++ long long[]&lt;/td&gt;&lt;td&gt;native&lt;/td&gt;&lt;td&gt;64-bit int&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;12 μs&lt;/td&gt;&lt;td align="right"&gt;4.2 s&lt;/td&gt;&lt;td align="right"&gt;1.2 s&lt;/td&gt;&lt;td align="right"&gt;N/A&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;byte[]&lt;/td&gt;&lt;td&gt;heap&lt;/td&gt;&lt;td&gt;byte&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;4.9 s&lt;/td&gt;&lt;td align="right"&gt;20.7/7.8 s&lt;/td&gt;&lt;td align="right"&gt;7.4 s&lt;/td&gt;&lt;td align="right"&gt;51 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;byte[]&lt;/td&gt;&lt;td&gt;heap&lt;/td&gt;&lt;td&gt;byte&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;4.9 s&lt;/td&gt;&lt;td align="right"&gt;7.1 s&lt;/td&gt;&lt;td align="right"&gt;8.5 s&lt;/td&gt;&lt;td align="right"&gt;44 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;long[]&lt;/td&gt;&lt;td&gt;heap&lt;/td&gt;&lt;td&gt;long&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;4.7 s&lt;/td&gt;&lt;td align="right"&gt;1.6 s&lt;/td&gt;&lt;td align="right"&gt;1.5 s&lt;/td&gt;&lt;td align="right"&gt;37 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;long[]&lt;/td&gt;&lt;td&gt;heap&lt;/td&gt;&lt;td&gt;long&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;4.7 s&lt;/td&gt;&lt;td align="right"&gt;1.5 s&lt;/td&gt;&lt;td align="right"&gt;1.4 s&lt;/td&gt;&lt;td align="right"&gt;45 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ByteBuffer&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;byte&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;4.8 s&lt;/td&gt;&lt;td align="right"&gt;18.1/10.0 s&lt;/td&gt;&lt;td align="right"&gt;14.0 s&lt;/td&gt;&lt;td align="right"&gt;6.1 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ByteBuffer&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;byte&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;4.8 s&lt;/td&gt;&lt;td align="right"&gt;12.2/10.0 s&lt;/td&gt;&lt;td align="right"&gt;16.7 s&lt;/td&gt;&lt;td align="right"&gt;6.1 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ByteBuffer&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;long&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;4.7 s&lt;/td&gt;&lt;td align="right"&gt;6.0/3.9 s&lt;/td&gt;&lt;td align="right"&gt;2.4 s&lt;/td&gt;&lt;td align="right"&gt;6.1 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ByteBuffer&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;long&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;4.6 s&lt;/td&gt;&lt;td align="right"&gt;4.7/2.3 s&lt;/td&gt;&lt;td align="right"&gt;7.9 s&lt;/td&gt;&lt;td align="right"&gt;6.1 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Unsafe&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;byte&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;10 μs&lt;/td&gt;&lt;td align="right"&gt;18.2 s&lt;/td&gt;&lt;td align="right"&gt;13.8 s&lt;/td&gt;&lt;td align="right"&gt;6.0 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Unsafe&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;byte&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;10 μs&lt;/td&gt;&lt;td align="right"&gt;8.7 s&lt;/td&gt;&lt;td align="right"&gt;8.3 s&lt;/td&gt;&lt;td align="right"&gt;6.0 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Unsafe&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;long&lt;/td&gt;&lt;td&gt;no&lt;/td&gt;&lt;td align="right"&gt;10 μs&lt;/td&gt;&lt;td align="right"&gt;5.2 s&lt;/td&gt;&lt;td align="right"&gt;1.9 s&lt;/td&gt;&lt;td align="right"&gt;6.0 ms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Unsafe&lt;/td&gt;&lt;td&gt;direct&lt;/td&gt;&lt;td&gt;long&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;td align="right"&gt;10 μs&lt;/td&gt;&lt;td align="right"&gt;4.2 s&lt;/td&gt;&lt;td align="right"&gt;1.3 s&lt;/td&gt;&lt;td align="right"&gt;6.0 ms&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;In each case, this is the time to perform 8-bit &lt;i&gt;byte&lt;/i&gt; or 64-bit &lt;i&gt;long&lt;/i&gt; operations on 16 GB of data in different structures as required. In C++ and using Unsafe, I single array/block memory was used. For Java array and ByteBuffer multiple objects were use to create the same total amount of space.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;C++ test configuration&lt;/h2&gt;All tests were performed with gcc 4.5.2 on ubuntu 11.04, compiled with &lt;i&gt;-O2&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Java test configuration&lt;/h2&gt;All test were performed with Java 6 update 26 and Java 7 update 0, on a fast PC with 24 GB of memory. Timings are for 6/7. Where there one value they were the same.&lt;br /&gt;&lt;br /&gt;All tests were run with the options &lt;i&gt;-mx23g -XX:MaxDirectMemorySize=20g -verbosegc &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Curiosity&lt;/h2&gt;&lt;br /&gt;For me the most curious result was the performance of the long[] which was very fast in Java, faster than using C++ or Unsafe directly.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The code&lt;/h2&gt;C++ tests - &lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/cpp/memorytest/main.cpp"&gt;memorytest/main.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Java tests - &lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/gc/MemoryTest.java"&gt;MemoryTest.java&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related Link&lt;/h2&gt;&lt;h3 class="post-title entry-title"&gt;&lt;a href="http://vanillajava.blogspot.com/2011/08/collections-library-for-millions-of.html"&gt;Collections Library for millions of elements&lt;/a&gt;&lt;/h3&gt;&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-487836453847052491?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/487836453847052491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/readingwriting-gc-less-memory.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/487836453847052491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/487836453847052491'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/readingwriting-gc-less-memory.html' title='Reading/writing GC-less memory'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7464352519288872854</id><published>2011-08-03T15:31:00.000+01:00</published><updated>2012-01-26T15:17:51.416Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>50,000 pages views last month</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-G7EG3O9I7rM/Tjla3MUgGRI/AAAAAAAAAEc/Ed90r4piSA8/s1600/50000.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="64" src="http://4.bp.blogspot.com/-G7EG3O9I7rM/Tjla3MUgGRI/AAAAAAAAAEc/Ed90r4piSA8/s200/50000.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;Thank you for your interest.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;At the moment I am working a few pet projects including&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A low latency, low GC, parsing, logging and writing library.&lt;/li&gt;&lt;li&gt;A direct memory collection library for storing massive amounts of data efficiently with minimal heap.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;See some of my previous post for teasers on how these will work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7464352519288872854?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7464352519288872854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/50000-pages-views-last-month.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7464352519288872854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7464352519288872854'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/50000-pages-views-last-month.html' title='50,000 pages views last month'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-G7EG3O9I7rM/Tjla3MUgGRI/AAAAAAAAAEc/Ed90r4piSA8/s72-c/50000.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1735035777427785635</id><published>2011-08-03T13:17:00.005+01:00</published><updated>2012-01-22T19:34:51.413Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>A collection with billions of entries</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;There are a number of problems with having a large number of records in memory.  One way around this is to use direct memory, but this is too low level for most developers.  Is there a way to make this more friendly?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Limitations of large numbers of objects &lt;/h2&gt;&lt;ul&gt;&lt;li&gt;The overhead per object is between 12 and 16 bytes for 64-bit JVMs. If the object is relatively small, this is significant and could be more than the data itself.&lt;/li&gt;&lt;li&gt;The GC pause time increases with the number of objects. Pause times can be around one second per GB of objects.&lt;/li&gt;&lt;li&gt;Collections and arrays only support two billion elements&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Huge collections&lt;/h2&gt;One way to store more data and still follow object orientated principles is have wrappers for direct ByteBuffers.&amp;nbsp; This can be tedious to write, but very efficient.&lt;br /&gt;&lt;br /&gt;What would be ideal is to have these wrappers generated automatically.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Small JavaBean Example&lt;/h2&gt;This is an example of JavaBean which would have far more overhead than actual data contained.&lt;br /&gt;&lt;pre&gt;interface MutableByte {&lt;br /&gt;    public void setByte(byte b);&lt;br /&gt;&lt;br /&gt;    public byte getByte();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It is also small enough that I can create billions of these on my machine. This example creates a List&amp;lt;Bytes&amp;gt; with 16 billion elements.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;final long length = 16_000_000_000L;&lt;br /&gt;HugeArrayList&amp;lt;MutableByte&amp;gt; hugeList = new HugeArrayBuilder&amp;lt;MutableByte&amp;gt;() {{&lt;br /&gt;    allocationSize = 4 * 1024 * 1024;&lt;br /&gt;    capacity = length;&lt;br /&gt;}}.create();&lt;br /&gt;&lt;br /&gt;List&amp;lt;MutableByte&amp;gt; list = hugeList;&lt;br /&gt;assertEquals(0, list.size());&lt;br /&gt;&lt;br /&gt;hugeList.setSize(length);&lt;br /&gt;&lt;br /&gt;// add a GC to see what the GC times are like.&lt;br /&gt;System.gc();&lt;br /&gt;&lt;br /&gt;assertEquals(Integer.MAX_VALUE, list.size());&lt;br /&gt;assertEquals(length, hugeList.longSize());&lt;br /&gt;&lt;br /&gt;byte b = 0;&lt;br /&gt;for (MutableByte mb : list)&lt;br /&gt;    mb.setByte(b++);&lt;br /&gt;&lt;br /&gt;b = 0;&lt;br /&gt;for (MutableByte mb : list) {&lt;br /&gt;    byte b2 = mb.getByte();&lt;br /&gt;    byte expected = b++;&lt;br /&gt;    if (b2 != expected)&lt;br /&gt;        assertEquals(expected, b2);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;From start to finish, the heap memory used is as follows. with &lt;i&gt;-verbosegc&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;0 sec - 3100 KB used&lt;br /&gt;[GC 9671K-&amp;gt;1520K(370496K), 0.0020330 secs]&lt;br /&gt;[Full GC 1520K-&amp;gt;1407K(370496K), 0.0063500 secs]&lt;br /&gt;10 sec - 3885 KB used&lt;br /&gt;20 sec - 4428 KB used&lt;br /&gt;30 sec - 4428 KB used&lt;br /&gt;  ... deleted ...&lt;br /&gt;1380 sec - 4475 KB used&lt;br /&gt;1390 sec - 4476 KB used&lt;br /&gt;1400 sec - 4476 KB used&lt;br /&gt;1410 sec - 4476 KB used&lt;br /&gt;&lt;/pre&gt;The only GC is one triggered explicitly. Without the &lt;i&gt;System.gc();&lt;/i&gt; no GC logs appear.&lt;br /&gt;&lt;br /&gt;After 20 sec, the increase in memory used is from logging how much memory was used.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;The library is relatively slow. Each get or set takes about 40 ns which really adds up when there are so many calls to make. I plan to work on it so it is much faster. ;)&lt;br /&gt;&lt;br /&gt;On the upside, it wouldn't be possible to create 16 billion objects with the memory I have, nor could it be put in an ArrayList, so having it a little slow is still better than not working at all.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related article&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/08/should-server-applications-limit.html"&gt;Should server applications limit themselves to 4 GB?&amp;nbsp;&lt;/a&gt;&lt;br /&gt;&lt;h3 class="post-title entry-title"&gt;&lt;a href="http://vanillajava.blogspot.com/2011/08/collections-library-for-millions-of.html"&gt;Collections Library for millions of elements&lt;/a&gt;&lt;/h3&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1735035777427785635?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1735035777427785635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/collection-with-billions-of-entries.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1735035777427785635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1735035777427785635'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/collection-with-billions-of-entries.html' title='A collection with billions of entries'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4050453021338702456</id><published>2011-08-03T08:39:00.004+01:00</published><updated>2012-01-22T19:34:51.500Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Should server applications limit themselves to 4 GB?</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;A very interesting talk by CTO of Azul, Gil Tene raises many timely issues about GC performance and server memory sizes.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;A typical new server should be 100 GB&lt;/h2&gt;One point he brings up is; with memory so cheap a typical server should be around 100 GB (at around $7K) Installing less memory is wasting data centre space. A typical JVM only uses 2-4 GB as the GC pause hurts responsiveness at this point.  However, if you are developing an application which only uses 2-4 GB you are writing an application which will soon fit on a mobile phone.  So how can we write server applications which can use the whole server in Java?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/presentations/Java-without-the-GC-Pauses"&gt;Java without the GC Pauses: Keeping Up with Moore’s Law and Living in a Virtualized World&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;He raises questions about how best to use that memory and not surprisingly Azul have a product which will scales to that much memory efficiently.&lt;br /&gt;&lt;br /&gt;For those who are not planing to buy such a system, you could be thinking about how you can use more memory efficiently.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;My view&lt;/h2&gt;When you increase the Eden size of an application but just create temporary garbage, the pause times don't increase. Its the retained objects which increase the pause time.&lt;br /&gt;&lt;br /&gt;The simplest thing to try is having a very large Eden size and see if the pause times increase or perhaps decrease.  It can decrease as you give more time for medium lived objects to die and less objects leave the Eden/Survivor spaces to make it into the tenured space which require long pauses to clean up.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What can you buy today&lt;/h2&gt;The prices Gil quotes are actually 6 months old now.&lt;br /&gt;&lt;br /&gt;I only quote Dell here because I find their web site easy to get a quote from.&lt;br /&gt;&lt;br /&gt;I found a Dell T610 with 96GB cost $5.8K and T710 with 192 GB costs $12.2K on their web site. &lt;br /&gt;&lt;br /&gt;I recently bought a PC with 24 GB for £1K. ;)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related article&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/08/collection-with-billions-of-entries.html"&gt;A collection with billions of entries&amp;nbsp;&lt;/a&gt;&lt;br /&gt;&lt;h3 class="post-title entry-title"&gt;&lt;a href="http://vanillajava.blogspot.com/2011/08/collections-library-for-millions-of.html"&gt;Collections Library for millions of elements&lt;/a&gt;&lt;/h3&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4050453021338702456?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4050453021338702456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/should-server-applications-limit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4050453021338702456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4050453021338702456'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/should-server-applications-limit.html' title='Should server applications limit themselves to 4 GB?'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1617960191062726354</id><published>2011-08-02T09:43:00.002+01:00</published><updated>2012-01-26T15:16:51.854Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Strange Hello World in Java</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;This is a strange Hello World program because it only needs to be compiled, not run. How does it work? Hint: it only works on MS-DOS/Windows. ;)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Program&lt;/h2&gt;In a file called A.java or any name exception Con.java&lt;br /&gt;&lt;pre&gt;class Con {&lt;br /&gt;    String hi = "\n\n\tHello World!\n\n";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;when compiled produces&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Kk3E8hbTB8E/Tje3ud0FPgI/AAAAAAAAAEU/YgCuSLZix3I/s1600/Hello%2BWorld.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Kk3E8hbTB8E/Tje3ud0FPgI/AAAAAAAAAEU/YgCuSLZix3I/s1600/Hello%2BWorld.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;How does this work&lt;/h2&gt;MS-DOS/Windows treats all files which start with CON (in any case and with any extension) as the console. So when &lt;i&gt;javac&lt;/i&gt; writes the Con.class file, it is written to the console instead.&lt;br /&gt;&lt;br /&gt;In the MS world; its not a bug, its a feature.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;For more details&lt;/h2&gt;&lt;a href="http://support.microsoft.com/kb/31157"&gt;Use PRINT# to MS-DOS "CON" Device to Send ANSI Escape Codes&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1617960191062726354?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1617960191062726354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/strange-hello-world-in-java.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1617960191062726354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1617960191062726354'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/strange-hello-world-in-java.html' title='Strange Hello World in Java'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-Kk3E8hbTB8E/Tje3ud0FPgI/AAAAAAAAAEU/YgCuSLZix3I/s72-c/Hello%2BWorld.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3097363692212193715</id><published>2011-08-01T17:41:00.002+01:00</published><updated>2012-01-22T19:34:51.432Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Comparing Java 7 Async NIO with NIO.</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;SDP (&lt;a href="http://download.oracle.com/javase/tutorial/sdp/sockets/index.html"&gt;Sockets Direct Protocol&lt;/a&gt;) in Java 7 promises better integration with InfiniBand.  This comes with a new Socket classes AsynchronousSocketChannel and AsynchronousServerSocketChannel.  Is there any advantage in using these libraries if you don't have InfiniBand?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Creating a server socket&lt;/h2&gt;The API for AsynchronousServerSocketChannel is slightly different to ServerSocketChannel.  The most notable difference is the use of Futures instead of always blocking.&lt;br /&gt;&lt;pre&gt;final AsynchronousServerSocketChannel ssc =&lt;br /&gt;      AsynchronousServerSocketChannel.open().bind(new InetSocketAddress("localhost", 9999));&lt;br /&gt;Future&amp;lt;AsynchronousSocketChannel&gt; accepted = ssc.accept();&lt;br /&gt;AsynchronousSocketChannel sc2 = accepted.get();&lt;br /&gt;&lt;br /&gt;ByteBuffer bb = ByteBuffer.allocateDirect(4096);&lt;br /&gt;Future&amp;lt;Integer&gt; readFuture = sc2.read(bb);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Creating a client socket&lt;/h2&gt;Similarly the client can start a connection and later wait when the connection is really needed.&lt;br /&gt;&lt;pre&gt;AsynchronousSocketChannel sc = AsynchronousSocketChannel.open();&lt;br /&gt;Future&lt;void&gt; connected = sc.connect(new InetSocketAddress("localhost", 9999));&lt;br /&gt;// later ensure we are connected.&lt;br /&gt;connected.get();&lt;br /&gt;&lt;br /&gt;ByteBuffer bb = ByteBuffer.allocateDirect(4096);&lt;br /&gt;// populate bb&lt;br /&gt;Future&amp;lt;Integer&gt; writeFuture = sc2.write(bb);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Is there any performance differences?&lt;/h2&gt;Without threads, the Asynchronous IO was 5-10% faster. However once threads were used, the performance dropped.  This could be because this is Java 7 &lt;b&gt;update 0&lt;/b&gt;.  I look forward to testing this again in the future.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Async Socket latency was 1/50/99%tile 5.2/5.4/7.3 us&lt;br /&gt;Async Socket Throughput was 186 K/s&lt;br /&gt;Threaded Async Socket Latency for 1/50/99%tile 13.8/16.9/24.7 us&lt;br /&gt;Threaded Async Socket Throughput was 183 K/s&lt;br /&gt;&lt;/pre&gt;The best of three runs was used.&lt;br /&gt;&lt;br /&gt;For comparison, the same tests using regular NIO on Java 7 were&lt;br /&gt;&lt;pre&gt;Socket latency was 1/50/99%tile 5.6/5.8/7.0 us&lt;br /&gt;Socket Throughput was 170 K/s&lt;br /&gt;Threaded Socket Latency for 1/50/99%tile 6.0/8.5/10.7 us&lt;br /&gt;Threaded Socket Throughput was 234 K/s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;The code&lt;/h2&gt;Its worth nothing that the code is slightly more complex to use than regular NIO. However, the features added are powerful and for the brave, it will be valuable.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/socket/AsyncPingTest.java"&gt;&lt;b&gt;Asynchronous NIO Socket - AsyncPingTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/socket/PingTest.java"&gt;&lt;b&gt;Plain NIO Socket - PingTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;The API for Asynchronous sockets looks promising despite the added complexity.  However the performance many not be there unless you have the right hardware, yet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3097363692212193715?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3097363692212193715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/comparing-java-7-async-nio-with-nio.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3097363692212193715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3097363692212193715'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/comparing-java-7-async-nio-with-nio.html' title='Comparing Java 7 Async NIO with NIO.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7045701525249760452</id><published>2011-08-01T09:06:00.006+01:00</published><updated>2012-01-22T19:34:51.575Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Using tmpfs to speed up "disk" access</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;If you have an application which performs a lot disk reads/writes and a modest amount of data, you don't need to keep. e.g. a unit tests, application builds. Using tmpfs may be the answer speeding up the process.&lt;br /&gt;&lt;br /&gt;In this article I compare using a tmpfs, an SSD, a hard drive and an NFS drive.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Comparing creating a file and deleting it&lt;/h2&gt;Small files (256 bytes) are created repeatedly and an average time taken.  These files are deleted in a second test.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;File system type&lt;/th&gt;&lt;th&gt;machine&lt;/th&gt;&lt;th&gt;file creation&lt;/th&gt;&lt;th&gt;file deletion&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;tmpfs&lt;/td&gt;&lt;td&gt;fast&lt;/td&gt;&lt;td align="right"&gt;7.2 us&lt;/td&gt;&lt;td align="right"&gt;3.9 us&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;tmpfs&lt;/td&gt;&lt;td&gt;older&lt;/td&gt;&lt;td align="right"&gt;19.9 us&lt;/td&gt;&lt;td align="right"&gt;8.9 us&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SSD ext4&lt;/td&gt;&lt;td&gt;fast&lt;/td&gt;&lt;td align="right"&gt;22.9 us&lt;/td&gt;&lt;td align="right"&gt;9.1 us&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7200 RPM ext4&lt;/td&gt;&lt;td&gt;older&lt;/td&gt;&lt;td align="right"&gt;42.9 us&lt;/td&gt;&lt;td align="right"&gt;24.1 us&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NFS&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td align="right"&gt;11,238 us&lt;/td&gt;&lt;td align="right"&gt;5,294 us&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;The "fast" machine was a 3.8 GHz i7 with 1600 MHz memory.&lt;br /&gt;&lt;br /&gt;The "older" machine was a 2.5 GHz AMD 4800 with 533 MHz memory.&lt;br /&gt;&lt;br /&gt;The NFS drive is a QNAP TS-210 with mirrored 7,200 RPM drives over a home plug network.&lt;br /&gt;&lt;br /&gt;The write cache for the 7,200 RPM disk is making a big difference.  Without the disk cache the performance would closer to that of the NFS file system.&lt;br /&gt;&lt;br /&gt;In each case, the tmpfs was limited to 80% of the total main memory. Using a larger tmpfs will impact performance.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Code&lt;/h2&gt;The core part of the test looks like this.&lt;br /&gt;&lt;pre&gt;byte[] bytes = new byte[256];&lt;br /&gt;long start = System.nanoTime();&lt;br /&gt;for (int i = 0; i &lt; files; i++) {&lt;br /&gt;    File file = new File(dir, Integer.toString(i));&lt;br /&gt;    FileOutputStream fos = new FileOutputStream(file);&lt;br /&gt;    fos.write(bytes);&lt;br /&gt;    fos.close();&lt;br /&gt;}&lt;br /&gt;long time = System.nanoTime() - start;&lt;br /&gt;System.out.printf("Took an average of %.1f us to write to LOCAL filesystem%n", time/1e3/files);&lt;br /&gt;&lt;/pre&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/files/OpenCloseFilesTest.java"&gt;&lt;b&gt;OpenCloseFilesTest.java&lt;/b&gt;&lt;/a&gt;&lt;p/&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;Using a tmpfs can be 2-3x faster than a local disk with write cache. When you have working data you don't need to keep it can speed up your process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7045701525249760452?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7045701525249760452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/08/using-tmpfs-to-speed-up-disk-access.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7045701525249760452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7045701525249760452'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/08/using-tmpfs-to-speed-up-disk-access.html' title='Using tmpfs to speed up &quot;disk&quot; access'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7288653859898192277</id><published>2011-07-30T20:52:00.008+01:00</published><updated>2012-01-22T19:34:51.582Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Synchronized vs Lock performance</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;There are a number of articles on whether &lt;i&gt;synchronized&lt;/i&gt; or &lt;i&gt;Locks&lt;/i&gt; are faster. There appear to be opinions in favour of either option. In this article I attempt to show how you can achieve different views depending on how you benchmark the two approaches.&lt;br /&gt;&lt;br /&gt;I have included AtomicInteger to see how a volatile field compares.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What are some of the differences&lt;/h2&gt;The &lt;i&gt;synchronized&lt;/i&gt; keyword has naturally built in language support.  This can mean the JIT can optimise synchronised blocks in ways it cannot with Locks. e.g. it can combine synchronized blocks.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;Lock&lt;/i&gt; has additional method such as &lt;i&gt;tryLock&lt;/i&gt; which is not an option for a &lt;i&gt;synchronized&lt;/i&gt; block.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The test&lt;/h2&gt;As the JIT can optimise &lt;i&gt;synchronized&lt;/i&gt; in ways a Lock cannot, I wanted to have a test which might demonstrate this and one which might "fool" the JIT.&lt;br /&gt;&lt;br /&gt;In this test, 25 million locks were performed between each of the threads. Java 6 update 26 was used.&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Threads&lt;/th&gt;&lt;th&gt;1x synch&lt;/th&gt;&lt;th&gt;1x Lock&lt;/th&gt;&lt;th&gt;1x AtomicInteger&lt;/th&gt;&lt;th&gt;2x synch&lt;/th&gt;&lt;th&gt;2x Lock&lt;/th&gt;&lt;th&gt;2x AtomicInteger&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;1 :&lt;/td&gt;&lt;td&gt;0.937&lt;/td&gt;&lt;td&gt;0.786&lt;/td&gt;&lt;td&gt;0.400&lt;/td&gt;&lt;td&gt;1.532&lt;/td&gt;&lt;td&gt;1.484&lt;/td&gt;&lt;td&gt;0.569&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;2 :&lt;/td&gt;&lt;td&gt;2.766&lt;/td&gt;&lt;td&gt;4.597&lt;/td&gt;&lt;td&gt;0.676&lt;/td&gt;&lt;td&gt;5.398&lt;/td&gt;&lt;td&gt;6.355&lt;/td&gt;&lt;td&gt;1.278&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;4 :&lt;/td&gt;&lt;td&gt;3.904&lt;/td&gt;&lt;td&gt;1.267&lt;/td&gt;&lt;td&gt;0.694&lt;/td&gt;&lt;td&gt;6.330&lt;/td&gt;&lt;td&gt;2.657&lt;/td&gt;&lt;td&gt;1.354&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;8 :&lt;/td&gt;&lt;td&gt;3.884&lt;/td&gt;&lt;td&gt;0.953&lt;/td&gt;&lt;td&gt;1.011&lt;/td&gt;&lt;td&gt;5.418&lt;/td&gt;&lt;td&gt;2.073&lt;/td&gt;&lt;td&gt;2.761&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;16 :&lt;/td&gt;&lt;td&gt;3.207&lt;/td&gt;&lt;td&gt;0.869&lt;/td&gt;&lt;td&gt;1.171&lt;/td&gt;&lt;td&gt;4.817&lt;/td&gt;&lt;td&gt;1.656&lt;/td&gt;&lt;td&gt;2.800&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;32 :&lt;/td&gt;&lt;td&gt;3.213&lt;/td&gt;&lt;td&gt;0.853&lt;/td&gt;&lt;td&gt;1.240&lt;/td&gt;&lt;td&gt;4.915&lt;/td&gt;&lt;td&gt;1.680&lt;/td&gt;&lt;td&gt;2.843&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align="right"&gt;64 :&lt;/td&gt;&lt;td&gt;3.322&lt;/td&gt;&lt;td&gt;0.921&lt;/td&gt;&lt;td&gt;1.269&lt;/td&gt;&lt;td&gt;5.049&lt;/td&gt;&lt;td&gt;1.639&lt;/td&gt;&lt;td&gt;2.843&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;These are the times to perform 25 million locks/operation in seconds. Lower numbers are better.  Different system will get different results, so these should be taken as a relative performance.&lt;br /&gt;&lt;br /&gt;Note: It appears that Lock performs best with high numbers of threads. However this may because the performance approaches the single threaded performance. It may do this by avoiding contention and letting just one thread run for long periods of time.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/threads/SynchronizedVsLockTest.java"&gt;&lt;b&gt;SynchronizedVsLockTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;In general, unless you have measured you system and you know you have a performance issue, you should do what you believe is simplest and clearest and it is likely to performance well.&lt;br /&gt;&lt;br /&gt;These results indicate that synchronized is best for a small number of threads accessing a lock (&amp;lt;4) and Lock may be best for a high number of threads accessing the same locks.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related articles&lt;/h2&gt;&lt;a href="http://my.safaribooksonline.com/book/programming/java/0321349601/explicit-locks/ch13lev1sec4"&gt;Java Concurrency in practice&lt;/a&gt; - Favours locks for performance, otherwise suggest synchronized be used if not an issue. States Lock are much faster for Java 5.0, slightly faster for Java 6&lt;br /&gt;&lt;a href="http://blog.rapleaf.com/dev/2011/06/16/java-performance-synchronized-vs-lock/"&gt;Java Performance: synchronized() vs Lock&lt;/a&gt; - Favours &lt;i&gt;synchronized&lt;/i&gt;, based on a micro-benchmark. Compares one and two threads&lt;br /&gt;&lt;a href="http://blogs.oracle.com/dave/entry/java_util_concurrent_reentrantlock_vs"&gt;java.util.concurrent ReentrantLock vs synchronized() - which should you use?&lt;/a&gt; - Favours synchronized on technical arguments&lt;br /&gt;&lt;a href="http://sourceforge.net/apps/trac/lilith/wiki/SynchronizedVsFairLock"&gt;Synchronized vs. Lock vs. fair Lock&lt;/a&gt; - Compares locks based on fairness rather than performance&lt;br /&gt;&lt;a href="http://devrandom.belsare.in/2011/01/synchronized-vs-custom-locking-java.html"&gt;synchronized vs custom locking: Java synchronization performance&lt;/a&gt; - Determines that Locks were 5x faster for Java 5.0&lt;br /&gt;&lt;a href="http://b0c1.wikidot.com/java:lockperformance"&gt;Java synchronized block vs ReentantLock performance&lt;/a&gt; - Compares synchronized vs Locks with 10 threads, concludes Locks are significantly faster (about 5x) Not clear if this test was done with Java 5.0 also&lt;br /&gt;&lt;a href="http://lycog.com/concurency/performance-reentrantlock-synchronized/"&gt; Performance of ReentrantLock and Synchronized&lt;/a&gt; - Compares different numbers of threads and concludes synchronized is only fastest for one thread&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7288653859898192277?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7288653859898192277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/synchronized-vs-lock-performance.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7288653859898192277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7288653859898192277'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/synchronized-vs-lock-performance.html' title='Synchronized vs Lock performance'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5522101189690564934</id><published>2011-07-30T13:40:00.003+01:00</published><updated>2012-01-22T19:34:51.541Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>C++ or Java, which is faster for high frequency trading?</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;There are conflicting views as to what is the best solution for high frequency trading.  Part of the problem is that what is high frequency trading varies more than you might expect, another part is what is meant by faster.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;My View&lt;/h2&gt;If you have a typical Java programmer and typical C++ programmer, each with a few years experience writing a typical Object Oriented Program, and you give them the same amount of time, the Java programmer is likely to have a working program earlier and will have more time to tweak the application.  In this situation it is likely the Java application will be faster. IMHO.&lt;br /&gt;&lt;br /&gt;In my experience, Java performs better at C++ at detecting code which doesn't need to be done. esp micro-benchmarks which don't do anything useful. ;) If you tune Java and C++ as far as they can go given any amount of expertise and time, the C++ program will be faster.  However, given limited resources and in changing environment a dynamic language will out perform. i.e. in real world applications.&lt;br /&gt;&lt;br /&gt;In the equities space latency you need latencies sub-10 us to be seriously high frequency. Java and even standard OOP C++ on commodity hardware is not an option. You need C or a cut down version of C++ and specialist hardware like FPGAs, GPUs.&lt;br /&gt;&lt;br /&gt;In FX, high frequency means a latencies of sub-100 us.  In this space C++ or a cut down Java (low GC) with kernel bypass network adapter is an option. In this space, using one language or another will have pluses and minuses.  Personally, I think Java gives more flexibility as the exchanges are constantly changing, assuming you believe you can use IT for competitive advantage.&lt;br /&gt;&lt;br /&gt;In many cases, when people talk about high frequency, esp Banks, they are talking sub 1 ms or single digit ms.  In this space, I would say the flexibility/dynamic programming of Java, Scala or C# etc would give you time to market, maintainability and reliability advantages over C/C++ or FPGA. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The problem Java faces&lt;/h2&gt;The problem is not in the language as such, but a lack of control over caches, context switches and interrupts.  If you copy a block of memory, something which occurs in native memory, but using a different delay between runs, that copy gets slower depending on what has happened between copies.  &lt;br /&gt;&lt;br /&gt;The problem is not GC, or Java as neither of these play much of a part. The problem is that part of the cache has been swapped out and the copy itself takes longer.  This is the same for any operation which accesses memory. e.g. accessing plain objects will also be slower.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;private void doTest(Pauser delay) throws InterruptedException {&lt;br /&gt;    int[] times = new int[1000 * 1000];&lt;br /&gt;    byte[] bytes = new byte[32* 1024];&lt;br /&gt;    byte[] bytes2 = new byte[32 * 1024];&lt;br /&gt;    long end = System.nanoTime() + (long) 5e9;&lt;br /&gt;    int i;&lt;br /&gt;    for (i = 0; i &amp;lt; times.length; i++) {&lt;br /&gt;        long start = System.nanoTime();&lt;br /&gt;        System.arraycopy(bytes, 0, bytes2, 0, bytes.length);&lt;br /&gt;        long time = System.nanoTime() - start;&lt;br /&gt;        times[i] = (int) time;&lt;br /&gt;        delay.pause();&lt;br /&gt;        if (start &amp;gt; end) break;&lt;br /&gt;    }&lt;br /&gt;    Arrays.sort(times, 0, i);&lt;br /&gt;    System.out.printf(delay + ": Copy memory latency 1/50/99%%tile %.1f/%.1f/%.1f us%n",&lt;br /&gt;            times[i / 100] / 1e3,&lt;br /&gt;            times[i / 2] / 1e3,&lt;br /&gt;            times[i - i / 100 - 1] / 1e3&lt;br /&gt;    );&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The test does the same thing many times, with different delays between performing that test.  The test spends most of its time in native methods and no objects are created or discarded as during the test.&lt;br /&gt;&lt;pre&gt;YIELD: Copy memory latency 1/50/99%tile 1.6/1.6/2.3 us&lt;br /&gt;NO_WAIT: Copy memory latency 1/50/99%tile 1.6/1.6/1.6 us&lt;br /&gt;BUSY_WAIT_10: Copy memory latency 1/50/99%tile 2.8/3.5/4.4 us&lt;br /&gt;BUSY_WAIT_3: Copy memory latency 1/50/99%tile 2.7/3.0/4.0 us&lt;br /&gt;BUSY_WAIT_1: Copy memory latency 1/50/99%tile 1.6/1.6/2.5 us&lt;br /&gt;SLEEP_10: Copy memory latency 1/50/99%tile 2.2/3.4/5.1 us&lt;br /&gt;SLEEP_3: Copy memory latency 1/50/99%tile 2.2/3.4/4.4 us&lt;br /&gt;SLEEP_1: Copy memory latency 1/50/99%tile 1.8/3.4/4.2 us&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With -XX:+UseLargePages with Java 7&lt;br /&gt;&lt;pre&gt;YIELD: Copy memory latency 1/50/99%tile 1.6/1.6/2.7 us&lt;br /&gt;NO_WAIT: Copy memory latency 1/50/99%tile 1.6/1.6/1.8 us&lt;br /&gt;BUSY_WAIT_10: Copy memory latency 1/50/99%tile 2.7/3.6/6.6 us&lt;br /&gt;BUSY_WAIT_3: Copy memory latency 1/50/99%tile 2.7/2.8/5.0 us&lt;br /&gt;BUSY_WAIT_1: Copy memory latency 1/50/99%tile 1.7/1.8/2.6 us&lt;br /&gt;SLEEP_10: Copy memory latency 1/50/99%tile 2.4/4.0/5.2 us&lt;br /&gt;SLEEP_3: Copy memory latency 1/50/99%tile 2.3/3.9/4.8 us&lt;br /&gt;SLEEP_1: Copy memory latency 1/50/99%tile 2.1/3.3/3.7 us&lt;br /&gt;&lt;/pre&gt;The best of three runs was used.&lt;br /&gt;&lt;br /&gt;The typical time (the middle value) it takes to perform the memory copy varies between 1.6 and 4.6 us depending on whether there was a busy wait or sleep for 1 to 10 ms. This is a ratio of about 3x which has nothing to do with Java, but something it has no real control over. Even the best times vary by about 2x.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/threads/ThreadLatencyTest.java"&gt;&lt;b&gt;ThreadlatencyTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;In ultra-high frequency, the core engine will be more C, assembly and custom hardware than OOP C++ or Java. In markets where the latency requirements of the engine are less tight C++ and Low GC Java become an option.  As latency requirement become less tight, Java and other dynamic languages can be more productive. In this situation, Java is faster to market so you can take advantages of changes in the market/requirements.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5522101189690564934?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5522101189690564934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/c-or-java-which-is-faster-for-high.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5522101189690564934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5522101189690564934'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/c-or-java-which-is-faster-for-high.html' title='C++ or Java, which is faster for high frequency trading?'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4202233265761125039</id><published>2011-07-29T09:31:00.001+01:00</published><updated>2012-01-22T19:34:51.512Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>How fast are Java Datagrams?</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Following my article &lt;a href="http://vanillajava.blogspot.com/2011/07/how-fast-are-java-sockets.html"&gt;How fast are Java sockets&lt;/a&gt;, this article follows the same tests except for Datagrams which use UDP rather than TCP.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The timings&lt;/h2&gt;The tests are the same except Datagrams don't support busy waiting in Java 6 which hurts the Threaded Ping latency&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;UDP Pings per second 224 K/s&lt;br /&gt;UDP Pings latency was 1/50/99%tile 4.1/4.2/4.7 us&lt;br /&gt;Threaded UDP Pings per second 131 K/s&lt;br /&gt;Threaded UDP Pings latency was 1/50/99%tile 9.8/11.0/33.2 us&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Comparison&lt;/h2&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Test&lt;/th&gt;&lt;th&gt;&amp;nbsp;Threaded&amp;nbsp;&lt;/th&gt;&lt;th&gt;Throughput&lt;/th&gt;&lt;th&gt;Typical latency&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Datagram Ping&lt;/td&gt;&lt;td align="center"&gt;no&lt;/td&gt;&lt;td align="right"&gt;224 K/s&lt;/td&gt;&lt;td align="right"&gt;&amp;nbsp;4.2 μs &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Socket Ping&lt;/td&gt;&lt;td align="center"&gt;no&lt;/td&gt;&lt;td align="right"&gt;170 K/s&lt;/td&gt;&lt;td align="right"&gt;&amp;nbsp;5.8 μs &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Datagram Ping&lt;/td&gt;&lt;td align="center"&gt;yes&lt;/td&gt;&lt;td align="right"&gt;131 K/s&lt;/td&gt;&lt;td align="right"&gt;11.0 μs &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Socket Ping&lt;/td&gt;&lt;td align="center"&gt;yes&lt;/td&gt;&lt;td align="right"&gt;235 K/s&lt;/td&gt;&lt;td align="right"&gt;8.5 μs &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;h2&gt;The Code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/datagram/DatagramPingTest.java"&gt;&lt;b&gt;DatagramPingTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related articles&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/how-fast-are-java-sockets.html"&gt;How fast are Java sockets&lt;/a&gt;&lt;p/&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/send-xml-over-socket-fast.html"&gt;Send XML over a Socket fast&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4202233265761125039?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4202233265761125039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/how-fast-are-java-datagrams.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4202233265761125039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4202233265761125039'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/how-fast-are-java-datagrams.html' title='How fast are Java Datagrams?'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6251484712965108700</id><published>2011-07-28T08:12:00.000+01:00</published><updated>2011-07-28T08:12:06.300+01:00</updated><title type='text'>Why are the keys of a Map in a jumbled order</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;When you first try to printout a HashMap, the order doesn't make any sense and when you add entries, they appear to jump around.  What is going on?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The order of Maps&lt;/h2&gt;The order keys should appear is not defined in many implementations.&lt;br /&gt;&lt;br /&gt;Hash map uses a hash of the key to place the key/value in a pseudo random place in the underlying store (an array)  How it does this is different in different implementations.  For HashMap the size of the Map is always a power of 2. For Hashtable the size grows 11, 23, 47, 95.&lt;br /&gt;&lt;br /&gt;For LinkedHashMap, the order will be the order the keys were added and for TreeMap &amp; ConcurrentSkipList, the order is based of the Comparable.compareTo() result (asciibetical order for String)&lt;br /&gt;&lt;br /&gt;For Hashtable and HashMap changing the initial size changes how the keys are hashed and thus their order&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public static void main(String... args) {&lt;br /&gt;    populate(new Hashtable&lt;String, String&gt;());&lt;br /&gt;    populate(new Hashtable&lt;String, String&gt;(47), " (47)");&lt;br /&gt;    populate(new Hashtable&lt;String, String&gt;(95), " (95)");&lt;br /&gt;    populate(new HashMap&lt;String, String&gt;());&lt;br /&gt;    populate(new HashMap&lt;String, String&gt;(32), " (32)");&lt;br /&gt;    populate(new HashMap&lt;String, String&gt;(64), " (64)");&lt;br /&gt;    populate(new LinkedHashMap&lt;String, String&gt;());&lt;br /&gt;    populate(new IdentityHashMap&lt;String, String&gt;());&lt;br /&gt;    populate(new WeakHashMap&lt;String, String&gt;());&lt;br /&gt;    populate(new ConcurrentHashMap&lt;String, String&gt;());&lt;br /&gt;    populate(new TreeMap&lt;String, String&gt;());&lt;br /&gt;    populate(new ConcurrentSkipListMap&lt;String, String&gt;());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static void populate(Map&lt;String, String&gt; map) {&lt;br /&gt;    populate(map, "");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static void populate(Map&lt;String, String&gt; map, String suffix) {&lt;br /&gt;    for (String s : "one,two,three,four,five,six,seven,eight,nine,ten".split(","))&lt;br /&gt;        map.put(s, s);&lt;br /&gt;    System.out.println(map.getClass().getSimpleName() + suffix + " " + map.keySet());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;prints&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Hashtable [three, six, ten, seven, nine, one, five, four, two, eight]&lt;br /&gt;Hashtable (47) [ten, five, seven, two, three, one, nine, six, eight, four]&lt;br /&gt;Hashtable (95) [nine, five, six, one, seven, eight, ten, two, four, three]&lt;br /&gt;HashMap [ten, two, seven, five, nine, one, three, four, eight, six]&lt;br /&gt;HashMap (32) [ten, five, nine, one, eight, six, two, seven, three, four]&lt;br /&gt;HashMap (64) [ten, nine, one, eight, six, three, four, five, two, seven]&lt;br /&gt;LinkedHashMap [one, two, three, four, five, six, seven, eight, nine, ten]&lt;br /&gt;IdentityHashMap [four, two, five, nine, three, six, eight, one, seven, ten]&lt;br /&gt;WeakHashMap [six, eight, four, three, nine, one, seven, five, ten, two]&lt;br /&gt;ConcurrentHashMap [seven, two, one, nine, four, six, eight, three, ten, five]&lt;br /&gt;TreeMap [eight, five, four, nine, one, seven, six, ten, three, two]&lt;br /&gt;ConcurrentSkipListMap [eight, five, four, nine, one, seven, six, ten, three, two]&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6251484712965108700?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6251484712965108700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/why-are-keys-of-map-in-jumbled-order.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6251484712965108700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6251484712965108700'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/why-are-keys-of-map-in-jumbled-order.html' title='Why are the keys of a Map in a jumbled order'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-2599437761969063921</id><published>2011-07-27T19:22:00.003+01:00</published><updated>2012-01-26T15:17:51.388Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>Size of an entry in a Map</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The have been some very good articles on the size of a map.  However as a map grows, it initial size become less important and the size per entry is what matters.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;How are the sizes measured&lt;/h2&gt;In these tests an &lt;i&gt;int&lt;/i&gt; key and &lt;i&gt;long&lt;/i&gt; values are used.  This adds a small but realistic size to each entry.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Size per entry of a medium sized Map&lt;/h2&gt;The following are the size per entry in bytes. The Map has 1024 entries.&lt;br /&gt;&lt;br /&gt;&lt;table border="0" cellspacing="0" cols="4" frame="VOID" rules="NONE"&gt;&lt;colgroup&gt;&lt;col width="151"&gt;&lt;/col&gt;&lt;col width="86"&gt;&lt;/col&gt;&lt;col width="86"&gt;&lt;/col&gt;&lt;col width="86"&gt;&lt;/col&gt;&lt;/colgroup&gt;  &lt;tbody&gt;&lt;tr&gt;    &lt;th align="LEFT" height="17" width="151"&gt;Type of Map&lt;/th&gt;    &lt;th align="LEFT" width="86"&gt;32-bit&lt;/th&gt;    &lt;th align="LEFT" width="86"&gt;64-bit compressed&lt;/th&gt;    &lt;th align="LEFT" width="86"&gt;64-bit not compressed&lt;/th&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;TIntLongHashMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;26.9&lt;/td&gt;    &lt;td align="RIGHT"&gt;26.9&lt;/td&gt;    &lt;td align="RIGHT"&gt;27.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;FastMap (recycled)&lt;/td&gt;    &lt;td align="RIGHT"&gt;32.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;39.9&lt;/td&gt;    &lt;td align="RIGHT"&gt;47.9&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;IdentityHashMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;48.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;56.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;80.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;ConcurrentSkipListMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;68.3&lt;/td&gt;    &lt;td align="RIGHT"&gt;76.1&lt;/td&gt;    &lt;td align="RIGHT"&gt;108.3&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;TreeMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;64.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;80.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;112.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;HashMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;64.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;80.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;112.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;SynchronizedMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;64.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;80.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;112.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;ConcurrentHashMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;65.2&lt;/td&gt;    &lt;td align="RIGHT"&gt;81.4&lt;/td&gt;    &lt;td align="RIGHT"&gt;114.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;Properties&lt;/td&gt;    &lt;td align="RIGHT"&gt;68.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;84.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;120.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;Hashtable&lt;/td&gt;    &lt;td align="RIGHT"&gt;68.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;84.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;120.0&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;LinkedHashMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;72.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;88.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;128.1&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;    &lt;td align="LEFT" height="17"&gt;WeakHashMap&lt;/td&gt;    &lt;td align="RIGHT"&gt;80.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;88.0&lt;/td&gt;    &lt;td align="RIGHT"&gt;136.1&lt;/td&gt;   &lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&amp;nbsp; &lt;br /&gt;The Javolution FastMap needed to be recycled.  If it is not recycled, it was the largest per entry.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;It may be worth considering The GNU Trove collections if you have primitive keys and/or values. However if you have non-trivial keys or values classes, the size of the collection is less likely to matter.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/sizeof/SizeOfMapsTest.java"&gt;&lt;b&gt;SizeOfMapsTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related Links&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/java-how-much-memory-do-different.html"&gt;Java: How much memory do different arrays consume &lt;/a&gt;&lt;br/&gt; &lt;a href="http://www.javaspecialists.eu/archive/Issue193.html"&gt;&lt;br /&gt;Memory Usage of Maps&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-2599437761969063921?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/2599437761969063921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/size-of-entry-in-map.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2599437761969063921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/2599437761969063921'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/size-of-entry-in-map.html' title='Size of an entry in a Map'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1162887639212272405</id><published>2011-07-27T14:12:00.002+01:00</published><updated>2012-01-22T19:34:51.409Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Send XML over a Socket fast</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;XML parsers are designed to handle any type of XML message you can send.  However if you assume the XML will always follow a specific format how fast can you make it.&lt;br /&gt;&lt;br /&gt;This follows my article on &lt;a href="http://vanillajava.blogspot.com/2011/07/how-fast-are-java-sockets.html"&gt;How fast are Java sockets&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The format&lt;/h2&gt;For this article I have written a self contained test which sends a heartbeat request and which expect a heartbeat response.&lt;br /&gt;&lt;pre&gt;&amp;lt;Root timestamp="{timestamp}"&gt;&amp;lt;HeartbeatRequest sequence="{sequence}"/&gt;&amp;lt;/Root&gt;&lt;br /&gt;&amp;lt;Root timestamp="{timestamp}"&gt;&amp;lt;HeartbeatResponse sequence="{sequence}"/&gt;&amp;lt;/Root&gt;&lt;br /&gt;&lt;/pre&gt;In this test, the sequence number contains the System.nanoTime().  When the client gets back the heartbeat response it can calculate the round trip time.&lt;br /&gt;&lt;br /&gt;Messages are parsed and a listener interface called.&lt;br /&gt;&lt;pre&gt;static interface EventListener {&lt;br /&gt;        void heartbeatRequest(long timestamp, long sequenceNumber);&lt;br /&gt;&lt;br /&gt;        void heartbeatResponse(long timestamp, long sequenceNumber);&lt;br /&gt;&lt;br /&gt;        void error(String message);&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Latency&lt;/h2&gt;Two messages are sent in quick succession and any data returned is processed.  From this the latency of each message can be determined by comparing the System.nanoTime() with the sequence number.&lt;br /&gt;&lt;br /&gt;Sending simple XML messages&lt;br /&gt;&lt;pre&gt;Socket latency was 1/50/99%tile 11.3/15.6/63.9 &amp;mu;s&lt;br /&gt;&lt;/pre&gt;Compared with sending 1KB with no data.&lt;br /&gt;&lt;pre&gt;Threaded Socket Latency for 1/50/99%tile 6.0/8.5/10.7 &amp;mu;s&lt;br /&gt;&lt;/pre&gt;The latency has increased, in particular the high percentile latency.  This indicates the variation in times has also increased.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Throughput&lt;/h2&gt;Two messages are sent in quick succession and any data returned is processed.  The throughput after more than 10 seconds is calculated.&lt;br /&gt;&lt;br /&gt;Send simple XML messages.&lt;br /&gt;&lt;pre&gt;Socket throughput was 264 K/s&lt;br /&gt;&lt;/pre&gt;Compared with sending 1KB with no data.&lt;br /&gt;&lt;pre&gt;Threaded Socket Throughput was 234 K/s&lt;br /&gt;&lt;/pre&gt;The throughput is slightly higher. This could be because the message size is much smaller.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The code&lt;/h2&gt;It is worth noting that this example creates next to no garbage and the GC doesn't run (checked with &lt;i&gt;-verbosegc&lt;/i&gt;) even though the test is running flat out for more than 10 seconds.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/socket/XmlServiceTest.java"&gt;XmlServiceTest.java&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related articles&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/how-fast-are-java-sockets.html"&gt;How fast are Java sockets&lt;/a&gt;&lt;p/&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/how-fast-are-java-datagrams.html"&gt;How fast are Java Datagrams?&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1162887639212272405?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1162887639212272405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/send-xml-over-socket-fast.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1162887639212272405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1162887639212272405'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/send-xml-over-socket-fast.html' title='Send XML over a Socket fast'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4270608064388563118</id><published>2011-07-27T09:52:00.004+01:00</published><updated>2012-01-22T19:34:51.516Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>How fast are Java sockets</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;How long a request/response takes and the rate requests can be performed in a Java application depends on a number of factors.  The network, the network adapter, Java Socket and TCP layer, and what your application does.&lt;br /&gt;&lt;br /&gt;Usually the last factor is your limitation. What if you wanted to test the overhead Java/TCP contributes, here is a way you can test this.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Latency and throughput&lt;/h2&gt;The Latency, in this test, is the Round Trip Time (sometimes written as RTT) This is the time between sending a request and receiving the response.  This includes the delay on the client side, the transport and the delay on the server side.&lt;br /&gt;&lt;br /&gt;The Throughput is a measure of how many request/responses can be performed in a given amount of time.  How long each request/response takes is not measured, and has no impact unless its really large.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Results&lt;/h2&gt;These results are for a &lt;a href="http://vanillajava.blogspot.com/2011/07/new-toy-for-home.html"&gt;fast PC&lt;/a&gt; doing nothing but pass data back and forth over loopback.  This will be one of the limiting factors to using Java and TCP on your system.  Your server running a real application on a real network will not be faster than this.&lt;br /&gt;&lt;br /&gt;Your should test your system as the hardware used can make a big difference. (See The Code below)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Socket latency was 1/50/99%tile 5.6/5.8/7.0 us&lt;br /&gt;Socket Throughput was 170 K/s&lt;br /&gt;Threaded Socket Latency for 1/50/99%tile 6.0/8.5/10.7 us&lt;br /&gt;Threaded Socket Throughput was 234 K/s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The first pair of results, test just the Socket. Its single threaded and as you would expect, the throughput is the inverse of the latency. i.e. 170K * 5.8e-6 = 0.986 (about 1 thread busy)  In the threaded test, the latency and throughput are higher. i.e. 234K * 8.5e-6 = 1.989 (about two threads were busy) Put another way, the throughput was double the inverse of the latency.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Can throughput be increased&lt;/h2&gt;Throughput can be increased further by batching and using multiple connections. This will increase/worsen latency but can give a significant increase in throughput. Between 2x to 10x can be expected with one server. Additional servers have the potential to increase throughput to the limits of your budget. ;)&lt;br /&gt;&lt;br /&gt;However, once you have a real application on a real network, you will be lucky to achieve this throughput numbers on one server even with batching and multiple connections.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Follow on Article&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/send-xml-over-socket-fast.html"&gt;Send XML over a Socket fast&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/socket/PingTest.java"&gt;&lt;b&gt;PingTest.java&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related articles&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/send-xml-over-socket-fast.html"&gt;Send XML over a Socket fast&lt;/a&gt;&lt;p/&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/how-fast-are-java-datagrams.html"&gt;How fast are Java Datagrams?&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4270608064388563118?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4270608064388563118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/how-fast-are-java-sockets.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4270608064388563118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4270608064388563118'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/how-fast-are-java-sockets.html' title='How fast are Java sockets'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-8641026958042612018</id><published>2011-07-24T13:24:00.006+01:00</published><updated>2012-01-22T19:34:51.588Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Java: How much memory do different arrays consume</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Arrays can be large and consume a significant amount of memory. It can me worth choosing the most memory efficient array/collection.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Comparing array sizes&lt;/h2&gt;How much space does a `new int[1024]` take compared with an `new Integer[1024]`?&lt;br /&gt;&lt;pre&gt;int[] ints = new int[1024];&lt;br /&gt;for (int i = 0; i &lt; ints.length; i++) ints[i] = i;&lt;br /&gt;&lt;/pre&gt;compared with&lt;pre&gt;Integer[] ints = new Integer[1024];&lt;br /&gt;for (int i = 0; i &lt; ints.length; i++) ints[i] = i;&lt;br /&gt;&lt;/pre&gt;Note: 1/8th of Integer values will come from the auto-box cache and not use additional memory. All possible Boolean and Byte values are cached.&lt;table&gt;&lt;tr&gt;&lt;th&gt;array&lt;/th&gt;&lt;th&gt;size in bytes&lt;br /&gt;32-bit JVM&lt;/th&gt;&lt;th&gt;size in bytes&lt;br /&gt;64-bit JVM&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new BitSet(1024)&lt;/td&gt;&lt;td&gt;168&lt;/td&gt;&lt;td&gt;168&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new boolean[1024]&lt;/td&gt;&lt;td&gt;1040&lt;/td&gt;&lt;td&gt;1040&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Boolean[1024]&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new ArrayList&amp;lt;Boolean&gt;(1024)&lt;/td&gt;&lt;td&gt;4136&lt;/td&gt;&lt;td&gt;4136&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new LinkedList&amp;lt;Boolean&gt;() with 1024&lt;/td&gt;&lt;td&gt;24624&lt;/td&gt;&lt;td&gt;24624&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new byte[1024]&lt;/td&gt;&lt;td&gt;1040&lt;/td&gt;&lt;td&gt;1040&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Byte[1024]&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new ArrayList&amp;lt;Byte&gt;(1024)&lt;/td&gt;&lt;td&gt;4136&lt;/td&gt;&lt;td&gt;4136&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new LinkedList&amp;lt;Byte&gt;() with 1024&lt;/td&gt;&lt;td&gt;24624&lt;/td&gt;&lt;td&gt;24624&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new char[1024]&lt;/td&gt;&lt;td&gt;2064&lt;/td&gt;&lt;td&gt;2064&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Character[1024]&lt;/td&gt;&lt;td&gt;18448&lt;/td&gt;&lt;td&gt;18448&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new short[1024]&lt;/td&gt;&lt;td&gt;2064&lt;/td&gt;&lt;td&gt;2064&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Short[1024]&lt;/td&gt;&lt;td&gt;18448&lt;/td&gt;&lt;td&gt;18448&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new ArrayList&amp;lt;Character/Short&gt;(1024)&lt;/td&gt;&lt;td&gt;18472&lt;/td&gt;&lt;td&gt;18472&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new LinkedList&amp;lt;Character/Short&gt;() with 1024&lt;/td&gt;&lt;td&gt;38960&lt;/td&gt;&lt;td&gt;38960&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new int[1024]&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Integer[1024]&lt;/td&gt;&lt;td&gt;18448&lt;/td&gt;&lt;td&gt;18448&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new float[1024]&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;td&gt;4112&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Float[1024]&lt;/td&gt;&lt;td&gt;20496&lt;/td&gt;&lt;td&gt;20496&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new ArrayList&amp;lt;Integer/Float&gt;(1024)&lt;/td&gt;&lt;td&gt;18472&lt;/td&gt;&lt;td&gt;18472&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new LinkedList&amp;lt;Integer/Float&gt;() with 1024&lt;/td&gt;&lt;td&gt;38960&lt;/td&gt;&lt;td&gt;38960&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new long[1024]&lt;/td&gt;&lt;td&gt;8208&lt;/td&gt;&lt;td&gt;8208&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Long[1024]&lt;/td&gt;&lt;td&gt;18448&lt;/td&gt;&lt;td&gt;25616&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new double[1024]&lt;/td&gt;&lt;td&gt;8208&lt;/td&gt;&lt;td&gt;8208&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new Double[1024]&lt;/td&gt;&lt;td&gt;20496&lt;/td&gt;&lt;td&gt;28688&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new ArrayList&amp;lt;Long/Double&gt;(1024)&lt;/td&gt;&lt;td&gt;18472&lt;/td&gt;&lt;td&gt;25640&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new LinkedList&amp;lt;Long/Double&gt;() with 1024&lt;/td&gt;&lt;td&gt;38960&lt;/td&gt;&lt;td&gt;46128&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new String[1024]&lt;/td&gt;&lt;td&gt;52464&lt;/td&gt;&lt;td&gt;61456&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new ArrayList&amp;lt;String&gt;(1024)&lt;/td&gt;&lt;td&gt;52488&lt;/td&gt;&lt;td&gt;61480&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;new LinkedList&amp;lt;String&gt;() with 1024&lt;/td&gt;&lt;td&gt;72976&lt;/td&gt;&lt;td&gt;81968&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;In both cases, Java 6 update 26 was used.  For the 64-bit JVM of this version, &lt;i&gt;-XX:+UseCompressedOops&lt;/i&gt; is the default option which uses 32-bit references.  If you use more than 32 GB of memory, you would need to turn this option off, using more memory for the arrays of objects.&lt;h2&gt;The full code&lt;/h2&gt;Is available here: &lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/sizeof/MemoryUsageExamplesTest.java"&gt;MemoryUsageExamplesTest&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-8641026958042612018?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/8641026958042612018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-how-much-memory-do-different.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8641026958042612018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/8641026958042612018'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-how-much-memory-do-different.html' title='Java: How much memory do different arrays consume'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5740624928755257257</id><published>2011-07-22T23:25:00.002+01:00</published><updated>2012-01-22T19:34:51.549Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Java and Memory Leaks</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The term "memory leak" is used in Java in a manner which is different to how it is used in other languages.  What does a "memory leak" mean in general terminology and how is it used in Java?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Wikipedia definition&lt;/h2&gt;&lt;blockquote&gt;A memory leak, in computer science (or leakage, in this context), occurs when a computer program consumes memory but is unable to release it back to the operating system.&lt;/blockquote&gt;The JVM reserves the heap as virtual memory on startup and doesn't gives that memory back until it exits. This virtual memory turns into main memory as it is used.  This is why the virtual size and the resident size for a JVM can be very different and the resident memory can grow without the virtual memory changing. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;In object-oriented programming, a memory leak happens when an object is stored in memory but cannot be accessed by the running code.&lt;/blockquote&gt;&lt;br /&gt;The GC can always find every object on the heap, even those which are not reachable to the application. As such there is no object which is not reachable to running code.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;however, many people refer to any unwanted increase in memory usage as a memory leak, though this is not strictly accurate from a technical perspective.&lt;/blockquote&gt;&lt;br /&gt;In Java, the amount of memory required cannot be determined without a full GC. It is normal to see the "used" memory of a Java application sawtooth. Returning to the same amount of memory used after each GC indicates the memory required has not increased.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;A memory leak can diminish the performance of the computer by reducing the amount of available memory. Eventually, in the worst case, too much of the available memory may become allocated and all or part of the system or device stops working correctly, the application fails, or the system slows down unacceptably due to thrashing.&lt;/blockquote&gt;&lt;br /&gt;This is how the term is used in Java.  There is a reduction in available memory, conclusion: it is a memory leak.&lt;br /&gt;&lt;br /&gt;But is it really a memory leak?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Examples of "memory leaks" in Java&lt;/h2&gt;Recently, two questions were asked on StackOverflow which illustrate a variety of views over what a "memory leak" means in Java.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/4400311/is-go-subject-to-the-same-subtle-memory-leaks-that-java-is"&gt;Is Go subject to the same subtle memory-leaks that Java is?&lt;/a&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java/6470695"&gt;Creating a memory leak in Java&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the first article there was a view expressed that a "memory leak" is when an application holds references to objects which are no longer needed. Another view was that the JVM itself doesn't have memory leaks.&lt;br /&gt;&lt;br /&gt;In the second article there were many examples of how the JVM could be used to hide away memory usage or operations which would consume memory.  Examples included File.deleteOnExit(), creating large static fields, discarded sockets, file handles, threads, JDBC connection which you don't need.&lt;br /&gt;&lt;br /&gt;The File.deleteOnExit on exit must use some memory to be able to perform its task.  This is not a leak in my option as it is not retaining memory which is not needed.&lt;br /&gt;&lt;br /&gt;Having static fields and threads which you don't need will waste memory and this is bug which the JVM cannot correct for.&lt;br /&gt;&lt;br /&gt;However, creating sockets, file handles, and JDBC connections the JVM does handle. When the finalize() method is called, these resources are cleaned up.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Diagnosing excess memory consumption&lt;/h2&gt;If you have a system which is getting an OutOfMemoryError, you can add &lt;i&gt;-XX:+HeapDumpOnOutOfMemoryError&lt;/i&gt; to generate a heap dump you can analyse with a free profiler like VisualVM, jhat or a commercial profiler like YourKit.&lt;br /&gt;&lt;br /&gt;If you want to analyse a running system, you can use &lt;i&gt;jmap&lt;/i&gt; which can give you a break down of the biggest consuming classes or a full heap dump.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;In Java it is meaningful to refer to objects which are retained and are not longer needed as a "memory leak".  &lt;br /&gt;&lt;br /&gt;There is nothing in the Java language which is prone to this problem and the JRE libraries do protect themselves from bugs in application code.  &lt;br /&gt;&lt;br /&gt;Your application can still have a memory leak, and you need to make sensible choices about when you still need a resource, in particular a thread and if you hold onto it too long it can mean you have a "memory leak".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5740624928755257257?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5740624928755257257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-and-memory-leaks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5740624928755257257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5740624928755257257'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-and-memory-leaks.html' title='Java and Memory Leaks'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-437741883410302157</id><published>2011-07-18T13:54:00.003+01:00</published><updated>2012-01-22T19:34:51.523Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Java: What is the limit to the number of threads you can create?</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;I have seen a number of tests where a JVM has 10K threads.  However, what happens if you go beyond this?&lt;br /&gt;&lt;br /&gt;My recommendation is to consider having more servers once your total reaches 10K.  You can get a decent server for $2K and a powerful one for $10K.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Creating threads gets slower&lt;/h2&gt;The time it takes to create a thread increases as you create more thread. For the 32-bit JVM, the stack size appears to limit the number of threads you can create. This may be due to the limited address space. In any case, the memory used by each thread's stack add up. If you have a stack of 128KB and you have 20K threads it will use 2.5 GB of virtual memory. &lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Bitness&lt;/th&gt;&lt;th&gt;Stack Size&lt;/th&gt;&lt;th&gt;Max threads&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;&amp;nbsp;64K&lt;/td&gt;&lt;td&gt;32,073&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;128K&lt;/td&gt;&lt;td&gt;20,549&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;256K&lt;/td&gt;&lt;td&gt;11,216&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;64-bit&lt;/td&gt;&lt;td&gt;&amp;nbsp;64K&lt;/td&gt;&lt;td&gt;stack too small&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;64-bit&lt;/td&gt;&lt;td&gt;128K&lt;/td&gt;&lt;td&gt;32,072&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;64-bit&lt;/td&gt;&lt;td&gt;512K&lt;/td&gt;&lt;td&gt;32,072&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;Note: in the last case, the thread stacks total 16 GB of virtual memory.&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Java 6 update 26 32-bit,-XX:ThreadStackSize=64&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;4,000 threads: Time to create 4,000 threads was 0.522 seconds &lt;br /&gt;8,000 threads: Time to create 4,000 threads was 1.281 seconds &lt;br /&gt;12,000 threads: Time to create 4,000 threads was 1.874 seconds &lt;br /&gt;16,000 threads: Time to create 4,000 threads was 2.725 seconds &lt;br /&gt;20,000 threads: Time to create 4,000 threads was 3.333 seconds &lt;br /&gt;24,000 threads: Time to create 4,000 threads was 4.151 seconds &lt;br /&gt;28,000 threads: Time to create 4,000 threads was 5.293 seconds &lt;br /&gt;32,000 threads: Time to create 4,000 threads was 6.636 seconds &lt;br /&gt;After creating 32,073 threads, java.lang.OutOfMemoryError: unable to create new native thread&lt;br /&gt; at java.lang.Thread.start0(Native Method)&lt;br /&gt; at java.lang.Thread.start(Thread.java:640)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.addThread(MaxThreadsMain.java:46)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.main(MaxThreadsMain.java:16)&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Java 6 update 26 32-bit,-XX:ThreadStackSize=128&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;4,000 threads: Time to create 4,000 threads was 0.525 seconds &lt;br /&gt;8,000 threads: Time to create 4,000 threads was 1.239 seconds &lt;br /&gt;12,000 threads: Time to create 4,000 threads was 1.902 seconds &lt;br /&gt;16,000 threads: Time to create 4,000 threads was 2.529 seconds &lt;br /&gt;20,000 threads: Time to create 4,000 threads was 3.165 seconds &lt;br /&gt;After creating 20,549 threads, java.lang.OutOfMemoryError: unable to create new native thread&lt;br /&gt; at java.lang.Thread.start0(Native Method)&lt;br /&gt; at java.lang.Thread.start(Thread.java:640)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.addThread(MaxThreadsMain.java:46)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.main(MaxThreadsMain.java:16)&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Java 6 update 26 32-bit,-XX:ThreadStackSize=128&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;4,000 threads: Time to create 4,000 threads was 0.526 seconds &lt;br /&gt;8,000 threads: Time to create 4,000 threads was 1.212 seconds &lt;br /&gt;After creating 11,216 threads, java.lang.OutOfMemoryError: unable to create new native thread&lt;br /&gt; at java.lang.Thread.start0(Native Method)&lt;br /&gt; at java.lang.Thread.start(Thread.java:640)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.addThread(MaxThreadsMain.java:46)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.main(MaxThreadsMain.java:16)&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Java 6 update 26 64-bit,-XX:ThreadStackSize=128&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;4,000 threads: Time to create 4,000 threads was 0.577 seconds &lt;br /&gt;8,000 threads: Time to create 4,000 threads was 1.292 seconds &lt;br /&gt;12,000 threads: Time to create 4,000 threads was 1.995 seconds &lt;br /&gt;16,000 threads: Time to create 4,000 threads was 2.653 seconds &lt;br /&gt;20,000 threads: Time to create 4,000 threads was 3.456 seconds &lt;br /&gt;24,000 threads: Time to create 4,000 threads was 4.663 seconds &lt;br /&gt;28,000 threads: Time to create 4,000 threads was 5.818 seconds &lt;br /&gt;32,000 threads: Time to create 4,000 threads was 6.792 seconds &lt;br /&gt;After creating 32,072 threads, java.lang.OutOfMemoryError: unable to create new native thread&lt;br /&gt; at java.lang.Thread.start0(Native Method)&lt;br /&gt; at java.lang.Thread.start(Thread.java:640)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.addThread(MaxThreadsMain.java:46)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.main(MaxThreadsMain.java:16)&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Java 6 update 26 64-bit,-XX:ThreadStackSize=512&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;4,000 threads: Time to create 4,000 threads was 0.577 seconds &lt;br /&gt;8,000 threads: Time to create 4,000 threads was 1.292 seconds &lt;br /&gt;12,000 threads: Time to create 4,000 threads was 1.995 seconds &lt;br /&gt;16,000 threads: Time to create 4,000 threads was 2.653 seconds &lt;br /&gt;20,000 threads: Time to create 4,000 threads was 3.456 seconds &lt;br /&gt;24,000 threads: Time to create 4,000 threads was 4.663 seconds &lt;br /&gt;28,000 threads: Time to create 4,000 threads was 5.818 seconds &lt;br /&gt;32,000 threads: Time to create 4,000 threads was 6.792 seconds &lt;br /&gt;After creating 32,072 threads, java.lang.OutOfMemoryError: unable to create new native thread&lt;br /&gt; at java.lang.Thread.start0(Native Method)&lt;br /&gt; at java.lang.Thread.start(Thread.java:640)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.addThread(MaxThreadsMain.java:46)&lt;br /&gt; at com.google.code.java.core.threads.MaxThreadsMain.main(MaxThreadsMain.java:16)&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;&lt;br /&gt;&lt;h2&gt;The Code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/threads/MaxThreadsMain.java"&gt;MaxThreadsMain.java&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-437741883410302157?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/437741883410302157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-what-is-limit-to-number-of-threads.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/437741883410302157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/437741883410302157'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-what-is-limit-to-number-of-threads.html' title='Java: What is the limit to the number of threads you can create?'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5269513602482054276</id><published>2011-07-16T17:18:00.004+01:00</published><updated>2012-01-22T19:34:51.538Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Java: Getting the size of an Object</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;Java was designed with the principle that you shouldn't need to know the size of an object. There are times when you really would like to know and want to avoid the guess work.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Measuring how much memory an object uses&lt;/h2&gt;There are three factors which make measuring how much an object uses difficult.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The TLAB allocates blocks of memory to a thread.&amp;nbsp; This means small amount of memory don't appear to reduce the free memory. If you do this repeatedly, you will see a block of free memory be used. The way around this is to turn off the TLAB. &lt;i&gt;-XX:-UseTLAB&lt;/i&gt; &lt;/li&gt;&lt;li&gt;A GC can occur while you are creating your object. This will result in more free memory at the end than when you started. I ignore any negative sizes in this test ;)&lt;/li&gt;&lt;li&gt;Other threads in the system could use memory at the same time. I perform multiple test and take the median, which removes any outliers. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;Size of objects in a 32-bit JVM&lt;/h2&gt;&lt;br /&gt;Running this &lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/sizeof/SizeofUtilTest.java"&gt;SizeofTest&lt;/a&gt;, with on 32-bit Sun/Oracle Java 6 update 26, &lt;i&gt;-XX:-UseTLAB&lt;/i&gt; I get&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;The average size of an int is 4.0 bytes&lt;br /&gt;The average size of an Object is 8.0 bytes&lt;br /&gt;The average size of an Integer is 16.0 bytes&lt;br /&gt;The average size of a Long is 16.0 bytes&lt;br /&gt;The average size of an AtomicReference is 16.0 bytes&lt;br /&gt;The average size of an SimpleEntry(Map.Entry) is 16.0 bytes&lt;br /&gt;The average size of a DateTime is 24.0 bytes&lt;br /&gt;The average size of a Calendar is 424.0 bytes&lt;br /&gt;The average size of an Exception is 400.0 bytes&lt;br /&gt;The average size of a bit in a BitSet is 0.125 bytes&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Looking a the size of Long confirms the size of header/Object being 8 bytes.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Size of objects with 32-bit references&lt;/h2&gt;Running this &lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/sizeof/SizeofUtilTest.java"&gt;SizeofTest&lt;/a&gt;, with 32-bit references On Sun/Oracle Java 6 update 26, &lt;i&gt;-XX:+UseCompressedOops -XX:-UseTLAB&lt;/i&gt; I get&lt;br /&gt;&lt;pre&gt;The average size of an int is 4.0 bytes&lt;br /&gt;The average size of an Object is 16.0 bytes&lt;br /&gt;The average size of an Integer is 16.0 bytes&lt;br /&gt;The average size of a Long is 24.0 bytes&lt;br /&gt;The average size of an AtomicReference is 16.0 bytes&lt;br /&gt;The average size of an SimpleEntry(Map.Entry) is 24.0 bytes&lt;br /&gt;The average size of a DateTime is 24.0 bytes&lt;br /&gt;The average size of a Calendar is 448.0 bytes&lt;br /&gt;The average size of an Exception is 440.0 bytes&lt;br /&gt;The average size of a bit in a BitSet is 0.125 bytes&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Objects are 8-byte aligned on this JVM, and you could conclude from the size of an Integer that the header is 12-bytes in size.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Size of objects with 64-bit references&lt;/h2&gt;Running the same test with 64-bit references. i.e. &lt;i&gt;-XX:-UseCompressedOops -XX:-UseTLAB&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;The average size of an int is 4.0 bytes&lt;br /&gt;The average size of an Object is 16.0 bytes&lt;br /&gt;The average size of an Integer is 24.0 bytes&lt;br /&gt;The average size of a Long is 24.0 bytes&lt;br /&gt;The average size of an AtomicReference is 24.0 bytes&lt;br /&gt;The average size of an SimpleEntry(Map.Entry) is 32.0 bytes&lt;br /&gt;The average size of a DateTime is 32.0 bytes&lt;br /&gt;The average size of a Calendar is 544.0 bytes&lt;br /&gt;The average size of an Exception is 648.0 bytes&lt;br /&gt;The average size of a bit in a BitSet is 0.125 bytes&lt;br /&gt;&lt;/pre&gt;From looking at the size of a Long, confirms the size of the header/Object is 16 bytes in length.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The code for the SizeofUtil&lt;/h2&gt;The code for the &lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/main/java/com/google/code/java/core/sizeof/SizeofUtil.java"&gt;SizeofUtil is here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5269513602482054276?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5269513602482054276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-getting-size-of-object.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5269513602482054276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5269513602482054276'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-getting-size-of-object.html' title='Java: Getting the size of an Object'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3607668804403879285</id><published>2011-07-15T07:13:00.000+01:00</published><updated>2012-01-26T15:17:51.396Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>30,000 hits last month.</title><content type='html'>I keep expecting interest to wane, but it is still growing.&lt;br /&gt;&lt;br /&gt;I have lots more ideas for articles on back to basics Java. :)&lt;br /&gt;&lt;br /&gt;BTW; I apologise for my English. If you see any typos or bad grammar don't be afraid to tell me. &lt;br /&gt;&lt;br /&gt;If you have any suggestions for articles you would like to see or you have seen an article you think I should review, let me know.&lt;br /&gt;&lt;br /&gt;peter.lawrey (a) gmail.com&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3607668804403879285?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3607668804403879285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/30000-hits-last-month.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3607668804403879285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3607668804403879285'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/30000-hits-last-month.html' title='30,000 hits last month.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-7998319794590284453</id><published>2011-07-14T16:01:00.011+01:00</published><updated>2012-01-22T19:31:40.817Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Puzzles'/><title type='text'>Incorrect Core Java Interview Answers</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;On the Internet, Java interview questions and answers get copied from one web site to another.  This can mean that an incorrect or out of date answer might never be corrected.  Here are some questions and answer which are not quite correct or are now out of date. i.e. are pre Java 5.0.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How many ways can an argument be passed to a subroutine and explain them?&lt;/h3&gt;&lt;blockquote&gt;An argument can be passed in two ways. They are passing by value and passing by reference. Passing by value: This method copies the value of an argument into the formal parameter of the subroutine. Passing by reference: In this method, a reference to an argument (not the value of the argument) is passed to the parameter.&lt;/blockquote&gt;Java only supports Pass-By-Value.  You can pass a reference by value, but you cannot pass by reference in Java.  Java references can be described as &lt;a href="http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing"&gt;Call By Sharing&lt;/a&gt; but this is not commonly used.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What is Garbage Collection and how to call it explicitly?&lt;/h3&gt;&lt;blockquote&gt;When an object is no longer referred to by any variable, java automatically reclaims memory used by that object. This is known as garbage collection. System. gc() method may be used to call it explicitly.&lt;/blockquote&gt;An object is eligible for cleanup when it no longer has a &lt;b&gt;strong &lt;/b&gt;reference from a Root context.  An object which has a weak or soft reference can be cleaned up. An object without a strong reference might not be cleaned up (i.e. there is no guarentee a GC will be run and a minor GC will not clean up tenured objects)&lt;br /&gt;&lt;br /&gt;System.gc() is a &lt;b&gt;hint&lt;/b&gt; that a Full GC should be run.  This can be disabled using a command line option.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What are Transient and Volatile Modifiers?&lt;/h3&gt;&lt;blockquote&gt;Transient: The transient modifier applies to variables only and it is not stored as part of its object’s Persistent state. Transient variables are not serialized. Volatile: Volatile modifier applies to variables only and it tells the compiler that the variable modified by volatile can be changed unexpectedly by other parts of the program.&lt;/blockquote&gt;&lt;i&gt;transient &lt;/i&gt;can only be applied to &lt;b&gt;fields &lt;/b&gt;and cannot be applied to local variables. It can be applied to static variables but will be generally ignored. Transient fields are not serialized automatically, but can be serialized by custom serialization e.g. &lt;a href="http://java.sun.com/developer/technicalArticles/ALT/serialization/"&gt;writeObject and readObject()&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;volatile &lt;/i&gt;can only be applied to &lt;b&gt;fields&lt;/b&gt; and the tell the JIT rather than the compiler that every access must get a cache coherent copy of the field. (Notionally from "main" memory)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Explain the usage of the keyword transient?&lt;/h3&gt;&lt;blockquote&gt;This keyword indicates that the value of this member variable does not have to be serialized with the object. When the class will be de-serialized, this variable will be initialized with a default value of its data type (i.e. zero for integers).&lt;/blockquote&gt;This keyword means the field &lt;b&gt;cannot&lt;/b&gt; be serialized automatically.  It is not de-serialized automatically leaving the default value for the field.  The default for &lt;i&gt;Integer&lt;/i&gt; is &lt;i&gt;null&lt;/i&gt;. The default for &lt;i&gt;int&lt;/i&gt; is &lt;i&gt;0&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What is method overloading and method overriding?&lt;/h3&gt;&lt;blockquote&gt;Method overloading: When a method in a class having the same method name with different arguments is said to be method overloading. Method overriding : When a method in a class having the same method name with same arguments is said to be method overriding.&lt;/blockquote&gt;Method overloading occurs when two methods have the same name but different &lt;b&gt;signatures&lt;/b&gt;. The signature includes the parameter types and generic type.  A single method can be called with different arguments and two overloaded methods can be called with the same arguments. i.e. its the signature not the arguments which matter.&lt;br /&gt;&lt;br /&gt;Method overriding only occurs when a sub-class has the same signature as a method in a parent class. &lt;br /&gt;&lt;br /&gt;It is worth clarifying that the return type is not part of the signature in Java.  At the JVM level it is and covariant return types are implemented with &lt;a href="http://vanillajava.blogspot.com/2011/07/java-secret-generated-methods.html"&gt;generated method&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What is the difference between Integer and int&lt;/h3&gt;&lt;blockquote&gt;a) Integer is a class defined in the java. lang package, whereas int is a primitive data type defined in the Java language itself. Java does not automatically convert from one to the other. b) Integer can be used as an argument for a method that requires an object, whereas int can be used for calculations.&lt;/blockquote&gt;An &lt;i&gt;Integer&lt;/i&gt; is a reference to an object which wraps an &lt;i&gt;int&lt;/i&gt;  The key difference since autoboxing and unboxing was added is that an &lt;i&gt;Integer &lt;/i&gt;can be &lt;i&gt;null&lt;/i&gt; and the &lt;i&gt;==&lt;/i&gt; operator compares references for Integer and the actual values for an &lt;i&gt;int&lt;/i&gt; type.&lt;br /&gt;&lt;pre&gt;Integer i1 = 1;&lt;br /&gt;Integer i2 = 1;&lt;br /&gt;// true as the same autoboxed Integer is used.&lt;br /&gt;System.out.println(i1 == i2); &lt;br /&gt;&lt;br /&gt;Integer i3 = -200;&lt;br /&gt;Integer i4 = -200;&lt;br /&gt;// false as different autoboxed Integer objects are used.&lt;br /&gt;System.out.println(i3 == i4);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;i3 == i4 is false as new Integer(int) is called by Integer.valueOf(int) which does the autoboxing.&lt;br /&gt;&lt;br /&gt;Note: On the Sun/Oracle JVM the maximum value of integer cached defaults to 127, however it can be increased with the &lt;i&gt;-XX:AutoBoxCacheMax=&lt;/i&gt; or &lt;i&gt;-Djava.lang.Integer.IntegerCache.high=&lt;/i&gt; options.  Thank you @Pedro Kowalski.&lt;br /&gt;&lt;h3&gt;What are the different states of a thread ?&lt;/h3&gt;&lt;blockquote&gt;The different thread states are ready, running, waiting and dead.&lt;/blockquote&gt;Since Java 5.0, which should be most Java systems under development, the &lt;a href="http://download.oracle.com/javase/6/docs/api/java/lang/Thread.State.html"&gt;Thread.State&lt;/a&gt; class lists the threads possible states as&lt;br /&gt;&lt;blockquote&gt;NEW&lt;br /&gt;A thread that has not yet started is in this state.&lt;br /&gt;&lt;br /&gt;RUNNABLE&lt;br /&gt;A thread executing in the Java virtual machine is in this state.&lt;br /&gt;&lt;br /&gt;BLOCKED&lt;br /&gt;A thread that is blocked waiting for a monitor lock is in this state.&lt;br /&gt;&lt;br /&gt;WAITING&lt;br /&gt;A thread that is waiting indefinitely for another thread to perform a particular action is in this state.&lt;br /&gt;&lt;br /&gt;TIMED_WAITING&lt;br /&gt;A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.&lt;br /&gt;&lt;br /&gt;TERMINATED&lt;br /&gt;A thread that has exited is in this state.&lt;/blockquote&gt;&lt;br /&gt;&lt;h3&gt;Which is the base class for all classes?&lt;/h3&gt;&lt;blockquote&gt;java.lang.Object&lt;/blockquote&gt;This is true for custom classes. For primitive types such as int.class, void.class and Object itself have no super class. &lt;br /&gt;&lt;pre&gt;Class parent = boolean.class.getSuperclass(); // returns null&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;What is daemon thread?&lt;/h3&gt;&lt;br /&gt;&lt;blockquote&gt;Theards [sic] which are running on the background are called deamon threads. daemon thread is a thread which doesn't give any chance to run other threads once it enters into the run state it doesn't give any chance to run other threads.  &lt;/blockquote&gt;A Daemon thread is any thread which will not prevent the JVM from shutting down. Any thread can be considered a "background" thread.  Daemon threads are given the same priority as non-Daemon threads (based on their priority) When a daemon thread is running it doesn't prevent another thread from running any differently from a non-daemon thread running.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Daemon thread is a low priority thread which runs intermittently in the back ground doing the garbage collection operation for the java runtime system.&lt;/blockquote&gt;&lt;br /&gt;The garbage collector is an example of a daemon thread. A daemon thread can have a high priority and it can run all the time.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What are the restrictions placed on the values of each case of a switch statement?&lt;/h3&gt;&lt;blockquote&gt;At compile time, each case values of switch statement must evaluate to a an int value&lt;/blockquote&gt;From Java 5.0, switching on an enum is supported and from Java 7, switching on a String is supported.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What is a Java Bean?&lt;/h3&gt;&lt;blockquote&gt;A Java Bean is a software component that has been designed to be reusable in a variety of different environments.&lt;/blockquote&gt;IMHO: This answer is vague and could be talking about anything.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://en.wikipedia.org/wiki/JavaBean"&gt;Java Bean&lt;/a&gt; is a "Java Object that is serializable, has a nullary constructor, and allows access to properties using getter and setter methods."&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why would you use a synchronized block vs. synchronized method?&lt;/h3&gt;&lt;blockquote&gt;Synchronized blocks place locks for shorter periods than synchronized methods.&lt;/blockquote&gt;This can be true but is not guaranteed. Often synchronized blocks are used to hold a lock over multiple calls to an object with synchronized methods. IMHO the most common use for synchronized blocks is locking on another object other than &lt;i&gt;this&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;Map&amp;lt;Key, Value&amp;gt; map = Collections.synchronizedMap(new LinkedHashMap&amp;lt;Key, Value&amp;gt;());&lt;br /&gt;// perform multiple operations in a thread safe manner&lt;br /&gt;synchronized(map) {&lt;br /&gt;    Value value = map.get(key);&lt;br /&gt;    if (value == null)&lt;br /&gt;        map.put(key, value = new Value(key));&lt;br /&gt;    return value;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Which one is faster in Java ?&lt;/h3&gt;&lt;blockquote&gt;for(int i = 100000; i &amp;gt; 0; i--) {}&lt;/blockquote&gt;&lt;blockquote&gt;for(int i = 1; i &amp;lt; 100001; i++) {}&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Answer: Which ever is run second with be fastest.  The server JVM can detect and eliminate loops which don't do anything.  A method with either loop is compiled when the loop iterates about 10,000 times. (Based on -XX:CompileThreshold=10000) The first loop will take time to detect it doesn't do anything, however the second will have been compiled.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Which Java operator is right associative?&lt;/h3&gt;&lt;blockquote&gt;The = operator is right associative. &lt;/blockquote&gt;According to &lt;a href="http://introcs.cs.princeton.edu/java/11precedence/"&gt;http://introcs.cs.princeton.edu/java/11precedence/&lt;/a&gt; the list of right to left associative operators are. (A lot more than one)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;( ) cast&lt;/li&gt;&lt;li&gt;new Object&lt;/li&gt;&lt;li&gt;? :&lt;/li&gt;&lt;li&gt;assignment&amp;nbsp;&amp;nbsp; =&amp;nbsp;&amp;nbsp; +=&amp;nbsp;&amp;nbsp; -=&amp;nbsp; *=&amp;nbsp;&amp;nbsp; /=&amp;nbsp;&amp;nbsp; %=&amp;nbsp;&amp;nbsp; &amp;amp;=&amp;nbsp;&amp;nbsp; ^=&amp;nbsp;&amp;nbsp; |= &amp;lt;&amp;lt;=&amp;nbsp;&amp;nbsp; &amp;gt;&amp;gt;= &amp;nbsp;&amp;nbsp;&amp;gt;&amp;gt;&amp;gt;=&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;What class of exceptions are generated by the Java run-time system?&lt;/h3&gt;&lt;blockquote&gt;The Java runtime system generates RuntimeException and Error exceptions. &lt;/blockquote&gt;IMHO: This an answer to a different question.  This is an answer to; what are the super classes of runtime, unchecked exceptions?&lt;br /&gt;&lt;br /&gt;The Java runtime can generate an Error, Exception or RuntimeException.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Links to this page&lt;/h2&gt;&lt;a href="http://news.ycombinator.com/item?id=2789570"&gt;http://news.ycombinator.com/item?id=2789570&lt;/a&gt;&lt;p/&gt;&lt;a href="http://news.ycombinator.com/item?id=2793399"&gt;http://news.ycombinator.com/item?id=2793399&lt;/a&gt;&lt;p/&gt;&lt;a href="http://www.javacodegeeks.com/2011/07/incorrect-core-java-interview-answers.html"&gt;http://www.javacodegeeks.com/2011/07/incorrect-core-java-interview-answers.html&lt;/a&gt;&lt;p/&gt;&lt;a href="http://java.dzone.com/articles/incorrect-core-java-interview"&gt;http://java.dzone.com/articles/incorrect-core-java-interview&lt;/a&gt;&lt;p/&gt;&lt;a href="http://www.dzone.com/links/15_incorrect_yet_popular_core_java_interview_answ.html?ref=ps"&gt;http://www.dzone.com/links/15_incorrect_yet_popular_core_java_interview_answ.html?ref=ps&lt;/a&gt;&lt;/p&gt;&lt;a href="http://news.ycombinator.com/item?id=2789570"&gt;http://news.ycombinator.com/item?id=2789570&lt;/a&gt;&lt;p/&gt;&lt;a href="http://www.softwareservices.com/news/15833/incorrect-core-java-interview-answers/"&gt;http://www.softwareservices.com/news/15833/incorrect-core-java-interview-answers/&lt;/a&gt;&lt;p/&gt;&lt;a href="http://www.dzone.com/links/rss/incorrect_core_java_interview_answers.html"&gt;http://www.dzone.com/links/rss/incorrect_core_java_interview_answers.html&lt;/a&gt;&lt;p/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-7998319794590284453?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/7998319794590284453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/incorrect-core-java-interview-answers.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7998319794590284453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/7998319794590284453'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/incorrect-core-java-interview-answers.html' title='Incorrect Core Java Interview Answers'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-3151536714322438682</id><published>2011-07-14T13:38:00.000+01:00</published><updated>2012-01-26T15:17:51.391Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>Java Secret: Generated methods</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;The Java compiler generates extra methods which appear in stack traces.  These can be confusing at first. What are they and why do they exist?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The access model in the JVM&lt;/h2&gt;The access model in the JVM has not changed significantly since version 1.0.  However, Java 5.0 added features such as inner/nested classes and convariant return types which were not in the original design.  So how are they supported?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The issue with nested classes&lt;/h3&gt;Nested classes can access private methods and fields of an outer class.  However the JVM does not support this so the compiler generates methods as a workaround.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Private Methods&lt;/h3&gt;&lt;br /&gt;In this example, the inner class calls a private method &lt;i&gt;init()&lt;/i&gt; of the outer class.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public class PrivateMethod { // line 4&lt;br /&gt;    private void init() {&lt;br /&gt;        throw new UnsupportedOperationException(); // line 6&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    class Inner {&lt;br /&gt;        Inner() {&lt;br /&gt;            init();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;     public static void main(String... args) {&lt;br /&gt;        PrivateMethod pm = new PrivateMethod();&lt;br /&gt;        Inner inner = pm.new Inner();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So what does the stack trace look like when we run this?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Exception in thread "main" java.lang.UnsupportedOperationException&lt;br /&gt; at com.google.code.java.core.javac.generated.PrivateMethod.init(PrivateMethod.java:6)&lt;br /&gt; at com.google.code.java.core.javac.generated.PrivateMethod.access$000(PrivateMethod.java:4)&lt;br /&gt; at com.google.code.java.core.javac.generated.PrivateMethod$Inner.&lt;init&gt;(PrivateMethod.java:11)&lt;br /&gt; at com.google.code.java.core.javac.generated.PrivateMethod.main(PrivateMethod.java:17)&lt;br /&gt;&lt;/init&gt;&lt;/pre&gt;&lt;br /&gt;In the stack trace there is a method called &lt;i&gt;access$000&lt;/i&gt; on line 4 which is the first line of the class.  Is this a real method? What do we see in the byte code?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ javap -c -private -classpath . com.google.code.java.core.javac.generated.PrivateMethod&lt;br /&gt;&lt;br /&gt;static void &lt;b&gt;access$000&lt;/b&gt;(com.google.code.java.core.javac.generated.PrivateMethod);&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   invokespecial   #1; //Method init:()V&lt;br /&gt;   4:   return&lt;br /&gt;&lt;br /&gt;$ javap -c -private -classpath . com.google.code.java.core.javac.generated.PrivateMethod\$Inner&lt;br /&gt;Compiled from "PrivateMethod.java"&lt;br /&gt;public class com.google.code.java.core.javac.generated.PrivateMethod$Inner extends java.lang.Object{&lt;br /&gt;final com.google.code.java.core.javac.generated.PrivateMethod this$0;&lt;br /&gt;&lt;br /&gt;com.google.code.java.core.javac.generated.PrivateMethod$Inner(com.google.code.java.core.javac.generated.PrivateMethod);&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   aload_1&lt;br /&gt;   2:   putfield        #1; //Field this$0:Lcom/google/code/java/core/javac/generated/PrivateMethod;&lt;br /&gt;   5:   aload_0&lt;br /&gt;   6:   invokespecial   #2; //Method java/lang/Object."&lt;init&gt;":()V&lt;br /&gt;   9:   aload_1&lt;br /&gt;   10:  invokestatic    #3; //Method com/google/code/java/core/javac/generated/PrivateMethod.&lt;br /&gt;                        &lt;b&gt;access$000&lt;/b&gt;:(Lcom/google/code/java/core/javac/generated/PrivateMeth&lt;br /&gt;   13:  return&lt;br /&gt;&lt;br /&gt;}&lt;/init&gt;&lt;/pre&gt;The compiler has added a static method which is not private so the Inner class can access the private method of the outer class indirectly.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Private Fields&lt;/h3&gt;Private fields are accessed via a getter and setter, but the compiler can generate methods for assignment operations such as&lt;i&gt; ++ &lt;/i&gt;and &lt;i&gt;*=&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;public class PrivateField {&lt;br /&gt;    private int num = 0;&lt;br /&gt;&lt;br /&gt;    public class Inner {&lt;br /&gt;        public void set(int n) {&lt;br /&gt;            num = n;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public int get() {&lt;br /&gt;            return num;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void increment() {&lt;br /&gt;            num++;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void multiply(int n) {&lt;br /&gt;            num *= n;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Compiles with four generated methods, one for each of get, set, ++ and *=&lt;br /&gt;&lt;pre&gt;$ javap -c -private -classpath . com.google.code.java.core.javac.generated.PrivateField&lt;br /&gt;&lt;b&gt;setter&lt;/b&gt;&lt;br /&gt;static int access$002(com.google.code.java.core.javac.generated.PrivateField, int);&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   iload_1&lt;br /&gt;   2:   dup_x1&lt;br /&gt;   3:   putfield        #1; //Field num:I&lt;br /&gt;   6:   ireturn&lt;br /&gt;&lt;br /&gt;&lt;b&gt;getter&lt;/b&gt;&lt;br /&gt;static int access$000(com.google.code.java.core.javac.generated.PrivateField);&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   getfield        #1; //Field num:I&lt;br /&gt;   4:   ireturn&lt;br /&gt;&lt;br /&gt;&lt;b&gt;increment ++&lt;/b&gt;&lt;br /&gt;static int access$008(com.google.code.java.core.javac.generated.PrivateField);&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   dup&lt;br /&gt;   2:   getfield        #1; //Field num:I&lt;br /&gt;   5:   dup_x1&lt;br /&gt;   6:   iconst_1&lt;br /&gt;   7:   iadd&lt;br /&gt;   8:   putfield        #1; //Field num:I&lt;br /&gt;   11:  ireturn&lt;br /&gt;&lt;br /&gt;&lt;b&gt;multiplier *=&lt;/b&gt;&lt;br /&gt;static int access$028(com.google.code.java.core.javac.generated.PrivateField, int);&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   dup&lt;br /&gt;   2:   getfield        #1; //Field num:I&lt;br /&gt;   5:   iload_1&lt;br /&gt;   6:   imul&lt;br /&gt;   7:   dup_x1&lt;br /&gt;   8:   putfield        #1; //Field num:I&lt;br /&gt;   11:  ireturn&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Covariant return types&lt;/h2&gt;Covariant return types is a feature which was added to Java 5.0 but isn't supported in the JVM.  For this reason, the compiler generates a method which overrides all the super methods and their return types.&lt;br /&gt;&lt;pre&gt;public class CovariantReturnTypeA {&lt;br /&gt;    public Object method() { return 1L; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class CovariantReturnTypeB extends CovariantReturnTypeA {&lt;br /&gt;    public Number method() { return 2.0; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class CovariantReturnTypeC extends CovariantReturnTypeB {&lt;br /&gt;    public Integer method() { return 3; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The last method() overrides the method which returns Number and the method which returns Object.  To implement this, the compile generates a method with the same signature which calls the method which returns Integer&lt;br /&gt;&lt;pre&gt;$ javap -c -private -classpath . com.google.code.java.core.javac.generated.CovariantReturnTypeC&lt;br /&gt;&lt;br /&gt;public java.lang.Integer method();&lt;br /&gt;  Code:&lt;br /&gt;   0:   iconst_3&lt;br /&gt;   1:   invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;&lt;br /&gt;   4:   areturn&lt;br /&gt;&lt;br /&gt;public java.lang.Number method();&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   invokevirtual   #3; //Method method:()Ljava/lang/Integer;&lt;br /&gt;   4:   areturn&lt;br /&gt;&lt;br /&gt;public java.lang.Object method();&lt;br /&gt;  Code:&lt;br /&gt;   0:   aload_0&lt;br /&gt;   1:   invokevirtual   #3; //Method method:()Ljava/lang/Integer;&lt;br /&gt;   4:   areturn&lt;br /&gt;&lt;/pre&gt;There are three implementations of method() in the byte code.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Performance implications&lt;/h2&gt;The performance implications for Java Standard Edition are small as these methods can be inlined and effectively have no impact. In Java Mobile Edition, this might not be the case.&lt;br /&gt;&lt;br /&gt;They can cause some confusion and if this is a problem you can make the fields/methods package-local instead and the generated methods will go away.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-3151536714322438682?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/3151536714322438682/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-secret-generated-methods.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3151536714322438682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/3151536714322438682'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-secret-generated-methods.html' title='Java Secret: Generated methods'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1710497809783157814</id><published>2011-07-14T11:09:00.002+01:00</published><updated>2012-01-26T15:22:22.469Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Java low level: Converting between integers and text (part 2)</title><content type='html'>&lt;h2&gt;Parsing an integer from text&lt;/h2&gt;Parsing an integer is relatively simple depending on how many checks you make.  This loop does almost no validation.  The input can multiple '-' signs and the number can overflow. As soon as it reaches a character is does not accept to stops. It is left to the caller to check if this character was a valid separartor.&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;ByteBufferTextLongReader.read()&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;long num = 0;&lt;br /&gt;boolean negative = false;&lt;br /&gt;while (true) {&lt;br /&gt;    byte b = buffer.get();&lt;br /&gt;//  if (b &gt;= '0' &amp;&amp; b &lt;= '9')&lt;br /&gt;    if ((b - ('0' + Integer.MIN_VALUE)) &lt;= 9 + Integer.MIN_VALUE)&lt;br /&gt;        num = num * 10 + b - '0';&lt;br /&gt;    else if (b == '-')&lt;br /&gt;        negative = true;&lt;br /&gt;    else&lt;br /&gt;        break;&lt;br /&gt;}&lt;br /&gt;return negative ? -num : num;&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;Note: The expression &lt;i&gt;(b &gt;= '0' &amp;&amp; b &lt;= '9')&lt;/i&gt; has been re-written taking advantage of an underflow to turn this into one comparison.&lt;h2&gt;To follow...&lt;/h2&gt;Converting floating point numbers to text&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1710497809783157814?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1710497809783157814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-low-level-converting-between_14.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1710497809783157814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1710497809783157814'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-low-level-converting-between_14.html' title='Java low level: Converting between integers and text (part 2)'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4655253057581866467</id><published>2011-07-14T10:32:00.009+01:00</published><updated>2012-01-26T15:20:07.869Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Java low level: Converting between integers and text (part 1)</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;As Java has a number of way to convert an integer to a String, its not something you might have considered writing yourself.&lt;br /&gt;&lt;br /&gt;However, there may be situations where you want to do this.  One of them is when performance is critical.  Java libraries tend to create more objects than are required.  Usually this doesn't matter but there are times when you need the system to go faster and reading and writing numbers is a big hit for you.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Performance difference&lt;/h2&gt;The following is based on a tests of 128K integers in binary and text formats repeatedly to take an average time to write and read an integer.&lt;br /&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/test/java/com/google/code/java/core/parser/InMemoryPerfTest.java"&gt;Source to run all tests&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/main/java/com/google/code/java/core/parser/"&gt;Source for the examples&lt;/a&gt; Scroll down for the Unsafe examples.&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;On a 2.6 GHz Xeon&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;Unsafe text: Typically took 41.4 ns to write/read per long.&lt;br /&gt;ByteBuffer direct text: Typically took 63.9 ns to write/read per long.&lt;br /&gt;ByteBuffer heap text: Typically took 68.9 ns to write/read per long.&lt;br /&gt;Print text: Typically took 325.7 ns to write/read per long.&lt;br /&gt;DecimalFormat text: Typically took 645.5 ns to write/read per long.&lt;br /&gt;&lt;br /&gt;Unsafe binary: Typically took 4.2 ns to write/read per long.&lt;br /&gt;ByteBuffer binary: Typically took 10.3 ns to write/read per long.&lt;br /&gt;DataStream binary: Typically took 72.1 ns to write/read per long.&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;On a 3.8 GHz i7&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;Unsafe text: Typically took 32.1 ns to write/read per long.&lt;br /&gt;ByteBuffer direct text: Typically took 48.4 ns to write/read per long.&lt;br /&gt;ByteBuffer heap text: Typically took 58.4 ns to write/read per long.&lt;br /&gt;Print text: Typically took 205.6 ns to write/read per long.&lt;br /&gt;DecimalFormat text: Typically took 436.8 ns to write/read per long.&lt;br /&gt;&lt;br /&gt;Unsafe binary: Typically took 5.0 ns to write/read per long.&lt;br /&gt;ByteBuffer binary: Typically took 17.4 ns to write/read per long.&lt;br /&gt;DataStream binary: Typically took 50.8 ns to write/read per long.&lt;br /&gt;&lt;/pre&gt;&lt;/legend&gt;&lt;/fieldset&gt;The i7 has a faster clock speed than the Xeon, but a smaller cache. This narrows the gap between the fastest and slowest times. When comparing using a direct ByteBuffer and a heap ByteBuffer, there was little difference on the Xeon, however the direct ByteBuffer was consistently faster on the i7.&lt;br /&gt;&lt;br /&gt;In this test, reading/writing integers as text using different approaches varies by as much as 14x.  If your integer format is needs to be customised you may need to use DecimalFormat, or write your own.&lt;br /&gt;&lt;br /&gt;Note: the faster options for writing/reading text were faster than using the binary DataInput/OutputStream. The stream arranges a &lt;i&gt;long &lt;/i&gt;as 8 bytes in &lt;a href="http://en.wikipedia.org/wiki/Endianness"&gt;big-endian&lt;/a&gt; order which is more work than converting the number to text in these cases.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Writing an integer to text&lt;/h2&gt;For this example, all integers are treated as &lt;i&gt;long&lt;/i&gt; type.  There is a small performance advantage in having an &lt;i&gt;int&lt;/i&gt; type instead but it is relatively small.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Integer representation&lt;/h3&gt;All signed integers, &lt;i&gt;byte&lt;/i&gt;, &lt;i&gt;short&lt;/i&gt;, &lt;i&gt;int &lt;/i&gt;and &lt;i&gt;long&lt;/i&gt; are represented as &lt;a href="http://en.wikipedia.org/wiki/Two%27s_complement"&gt;twos-complement&lt;/a&gt;  Encoding/decoding this format doesn't require any bitwise operations like floating point numbers can to.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Extract the sign&lt;/h3&gt;Firstly extract the sign. This is simple to do,&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Extracting the sign&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;if (num &amp;lt; 0) {&lt;br /&gt;   writeByte('-');&lt;br /&gt;   num = -num;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/fieldset&gt;&lt;br /&gt;There is one edge case here which is Long.MIN_VALUE.  Due to two-complement representation, this value is the negative of itself.  One way to handle this value is to encode it specially. e.g. have a constant which contains what it should be encoded as.  Another approach is to treat Long.MIN_VALUE as an unset value or NaN. Most spreadsheet applications treat an empty field as an unset cell. (This is my preference)  Another special value is zero.  Other numbers do not have a leading zero, but zero needs to have at least one digit.&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Handling 0&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;if (num == 0) {&lt;br /&gt;    writeByte('0');&lt;br /&gt;    writeByte(SEPARATOR);&lt;br /&gt;} else {&lt;br /&gt;&lt;/pre&gt;&lt;/fieldset&gt;&lt;br /&gt;&lt;h3&gt;Writing the digits&lt;/h3&gt;It can be easier to decode a number from the end.  This is the approach I have taken here.&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Writing each digit in reverse&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;// find the number of digits&lt;br /&gt;int digits = ParserUtils.digits(num);&lt;br /&gt;// starting from the end, write each digit&lt;br /&gt;for (int i = digits - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;    // write the lowest digit.&lt;br /&gt;    buffer.put(buffer.position() + i, (byte) (num % 10 + '0'));&lt;br /&gt;    // remove that digit.&lt;br /&gt;    num /= 10;&lt;br /&gt;}&lt;br /&gt;// move the position to after the digits.&lt;br /&gt;buffer.position(buffer.position() + digits);&lt;br /&gt;writeByte(SEPARATOR);&lt;br /&gt;&lt;/pre&gt;&lt;/fieldset&gt;&lt;h2&gt;Part 2&lt;/h2&gt;&lt;a href="http://vanillajava.blogspot.com/2011/07/java-low-level-converting-between_14.html"&gt;Decoding an integer from text&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4655253057581866467?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4655253057581866467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-low-level-converting-between.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4655253057581866467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4655253057581866467'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-low-level-converting-between.html' title='Java low level: Converting between integers and text (part 1)'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6902241595471006967</id><published>2011-07-12T11:22:00.005+01:00</published><updated>2012-01-26T15:15:47.248Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Java: All about 64-bit programming</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;I found this article series very interesting &lt;a href="http://software.intel.com/en-us/blogs/2011/07/07/all-about-64-bit-programming-in-one-place/"&gt;All about 64-bit programming in one place&lt;/a&gt; which collects "a lot of links on the topic of 64-bit C/C++ software development."&lt;br /&gt;&lt;br /&gt;However some of these issues are relevant to Java and can make a difference.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The size_t in C++ is 64-bit&lt;/h2&gt;Java uses the &lt;i&gt;int&lt;/i&gt; type for sizes and this doesn't change in a 64-bit JVM.  This gives backward compatibility but limits arrays, collections and ByteBuffer's to this size.  Generally 2 billion is enough, but as files sizes and memory sizes get larger, the number of situations where it is not will grow over time.&lt;br /&gt;&lt;br /&gt;As of mid 2011, for £1K you can buy a PC with 24 GB of memory and for £21K you can buy a server with 512 GB of memory.&lt;br /&gt;&lt;br /&gt;This is already a problem for memory mapping a file larger than 2 GB.  This can only be done by mapping in a 2 GB window of memory (2^31-1 bytes at a time).  This is rather ugly and removes one of memory mapping's key features; transparency.&lt;br /&gt;&lt;br /&gt;BTW: I have tried using the underlying library directly using reflection which supports `long` lengths and I could get this working for reading files larger than 2 GB, but not writing.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;x64 has more registers than x86&lt;/h2&gt;This is be a small advantage. If you are performing a lot of operations using &lt;i&gt;long&lt;/i&gt; I have seen about 10% performance improvement.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;64-bit JVM can access more memory&lt;/h2&gt;This is essential if you need more than 1.2-3.5 GB of memory (depending on the OS). The downside is 64-bit references can increase memory usage and slow performance.  &lt;br /&gt;&lt;br /&gt;One way to use a 64-bit JVM efficiently is to use the &lt;i&gt;-XX:+UseCompressedOops&lt;/i&gt; which uses 32-bit references in a way which can still access 32 GB of memory. It can do this because every object in the Sun/Oracle JVM is allocated on a 8-byte boundary (i.e. the lower 3 bits of the address are 000) By shifting the bits of the 32-bit reference, it can access 4GB * 8 or 32 GB in total.  It has been suggested that this should be the default for Java 7.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Link:&lt;/b&gt; &lt;a href="http://www.viva64.com/en/l/0001/"&gt;What 64-bit systems are.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Support for 32-bit programs&lt;/h2&gt;Programs written and compiled for a 32-bit JVM will work without re-compilation.  However any native libraries used will not.  A 64-bit JVM can only load 64-bit native libraries.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Switching between int and long&lt;/h2&gt;The &lt;i&gt;int&lt;/i&gt; and &lt;i&gt;long&lt;/i&gt; types work the same on a 32-bit and 64-bit JVM however if you switch code between &lt;i&gt;int&lt;/i&gt; and &lt;i&gt;long&lt;/i&gt; you can get some issues.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Long literals may need an ell&lt;/h3&gt;With all &lt;i&gt;int&lt;/i&gt; literals you can just use the number&lt;br /&gt;&lt;pre&gt;int i = 123456789;&lt;br /&gt;long j = 123456789;&lt;br /&gt;&lt;/pre&gt;However for large numbers an &lt;i&gt;L&lt;/i&gt; is required. &lt;br /&gt;&lt;pre&gt;long i = 111111111111111L; // a long literal.&lt;br /&gt;long j = 111111111111111l; // using `l` is discouraged as it looks like a 1.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you have a calculated values you may need to use &lt;i&gt;L&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;long i = 1 &lt;&lt; 40; // i = 256!&lt;br /&gt;long i = 1L &lt;&lt; 40; // i = 2^40&lt;br /&gt;&lt;/pre&gt;The shift operator only takes the lower 5 bits of the shift for 32-bit numbers, and 6 bits for 64-bit values. So the first line is like&lt;pre&gt;long i = 1 &lt;&lt; (40 % 32);&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Shifting puzzle&lt;/h3&gt;A puzzle for you. ;) What does this do for a 32-bit and 64-bit for &lt;i&gt;x&lt;/i&gt;?&lt;pre&gt;sign = x &gt;&gt; -1;&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;64-bit references and Object size&lt;/h2&gt;When using 64-bit references, the size of a reference doubles. In the Sun/Oracle JVM the header includes a reference. From the &lt;a href="http://www.docjar.com/html/api/java/util/MapEntry.java.html"&gt;Source for Map.Entry&lt;/a&gt;&lt;pre&gt;class MapEntry&lt;K, V&gt; implements Map.Entry&lt;K, V&gt;, Cloneable {&lt;br /&gt;       K key;&lt;br /&gt;       V value;&lt;br /&gt;&lt;/pre&gt;In a 32-bit JVM, the header takes 8 bytes, with each reference, this takes 16 byte total.In a 64-bit JVM with 32-bit references, the header takes 8 + 4 bytes and each reference takes 4 bytes. 8-bytes aligned means it uses (12+4+4 bytes + 4 padding) total: 24 bytes.With 64-bit references, the header uses 16-bytes and each references uses 8 bytes. (16 + 8 + 8) total: 32 bytes.For more details read &lt;a href="http://vanillajava.blogspot.com/2011/07/java-getting-size-of-object.html"&gt;Java: Getting the size of an Object&lt;/a&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;Migrating from 32-bit to a 64-bit in Java is relatively easy compared with C/C++ however there are some issues you may need to consider when migrating.&lt;h2&gt;Links to this page&lt;/h2&gt;&lt;a href="http://java.dzone.com/articles/java-all-about-64-bit"&gt;http://java.dzone.com/articles/java-all-about-64-bit&lt;/a&gt;&lt;p/&gt;&lt;a href="http://www.codeproject.com/News/15990/Java-All-about-64-bit-programming.aspx"&gt;http://www.codeproject.com/News/15990/Java-All-about-64-bit-programming.aspx&lt;/a&gt;&lt;p/&gt;&lt;a href="http://www.javameme.com/javameme-20110714.html&gt;http://www.javameme.com/javameme-20110714.html&lt;/a&gt;&lt;p/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6902241595471006967?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6902241595471006967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-all-about-64-bit-programming.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6902241595471006967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6902241595471006967'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/java-all-about-64-bit-programming.html' title='Java: All about 64-bit programming'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-1432360917198185390</id><published>2011-07-11T10:52:00.004+01:00</published><updated>2012-01-26T15:15:47.228Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opinion'/><title type='text'>Human Readable vs Machine Readable Formats</title><content type='html'>&lt;h1&gt;Overview&lt;/h1&gt;Most file/serialization formats can be broadly broking into two formats, Human Readable Text and Machine Readble Binary. The Human Readable formats have the advantage of being easily understood by a person reading them.  Machine readable formats are easier/faster for a machine to encode/decode.&lt;br /&gt;&lt;br /&gt;There are formats which attempt to be a little of both. XML, JSon, CSV are examples of these. However these do not achieve close to the performance a binary format can achieve.&lt;br /&gt;&lt;p/&gt;&lt;h2&gt;Myth: Machine Readable Binary is always more compact than a Human Readable&lt;/h2&gt;Binary can be more compact, however the obscurity of its format makes it difficult to ensure every byte counts. i.e. its usually hard enough getting something work. Making it compact as well is an added complication.  However with Human Readable formats, determing how the format can be made more compact is more easily understood.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;As text:  38 bytes long, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]&lt;br /&gt;As binary: 290 bytes long, &lt;br /&gt;....sr..java.util.ArrayListx.....a....I..sizexp....w.....sr..java.lang.Long;&lt;br /&gt;.....#....J..valuexr..java.lang.Number...........xp........sq.~..........sq.~&lt;br /&gt;..........sq.~..........sq.~..........sq.~..........sq.~..........sq.~&lt;br /&gt;..........sq.~..........sq.~..........sq.~..........sq.~..........x&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Even though the first format is more compact, you can immedately see you could drop the &lt;i&gt;[ ]&lt;/i&gt; and spaces after the ", " to make it more compact.  With the binary formats, it is hard to know where to start.&lt;br /&gt;&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;ComparingHumanReadableToBinaryMain.java&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;List&lt;long&gt; longs = new ArrayList&lt;long&gt;();&lt;br /&gt;for(long i=-1;i&lt;=10;i++)&lt;br /&gt;    longs.add(i);&lt;br /&gt;String asText = longs.toString();&lt;br /&gt;byte[] bytes1 = asText.getBytes();&lt;br /&gt;System.out.println("As text:  "+ bytes1.length+" bytes long, "+asText);&lt;br /&gt;&lt;br /&gt;ByteArrayOutputStream baos = new ByteArrayOutputStream();&lt;br /&gt;ObjectOutputStream oos = new ObjectOutputStream(baos);&lt;br /&gt;oos.writeObject(longs);&lt;br /&gt;oos.close();&lt;br /&gt;byte[] bytes2 = baos.toByteArray();&lt;br /&gt;System.out.println("As binary: "+bytes2.length+" bytes long, "&lt;br /&gt;    +new String(bytes2, 0).replaceAll("[^\\p{Graph}]", "."));&lt;br /&gt;&lt;/pre&gt;&lt;/fieldset&gt;&lt;p/&gt;&lt;h2&gt;Myth: Machine Readable Binary is always faster than a Human Readable&lt;/h2&gt;Its assumed the cost of parsing data in a human readable format always makes it slower, however machine sreadbale formats have to deal with an issue human readbale formats takes for granted, that is byte endianness.  For human readable formats the order of digits is fairly obvious, however for machine formats the byte endianess of the data might not match that the natrual byte order of the CPU, leading to a source of overhead (as it has to swap the bytes around)One example of this is using big-endian (e.g. TCP/Network byte order) on a little endian machine e.g. Windows/Linux Intel/AMD.  A common class which has this issue is DataInputStream and DataOutputStream which re-arranges the byte order (even if the native byte order matches)For this reason, a fast human readable parse can be as fast or faster.In an earlier article I showed how a Human Readable format could be used to read/write integers 30% faster than using DataInput/DataOuput. &lt;a href="http://vanillajava.blogspot.com/2011/06/writing-human-readable-data-faster-than.html"&gt;Writing human readable data faster than binary.&lt;/a&gt;&lt;p/&gt;&lt;h2&gt;Myth: Using a Human Readable Format makes it easy to read&lt;/h2&gt;Just using a human readable format doesn't mean it will be easier to read than a machine readable format.  Reusing existing tools as much as possible makes human readable format preferrable. However, machine readable formats can come with tools which decode the data and make maintain it easier.  If you have data which can only be managed with the use of specialist tools, being human readable is not much advantage.Images are a good example of where a machine readable format is the best option. It is hard to image editing or viewing an image without the need for a specialist tool.  A practical human readable format would undoubtably lower the quality of the image. ;)&lt;pre&gt;________/.- ,’_______`-. \&lt;br /&gt;_________\ /`__________\’/&lt;br /&gt;_________ /___’a___a`___\&lt;br /&gt;_________|____,’(_)`.____ |&lt;br /&gt;_________\___( ._|_. )___ /&lt;br /&gt;__________\___ .__,’___ /&lt;br /&gt;__________.-`._______,’-.__&lt;br /&gt;________,’__,’___`-’___`.__`.&lt;br /&gt;_______/____/____V_____\___\_&lt;br /&gt;_____,’____/_____o______\___`.__&lt;br /&gt;___,’_____|______o_______|_____`.&lt;br /&gt;__|_____,’|______o_______|`._____|&lt;br /&gt;___`.__,’_.-\_____o______/-._`.__,’&lt;br /&gt;__________/_`.___o____,’__\_&lt;br /&gt;__.””-._,’_____`._:_,’_____`.,-””._&lt;br /&gt;_/_,-._`_______)___(________’_,-.__\&lt;br /&gt;(_(___`._____,’_____`.______,’___)_)&lt;br /&gt;_\_\____\__,’________`.____/.___/_/&lt;br /&gt;&lt;/pre&gt;On the other hand human readable formats can be almost as obscure. This is a piece of code written in a language I am not worthy of mentioning. ;)  Its is descibed as "used to list all of the prime numbers between 1 and R"&lt;pre&gt;(!R)@&amp;{&amp;/x!/:2_!x}'!R&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;If you are designing a file format, start with a human readable one as its much easier to understand.  If this is not compact enough, consider compressing it.  If it is not fast enough concider making it a binary format, but make sure it really is faster to use such a format.  If you are going to use a binary format make sure you have tools in place to supprot viewing (possibly editing) the data (which you would get for free with a text format)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-1432360917198185390?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/1432360917198185390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/human-readable-vs-machine-readble.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1432360917198185390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/1432360917198185390'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/human-readable-vs-machine-readble.html' title='Human Readable vs Machine Readable Formats'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6995148365737631717</id><published>2011-07-08T21:05:00.000+01:00</published><updated>2012-01-26T15:17:51.412Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>20000 hits last month.</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-r60KUhO9_zw/Thdi2QWUQvI/AAAAAAAAADs/rOv46qeC2p0/s1600/20000-pageviews.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-r60KUhO9_zw/Thdi2QWUQvI/AAAAAAAAADs/rOv46qeC2p0/s1600/20000-pageviews.png" /&gt;&lt;/a&gt;&lt;/div&gt;Thank you for all who read my articles. It encourages me to do more. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6995148365737631717?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6995148365737631717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/20000-hits-last-month.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6995148365737631717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6995148365737631717'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/20000-hits-last-month.html' title='20000 hits last month.'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-r60KUhO9_zw/Thdi2QWUQvI/AAAAAAAAADs/rOv46qeC2p0/s72-c/20000-pageviews.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-5620347693218423929</id><published>2011-07-08T19:36:00.008+01:00</published><updated>2012-01-22T19:34:51.545Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Low GC in Java: Using primitives</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;In a recent article I examined how using primitives and collections which support primitives natively instead of Wrappers and standard collections can reduce memory usage and improve performance.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Different way to have a Map of int/Integer&lt;/h2&gt;There are a number of ways you can use int/Integer and a number of collections you store them in.  Depending on which approach you use can have a big difference on the performance and the amount of garbage produced.&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Test&lt;/th&gt;&lt;th&gt;Performance Range&lt;/th&gt;&lt;th&gt;Memory used&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Use Integer wrappers and HashMap&lt;/td&gt;&lt;td&gt;71 - 134 (ns) &lt;/td&gt;&lt;td&gt;53 MB/sec &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Use int primitives and HashMap&lt;/td&gt;&lt;td&gt;45 - 76 (ns)&lt;/td&gt;&lt;td&gt;36 MB/sec &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Use int primitives and FastMap&lt;/td&gt;&lt;td&gt;58 - 93 (ns)&lt;/td&gt;&lt;td&gt;28 MB/sec  &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Use int primitives and TIntIntHashMap&lt;/td&gt;&lt;td&gt;18 - 28 (ns) &lt;/td&gt;&lt;td&gt;nonimal &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Use int primitives and simple hash map&lt;/td&gt;&lt;td&gt;6 - 9 (ns) &lt;/td&gt;&lt;td&gt;nonimal &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;The performance range was the typical (50%tile) and one of the higher (98%tile) timings. The garbage was the result of 900,000 loops per second.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.armandmorin.com/wp-content/uploads/1900-smiley_face.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://www.armandmorin.com/wp-content/uploads/1900-smiley_face.gif" /&gt;&lt;/a&gt;These tests were run on my new system.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Code&lt;/h2&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Loop tested&lt;/b&gt;&lt;/legend&gt;&lt;pre class='brush: java'&gt;int runs = 300 * 300;&lt;br /&gt;for (int i = 0; i &amp;lt; runs; i++) {&lt;br /&gt;    int x = i % 300;&lt;br /&gt;    int y = i / 300;&lt;br /&gt;    int times = x * y;&lt;br /&gt;    Integer count = counters.get(times);&lt;br /&gt;    if (count == null)&lt;br /&gt;        counters.put(times, 1);&lt;br /&gt;    else&lt;br /&gt;        counters.put(times, count + 1);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/fieldset&gt;&lt;h3&gt;Link to all the code is here&lt;/h3&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/main/java/com/google/code/java/core/primitives/"&gt;&lt;b&gt;Directory of performance examples&lt;/b&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-5620347693218423929?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/5620347693218423929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/low-gc-in-java-using-primitives.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5620347693218423929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/5620347693218423929'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/low-gc-in-java-using-primitives.html' title='Low GC in Java: Using primitives'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-4385961391602966064</id><published>2011-07-08T14:45:00.000+01:00</published><updated>2012-01-26T15:17:51.399Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>World's first commercial quantum computer</title><content type='html'>There is news of the &lt;a href="http://venturebeat.com/2011/05/27/first-quantum-computer-sold/"&gt;World's first commercial quantum computer sold to Lockheed Martin&lt;/a&gt; You get a 128 qubit computer for $10 million.  Since this computer works on different paradigms, its likely it will need a new programming language to describe the problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-4385961391602966064?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/4385961391602966064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/worlds-first-commercial-quantum.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4385961391602966064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/4385961391602966064'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/worlds-first-commercial-quantum.html' title='World&apos;s first commercial quantum computer'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6454108009339355582</id><published>2011-07-07T11:17:00.002+01:00</published><updated>2012-01-26T15:17:51.406Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Info'/><title type='text'>New toy for home</title><content type='html'>I have set up a new PC for home. Its got&lt;br /&gt;&lt;ul&gt;&lt;li&gt;An Intel i7 running at 3.8 GHz&lt;/li&gt;&lt;li&gt; 24 GB of 1600 MHz memory.&lt;/li&gt;&lt;li&gt;120 GB SSD drive&lt;/li&gt;&lt;li&gt;Two 20" screens.&lt;/li&gt;&lt;li&gt;Ubuntu 11.04 64-bit. &lt;/li&gt;&lt;/ul&gt;It cost me just over £1K incl tax. &lt;br /&gt;&lt;br /&gt;I will be using this as a based system to benchmark in future articles.&lt;br /&gt;&lt;br /&gt;With lots of memory and a flash disk it does pretty much everything immediately. ;)&lt;br /&gt;&lt;br /&gt;If you want look at a good range of overclocked processors up to 4.8 GHz try &lt;a href="http://3xs.scan.co.uk/Category.asp?SystemMasterCategoryID=38"&gt;Scan's Overclocked Bundles&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6454108009339355582?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6454108009339355582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/new-toy-for-home.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6454108009339355582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6454108009339355582'/><link rel='alternate' type='text/html' href='http://vanillajava.blogspot.com/2011/07/new-toy-for-home.html' title='New toy for home'/><author><name>Peter Lawrey</name><uri>http://www.blogger.com/profile/17982030676088168612</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1729822519392175009.post-6911458158935366498</id><published>2011-07-05T08:35:00.007+01:00</published><updated>2012-01-26T15:22:22.475Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Low GC in Java: Use primitives instead of wrappers</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;There are two good reason to use primitives instead of wrappers where possible.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Clarity. By using a primitive, you are making it clear that a &lt;i&gt;null&lt;/i&gt; value is not appropriate.&lt;/li&gt;&lt;li&gt;Performance. Using primitives is often much faster.&lt;/li&gt;&lt;/ul&gt;Clarity is often more important than performance, and is the best reason to use them.  However, this article discussed the performance implications of using wrappers.&lt;br /&gt;&lt;br /&gt;I have had a lot of interest in this article &lt;a href="http://vanillajava.blogspot.com/2011/06/how-to-avoid-garbage-collection.html"&gt;How to avoid Garbage Collection&lt;/a&gt;, however this was lacking in much practical detail.  This is the first article in a series on ways to reduce demands on the GC.&lt;br /&gt;&lt;br /&gt;A followup article &lt;a href="http://vanillajava.blogspot.com/2011/07/low-gc-in-java-using-primitives.html"&gt;Low GC in Java: Using primitives&lt;/a&gt; looks at using primitives and collections which support them.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Performance of using wrappers&lt;/h2&gt;The following micro-benchmark behaves in a way many application do.   &lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Loop using Wrappers and Wrapper Collection&lt;/b&gt;&lt;/legend&gt;&lt;br /&gt;&lt;pre&gt;Map&amp;lt;Integer, Integer&amp;gt; counters = new HashMap&amp;lt;Integer, Integer&amp;gt;();&lt;br /&gt;int runs = 20 * 1000;&lt;br /&gt;for (Integer i = 0; i &amp;lt; runs; i++) {&lt;br /&gt;    Integer x = i % 12;&lt;br /&gt;    Integer y = i / 12 % 12;&lt;br /&gt;    Integer times = x * y;&lt;br /&gt;    Integer count = counters.get(times);&lt;br /&gt;    if (count == null)&lt;br /&gt;        counters.put(times, 1);&lt;br /&gt;    else&lt;br /&gt;        counters.put(times, count + 1);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/fieldset&gt;This creates objects for each task.  While it is common practice to use &lt;i&gt;int&lt;/i&gt; for loop counters its is also common practice to use &lt;i&gt;Iterator&lt;/i&gt;  You can play around with the types and parameters of this micro-benchmark, however you get a memory profile which will be familiar to many developers who have tried to tune their application.  Using VisualVM the heap usage looks like this over a five minute period. &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-RLfWaJojJMo/ThK7dqHE3iI/AAAAAAAAADU/ZhY_ido-ohE/s1600/wrapper-main-heap.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-RLfWaJojJMo/ThK7dqHE3iI/AAAAAAAAADU/ZhY_ido-ohE/s1600/wrapper-main-heap.png" /&gt;&lt;/a&gt;&lt;/div&gt;There was 20 minor GCs in about 6 minutes.&lt;br /&gt;The average time of each loop is sub-microsecond which is pretty fast.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Took 4,099 ns per loop&lt;br /&gt;Took 559 ns per loop&lt;br /&gt;Took 115 ns per loop&lt;br /&gt;Took 240 ns per loop&lt;br /&gt;Took 255 ns per loop&lt;br /&gt;&lt;/pre&gt;In the first test, the JVM hasn't warmed up.&lt;br /&gt;&lt;br /&gt;Can using primitives really make much difference?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Performance of using primitives&lt;/h2&gt;The following benchmark behaves rather differently to most applications. Even though it is doing the same work as the previous benchmark, there is no objects created.&lt;br /&gt;&lt;fieldset style="border-color: #3322FF; border-style: dashed; font-size: 14px;"&gt;&lt;legend&gt;&lt;b&gt;Loop using Primitives and array&lt;/b&gt;&lt;/legend&gt;&lt;br /&gt;&lt;pre&gt;int[] counters = new int[144];&lt;br /&gt;int runs = 20 * 1000;&lt;br /&gt;for (int i = 0; i &amp;lt; runs; i++) {&lt;br /&gt;    int x = i % 12;&lt;br /&gt;    int y = i / 12 % 12;&lt;br /&gt;    int times = x * y;&lt;br /&gt;    counters[times]++;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/fieldset&gt;and the heap usage reflects this &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-r4EkaLTlH_4/ThK8l_GI7CI/AAAAAAAAADc/ZwiSsQRnLxo/s1600/primitive-main-heap.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-r4EkaLTlH_4/ThK8l_GI7CI/AAAAAAAAADc/ZwiSsQRnLxo/s1600/primitive-main-heap.png" /&gt;&lt;/a&gt;&lt;/div&gt;There was no GCs over a period of 5 minutes. The test could have run longer and still not triggered a GC.&lt;br /&gt;And the average time per loop is much lower as well&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Took 198 ns per loop&lt;br /&gt;Took 17 ns per loop&lt;br /&gt;Took 16 ns per loop&lt;br /&gt;Took 14 ns per loop&lt;br /&gt;Took 15 ns per loop&lt;br /&gt;&lt;/pre&gt;In the first test, the JVM hasn't warmed up.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;Using primitives will perform better. (Unless there is excessive boxing and unboxing)&lt;br /&gt;&lt;br /&gt;Even in applications where performance is not critical, it will improve clarity, both of the code and when you do attempt to profile your application, it will reduce the level of "noise" making it clearer as to what the problem is.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Notes&lt;/h2&gt;Even in the test where few objects were created, you can see some object allocation.  This is mostly due to VisualVM's polling.  To reduce this I changed the polling interval from 3 seconds to 20 seconds.&lt;br /&gt;&lt;br /&gt;The Eden size was increased to make the graphs clearer with &lt;i&gt;-XX:NewSize=100m&lt;/i&gt;  This value is not recommend (except perhaps for micro-benchmarks) but its is a parameter you may need to tune for your application.&lt;br /&gt;&lt;h2&gt;Full code&lt;/h2&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/main/java/com/google/code/java/core/primitives/PrimitiveMain.java"&gt;Primitive benchmark&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/core-java-performance-examples/source/browse/trunk/src/main/java/com/google/code/java/core/primitives/WrapperMain.java"&gt;Wrapper benchmark&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1729822519392175009-6911458158935366498?l=vanillajava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vanillajava.blogspot.com/feeds/6911458158935366498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vanillajava.blogspot.com/2011/07/low-gc-in-java-use-primitives-instead.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1729822519392175009/posts/default/6911458158935366498'/
