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

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<String> 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