New candidate JEP: 471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal

forax at univ-mlv.fr forax at univ-mlv.fr
Tue May 7 12:02:24 UTC 2024


----- Original Message -----
> From: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> To: "Remi Forax" <forax at univ-mlv.fr>, "jdk-dev" <jdk-dev at openjdk.org>
> Cc: "Ron Pressler" <ron.pressler at oracle.com>
> Sent: Tuesday, May 7, 2024 12:20:48 PM
> Subject: Re: New candidate JEP: 471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal

> Hi Remi,

Hi Maurizio,

> we do have benchmarks like that, and are aware of the cost for creating
> arenas.
> 
> We will try to improve this area over time, but please note that the way
> you are using arenas is not very idiomatic.
> 
> That is, while you can of course create a single arena for a single
> segment, this doesn't seem to be a very realistic use case.

The problem is that if i'm designing a new API, I can take a SegmentAllocator as parameter but this is not what i'm trying to do, i'm trying to replace the usages of Unsafe by the java.lang.foreign API, often i've not the luxury to change the API of the existing code.

I'm glad that you agree that the example of the class OffHeapIntBuffer in the JEP 471 that is using Arena.ofShared() in not very realistic. As i've said, i'm not against the goal of this JEP, I find it too optimistic, replacing usages of Unsafe by the java.lang.foreign API will take time because it's not a drop-in replacement.


> Jextract-generated structs have factories that allow the user to specify
> an external allocator, which is, I think, a much better way to do
> things, as clients should want more control of the lifetime in which
> things get allocated.

Also taking a SegmentAllocator as parameters introduce 3 issues:
- obviously it's not backward compatible
- there is a problem of trust, should my code verify the return value of SegmentAllocator.allocate() or blindy trust the SegmentAllocator implementation ? And also who is responsible for zeroing (*) the segment ?
- that interface has no explicit signal to indicate that a memory segment can be recycled, so a lot of existing memory allocators/algorithms can not be implemented.

(*) BTW, zeroing is a big difference between a SegmentAllocator and an Arena but I believe it's not explicily documented in the SegmentAllocator API.

> 
> If you really want something close to a "raw" allocation, then you can
> create downcall method handles for "malloc" and "free" and take it from
> there. You will get restricted warnings (as you should, since you are
> opting out of the safety provided by arenas), but you should get
> performance numbers that are more aligned with a raw Unsafe::allocate
> memory.

If your code is a library it's not really an option.
And now the controvertial part, if I control the command line, now i've a tradeoff, I can write my own malloc library as you suggest or I can export jdk.internal.misc to access jdk.internal.misc.Unsafe. The latter means using an unsupported API which is bad but it's a drop-in replacement for sun.misc.Unsafe, which is tempting. 

> 
> Maurizio

Rémi

> 
> 
> On 06/05/2024 17:47, Remi Forax wrote:
>> Hello,
>> I think this JEP is a little too optimistic,
>> I've spent the last two weeks trying to replace all the usages of Unsafe with
>> the foreign memory API in my code (public or private) and there are some rough
>> edges.
>>
>> The main blocker in my case if that creating an Arena ranges between slow for a
>> confined arena to very very slow for a shared arena.
>>
>> Here is a JMH benchmark [0] to understand the issue:
>>
>> // Benchmark                                Mode  Cnt     Score     Error  Units
>> // ArenaBenchmarks.newArray                 avgt    5     2.529 ±   0.013  ns/op
>> // ArenaBenchmarks.newSegmentAuto           avgt    5   409.666 ± 210.548  ns/op
>> // ArenaBenchmarks.newSegmentConfined       avgt    5    82.353 ±   0.263  ns/op
>> // ArenaBenchmarks.newSegmentShared         avgt    5  7094.796 ± 297.683  ns/op
>> // ArenaBenchmarks.newSegmentWrap           avgt    5     6.454 ±   0.113  ns/op
>> // ArenaBenchmarks.newUnsafeMemory          avgt    5    22.753 ±   0.023  ns/op
>> // ArenaBenchmarks.newUnsafeMemoryWithInit  avgt    5    71.563 ±   0.827  ns/op
>>
>> It compares the cost of allocating an array of bytes either in Java (newArray),
>> using different arenas (newSegmentAuto, newSegmentConfined, newSegmentShared)
>> or using sun.misc Unsafe (newUnsafeMemory, newUnsafeMemoryWithInit).
>>
>> As an example, the migration of OffHeapIntBuffer is not really realistic because
>> of the performance cost of Arena.ofShared() is 300x compared to
>> Unsafe.allocate().
>>
>> I'm not saying the foreign memory API is not amazing, it is, I was able to
>> replace all the codes using Unsafe based on mmap to use the memory segment
>> without any performance loss but there are still some rough edges and I think
>> we should acknowledge that.
>>
>> regards,
>> Rémi
>>
>>
>> [0]
>> https://github.com/forax/memory-mapper/blob/master/src/main/java/com/github/forax/memorymapper/bench/ArenaBenchmarks.java
>>
>> ----- Original Message -----
>>> From: "mark reinhold" <mark.reinhold at oracle.com>
>>> To: "Ron Pressler" <ron.pressler at oracle.com>
>>> Cc: "jdk-dev" <jdk-dev at openjdk.org>
>>> Sent: Friday, May 3, 2024 5:11:42 PM
>>> Subject: New candidate JEP: 471: Deprecate the Memory-Access Methods in
>>> sun.misc.Unsafe for Removal
>>> https://openjdk.org/jeps/471
>>>
>>>   Summary: Deprecate the memory-access methods in sun.misc.Unsafe for
>>>   removal in a future release. These unsupported methods have been
>>>   superseded by standard APIs, namely the VarHandle API (JEP 193,
>>>   JDK 9) and the Foreign Function & Memory API (JEP 454,
>>>   JDK 22). We strongly encourage library developers to migrate from
>>>   sun.misc.Unsafe to supported replacements, so that applications can
>>>   migrate smoothly to modern JDK releases.
>>>
> >> - Mark


More information about the jdk-dev mailing list