Question about Linker.Option.isTrivial()

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Jan 12 17:03:02 UTC 2024


On 12/01/2024 16:28, 刘希晨 wrote:
> Hi I want to ask a question about using project-panama, I implemented 
> a network library using JDK21 with panama-foreign and the performance 
> are quite well, since the API will officially release in JDK22, I 
> started to migrating my project to using JDK22-ea, and I have a 
> question about using Linker.Option.isTrivial(), I noticed that in 
> JDK22 it seems to be renamed as Linker.Option.critical(), the javadoc 
> says the function should have an extremely short running time in all 
> cases, and does not callback into Java. I am pretty sure that it could 
> be used on some functions returning constants macro from C, but in 
> some cases, I am not quite sure if this option could be used, here are 
> some examples:
It's hard to define a clear boundary - the thing to keep in mind is that 
critical() disables GC while the call is active - so you don't want to 
run it for a very long time. But if you understand the consequences, you 
might be in a better position to judge if that's ok.
>
> 1. calling malloc() and free(), or some other API like epoll_create() 
> and epoll_ctl()
malloc and free definitively (and I used that in the past - I think the 
current implementation of Arena::allocate also skips the transition, so 
effectively it's as if it were using that option). I'm less sure about 
the others, as I'm not too familiar with them.
> 2. calling send() and recv() on non-blocking sockets
That should be ok (because of the non-blocking nature)
> 3. just assigning some values to the target structs in C functions
Definitively - that's, one might argue, one of the things critical() is 
designed for.
>
> They all have a very short running time, and they do not callback into 
> Java, I have tested using Linker.Option.isTrivial() and they all went 
> well, but I am still not very sure about my usage here, since I don't 
> quite understand what Linker.Option.isTrivial() did under the hood, so 
> I want to seek some suggestions from experts here.

I believe you are good. As I said, the main thing is that code in 
critical state never safepoints, so GC can't run while you are in 
critical native. But if you used that option in few places, and you 
noticed no degradation of GC performance, then I think you are good.

That said... in many cases and benchmarks I made, I could not see a big 
difference between critical and non-critical. It is really good for 
short-lived calls (e.g. ~10ns), but if you call heavier stuff it gets in 
the noise pretty rapidly (e.g. from 25ns onwards). Typically it amounts 
to 4-5ns of savings, which might not make a difference at all in the big 
picture.

The new flavor of critical available in 22, on the other hand (which 
allows you to pass pinned heap segments as well) is much more powerful, 
as it allows you to omit memory copy in some cases. So, typically, the 
advantages of using that mode tend to scale more even as the cost of the 
called function goes up.

Maurizio




More information about the panama-dev mailing list