Weird performance behavior involving VarHandles
Per-Ake Minborg
per-ake.minborg at oracle.com
Wed Apr 24 07:04:34 UTC 2024
Hi Rémi,
I understand how the code is supposed to work (interesting solution!) but actually seeing how things are inlined/folded in reality is often hard. What you could do is to try and log inlining. Jorn has written some excellent articles about this:
https://jornvernee.github.io/methodhandles/2024/01/19/methodhandle-primer.html#method-handle-inlining
https://jornvernee.github.io/hotspot/jit/2023/08/18/debugging-jit.html#3-printing-inlining-traces
I hope that can give you some additional clues what is going on. If not, I hope someone else with more knowledge on the compiler can point you in the right direction.
Best, Per Minborg
________________________________
From: panama-dev <panama-dev-retn at openjdk.org> on behalf of Remi Forax <forax at univ-mlv.fr>
Sent: Wednesday, April 24, 2024 8:37 AM
To: hotspot compiler <hotspot-compiler-dev at openjdk.java.net>
Cc: panama-dev <panama-dev at openjdk.org>
Subject: Weird performance behavior involving VarHandles
Hello,
i'm trying to build an API on top of the foreign memory API and i've found a performance difference i'm not able to explain.
I'm using a guardWithTest to try to provide a simple way to access a VarHandle on a MemoryLayout without having to declare each VarHandle by hand,
so instead of
private static final StructLayout LAYOUT = MemoryLayout.structLayout(
ValueLayout.JAVA_INT.withName("x"),
ValueLayout.JAVA_INT.withName("y")
);
private static final VarHandle HANDLE_X =
LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("x"));
private static final VarHandle HANDLE_Y =
LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("y"));
I want something like
private static final MethodHandle MH = guardWithTest(
TEST.bindTo("x"),
dropArguments(constant(VarHandle.class, HANDLE_X), 0, String.class),
guardWithTest(
TEST.bindTo("y"),
dropArguments(constant(VarHandle.class, HANDLE_Y), 0, String.class),
BOOM
));
(TEST does an == on the strings and BOOM throws an exception)
which if called with "x" returns the VarHandle for "x" and if called with "y" returns the VarHandle for "y".
Now if I try to benchmark the performance with JMH,
private final MemorySegment segment = Arena.ofAuto().allocate(LAYOUT);
@Benchmark
public int control() {
var x = (int) HANDLE_X.get(segment, 0L);
var y = (int) HANDLE_Y.get(segment, 0L);
return x + y;
}
@Benchmark
public int gwt2_methodhandle() throws Throwable {
var x = (int) ((VarHandle) MH.invokeExact("x")).get(segment, 0L);
var y = (int) ((VarHandle) MH.invokeExact("y")).get(segment, 0L);
return x + y;
}
I get
Benchmark Mode Cnt Score Error Units
ReproducerBenchmarks.control avgt 5 1.250 ± 0.024 ns/op
ReproducerBenchmarks.gwt2_methodhandle avgt 5 1.852 ± 0.024 ns/op
and I don't understand why there is a difference in performance because for c2, the strings "x" and "y" are constant so the corresponding VarHandles should be constant thus optimized the same way.
The full benchmark is available here:
https://raw.githubusercontent.com/forax/memory-mapper/master/src/main/java/com/github/forax/memorymapper/bench/ReproducerBenchmarks.java
regards,
Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20240424/1ca38cf8/attachment-0001.htm>
More information about the panama-dev
mailing list