-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace Unsafe with VarHandle #67
Comments
@qweek I suggest, in a new pr, create a dedicated |
@qweek It can be published as a multi-release JAR in the same artifact that is still compatible with Java 8: https://in.relation.to/2017/02/13/building-multi-release-jars-with-maven/ |
@gzm55 I'll try to look at it, but it won't be any time soon. It may be easier for you to start by checking how much it speeds up your use cases. @plokhotnyuk I thought about multi-release JAR, but it have some drawbacks:
With such a structure that is required to maintain backward compatibility, the code will turn into mess |
@qweek I see that in your fork there is no support for seed. It was difficult to implement? |
I try to benchmark the @qweek, in your implementation and benchmark, is there other difference between two compared version?
JDK 11 Result Benchmark Mode Cnt Score Error Units
VarHandleJmh.getLongPlain avgt 3 480385.742 ± 45707.927 ns/op
VarHandleJmh.getLongUnsafe avgt 3 405600.434 ± 609.814 ns/op JDK 17 Result Benchmark Mode Cnt Score Error Units
VarHandleJmh.getLongPlain avgt 3 165615.717 ± 387.519 ns/op
VarHandleJmh.getLongUnsafe avgt 3 80043.996 ± 102.376 ns/op Code import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.Random;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 3, time = 3)
@Measurement(iterations = 3, time = 3)
@Fork(1)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class VarHandleJmh {
private final static int L = 1024 * 1024;
byte data[] = new byte[L];
private static final Unsafe UNSAFE;
private static final long BYTE_BASE;
private static final VarHandle LONG_HANDLE = MethodHandles.byteArrayViewVarHandle(long[].class, LITTLE_ENDIAN);
static {
Unsafe u = null;
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
u = (Unsafe) theUnsafe.get(null);
} catch (final Exception e) {
}
UNSAFE = u;
BYTE_BASE = UNSAFE.arrayBaseOffset(byte[].class);
}
@Setup
public void init() {
new Random().nextBytes(data);
}
@Benchmark
public void getLongUnsafe(Blackhole bh) {
for (long i = BYTE_BASE; i < BYTE_BASE + L - 8; i += 8) {
final long d = UNSAFE.getLong(data, i);
bh.consume(d);
}
}
@Benchmark
public void getLongPlain(Blackhole bh) {
for (long i = 0; i < L - 8; i += 8) {
final long d = (long)LONG_HANDLE.get(data, (int)i);
bh.consume(d);
}
}
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
} |
I also benchmarked a dedicated VarHandleAccess vs UnsafeAccess, the latter one still performs about 5% better. |
Just wanted to let you know that on Java 17 I stumbled upon a strange problem with hashing, MD5 in particular. It is hard to provide a repeatable scenario as this happened on PROD system without any clear circumstances. And one of the attempted solutions was to switch to this library and XXH3 algorithm since we care about speed and not crypto.
|
I tested my implementation for Java 9+ with VarHandles instead of Unsafe.
In my test case (hashing multiple files with a total size of ~ 1 GB) I noticed a huge speed improvement
Is it possible to publish separate version for modern JDKs without dependency on Unsafe?
The text was updated successfully, but these errors were encountered: