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