RFR(s): 8078463: optimize java/util/Map/Collisions.java (original) (raw)

Stuart Marks stuart.marks at oracle.com
Thu May 14 20:47:10 UTC 2015


On 5/14/15 1:22 AM, Daniel Fuchs wrote:

I'm curious: have you tried with using a lambda instead? changing:

394 static void check(String desc, boolean cond) { 395 if (cond) { 396 pass(); 397 } else { 398 fail(desc); 399 } 400 } into static void check(Supplier descSupplier, boolean cond) { if (cond) { pass(); } else { fail(descSupplier.get()) } } I wonder how the performance would compare...

I hadn't tried this, but I did out of curiosity. It's not very good. Here are the numbers:

(current jdk9-dev, -Xcomp -XX:+DeoptimizeALot -client, 3GHz i7, MBP 13" 2014, elapsed time in seconds, averaged over five runs)

 21.4  original
 18.7  lambda
 14.2  varargs
 12.3  multiple overloads (proposed version)

I'm not too surprised. The lambda calls will look something like this:

 check(() -> String.format("map expected size m%d != k%d", map.size(), 

keys.length), map.size() == keys.length);

Although the string formatting itself isn't performed unless the assertion fails, this is pretty much the worst case scenario for lambda. Every lambda is a capturing lambda, so the metafactory has to create a new lambda instance every time. However, the lambda itself is never actually called. That adds a lot of overhead.

In addition, there are several cases where the captured variables aren't effectively final, so I had to copy them into local variables and capture those instead. This was merely annoying, but it's a inconvenient and it adds a bit of clutter.

Anyway, good idea, but lambda didn't really work for this. I'm going to push my original patch.

s'marks



More information about the core-libs-dev mailing list