October 18, 2013

Java 8 Method Reference and Lambda Performance

I happened to come across a post on SO talking about performance of methods called via reflection and method handles. I was under the impression that method handles was a Java 8 thing. To my surprise it is actually in Java 7 (I've been coding android for a while so never played much with it). I figure it would be worth while to extend the answers there to show off the performance of some of the Java 8 features. I.e. lambda and method references. It doesn't actually answer the question there so I won't pollute it on SO but I can write it here to show it:

I took the basic code for the micro-benchmark (again micro, does not truly reflect real world performance). A quick dump of my laptop specs (cause people always ask):

Operating System
Windows 7 Ultimate 64-bit SP1
CPU
Intel Core i7 620M @ 2.67GHz 46 °C
Arrandale 32nm Technology
RAM
4.00GB Dual-Channel DDR3 @ 532MHz (7-7-7-20)
Motherboard
LENOVO 2516CTO (None) 53 °C
Graphics
ThinkPad Display 1440x900 (1440x900@60Hz)
DELL P2211H (1920x1080@60Hz)
256MB NVIDIA NVS 3100M (Lenovo)
Hard Drives
298GB HITACHI HTS725032A9A364 ATA Device (SATA) 33 °C
SD Memory Card (NULL)
Optical Drives
Optiarc DVD RW AD-7930H ATA Device
Audio
Conexant 20585 SmartAudio HD

The code I am running is pretty much copy paste from the SO post, but I added a few lines to add in the Java 8 stuff. Anyone familiar with Java will see the new syntax and be in awe at the performance.


And of course here are the results:

reflective invocation (without setAccessible) 4.847 ns
reflective invocation (with setAccessible) 4.593 ns
methodhandle invocation 11.511 ns
static final methodhandle invocation 0.000 ns
direct invocation 0.000 ns
method reference invocation 0.000 ns
lambda invocation 0.000 ns

Which pretty much means the performance is no better than static final methodhandles OR direct invocations... which goes to show how huge of an impact these new constructs will have to functional programming in Java. I am impressed.

2 comments :

  1. I suspect that there are some optimizations which invalidate the results. If you look at the actual details of "direct invocation 0.000 ns" you find (for my pc) 76 ns for 2147483647 (2^31) iterations. Believe me, my pc is not THAT fast.

    ReplyDelete
  2. You are absolutely correct about there being optimizations. I'm not sure that invalidates the results. The micro benchmark is more just to compare the performance of the different constructs to eachother. The above case shows how the JVM can optimize away the non-reflective invocations and simply return the correct value without having to actually run all the iterations.

    When I posted this, I was surprised the JVM could optimize methodhandles because I would have guessed they were just syntactic sugar.

    ReplyDelete