4 ms·
> The JVM world tends to solve this problem by using off-heap caches. See Apache Ignite [0] or Ehcache [1]. For those who care, I was interested how off-heap c
by stingraycharles 7y ago
> The JVM world tends to solve this problem by using off-heap caches. See Apache Ignite [0] or Ehcache [1].
For those who care, I was interested how off-heap caching works in Java and I did some quick searching around the Apache Ignite code.
The meat is here:
- GridUnsafeMemory, an implementation of access to entries allocated off-heap. This appears to implement some common Ignite interface, and invokes calls to a “GridUnsafe” class https://github.com/apache/ignite/blob/53e47e9191d717b3eec495e6246cd957a8d33c7d/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridUnsafeMemory.java https://github.com/apache/ignite/blob/53e47e9191d717b3eec495...
- This class is the closest to the JVM’s native memory, and wraps sun.misc.Unsafe: https://github.com/apache/ignite/blob/53e47e9191d717b3eec495e6246cd957a8d33c7d/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java https://github.com/apache/ignite/blob/53e47e9191d717b3eec495...
- And this, sun.misc.Unsafe, is what it’s all about: http://www.docjar.com/docs/api/sun/misc/Unsafe.html http://www.docjar.com/docs/api/sun/misc/Unsafe.html
It’s very interesting because I did my fair share of JNI work, and context switches between JVM and native code are typically fairly expensive. My guess is that this class was likely one of the reasons why Sun ended up implementing their (undocumented) JavaCritical* etc functions and the likes.
- winrid 7y agoThe idea is that that call is still less expensive than going over the wire and MUCH less expensive than having the GC go through that heap now and then.
- stingraycharles 7y agoYes sorry I should have elaborated, those Critical JNI calls avoid locking the GC and in general are much more lightweight. This is available for normal JNI devs as well, its just not documented. They were primarily intended for some internal things that Sun needed. I’m now guessing that this might actually have been those Unsafe classes as an intended use case. It makes total sense and I can see how that will be very fast.
- chrisseaton 7y ago> context switches between JVM and native code are typically fairly expensive Aren't these Unsafe memory read and write methods intrinsified by any serious compiler? I don't believe they're using JNI or doing any kind of managed/native transition, except in the interpreter. They turn into the same memory read and write operations in the compiler's intermediate representation as Java field read and writes do.
- jfim 7y agoThey are optimized, yes, but from what I recall from reading the JVM code a few years ago, some optimizations don't get applied to those reads/writes. For example, summing two arrays together will be vectorized to use SSE instructions while doing so through Unsafe won't [0]. [0] https://cr.openjdk.java.net/~vlivanov/talks/2017_Vectorization_in_HotSpot_JVM.pdf https://cr.openjdk.java.net/~vlivanov/talks/2017_Vectorizati...
- sreque 7y agoUnsafe lets you manipulate memory without any JNI overhead other than when allocating or de-allocating memory, and that is usually done in larger chunks and pooled to avoid the overhead at steady state. Netty also takes advantage of Unsafe to move a lot of memory operations off the java heap. Unsafe was one of the cooler aspects to Java that Oracle is actively killing for, well, no good reason at least.
- kllrnohj 7y ago> Unsafe was one of the cooler aspects to Java that Oracle is actively killing for, well, no good reason at least. I mean, there's the obvious reason that it breaks the memory safety aspect that Java in general guarantees. The whole point of the feature is to subvert the language & expectations. I'm not saying they should remove it, but it's pretty hard to argue there's "no good reason" to kill it, either. It is, after all, taking the worst parts of C and ramming it into a language that is otherwise immune from that entire class of problems.
- jayd16 7y agoC# seems to have a neat middle ground for this kind of stuff with their Span<T> api.
- to11mtm 7y agoTrue, but we had our own version of unsafe for a much longer time. MS was just pragmatic enough to allow it across the ecosystem. I'm guessing at least some of that was a side effect of wanting to support C++; not having pointers as an option would have killed C++/CLI from the get go.
- thu2111 7y agoThey aren't killing it. They're steadily designing safe and API stable replacements for its features, with equal performance. That is a very impressive engineering feat! For instance fast access to un-GCd off heap memory is being added at the moment via the MemoryLayout class. Once that's here apps that upgrade won't need to use Unsafe anymore. MemoryLayout gives equivalent performance but with bounds checked accesses, so you can't accidentally corrupt the heap and crash the JVM. They've been at it for a long time now. For instance VarHandle exposes various low level tools like different kinds of memory barriers that are needed to implement low level concurrency constructs. They're working on replacements for some of the anonymous class stuff too.