<div dir="ltr"><div dir="ltr"><div dir="ltr">For whatever it's worth, I think that C# does pinning fairly well.<div>It uses a "fixed" statement around a variable which is similar to a try-with-resources in Java.</div><div><br></div><div>Without introducing a new keyword this could probably be done as a Functional Interface that takes a lamba or something.</div><div><br></div><div>> withPinned(heapSegment, segment -> {});</div><div><br></div><div>- <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/fixed">fixed statement - pin a moveable variable | Microsoft Learn</a></div><div>- <a href="https://learn.microsoft.com/en-us/dotnet/framework/interop/copying-and-pinning">Copying and Pinning - .NET Framework | Microsoft Learn</a></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 28, 2023 at 9:04 AM Yasumasa Suenaga <<a href="mailto:suenaga@oss.nttdata.com">suenaga@oss.nttdata.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Maurizio,<br>
<br>
Thank you for knowing ffmasm :)<br>
<br>
MS::pin/unpin in my proposal are same semantics with <br>
GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical in JNI. They <br>
might not be leveraged a lot of developers, but they help a part of <br>
experienced developers to improve their application performance. In JNI, <br>
we call GetPrimitiveArrayCritical() to access large arrays without <br>
memory copy cost. It makes sence. I just want to do same operation in <br>
FFM.<br>
<br>
Let's think about image processing. When we want to binarize JPEG image, <br>
we would load original image with ImageIO API. Then we can get pixels <br>
from BufferedImage::getRGB() as int[]. So we have to copy pixels into <br>
off-heap MemorySegment if we want to perform operations in native (e.g. <br>
SIMD, GPU processing). I'm sure most of Java API / third party libraries <br>
use primitive array, not MemorySegment. So I think it is better if we <br>
pin on-heap memory and leverage it in native.<br>
<br>
Of course I understand it might be some worse behaviors especially GC, <br>
so pinning might not be recommended for all of Java developers. But I <br>
believe pinning is welcomed from developers who experienced in native <br>
(C/C++/assembly/GPGPU and so on) because they want to offload processing <br>
which needs large memory (preprocessed in Java).<br>
<br>
<br>
Thanks,<br>
<br>
Yasumasa<br>
<br>
<br>
2023-08-28 18:48 に Maurizio Cimadamore さんは書きました:<br>
> On 28/08/2023 08:29, Yasumasa Suenaga wrote:<br>
>> Hi all,<br>
>> <br>
>> I'm very interested in FFM, especially generate assembly code in Java <br>
>> and calling them with FFM [1].<br>
> Hi,<br>
> I've seen your work a year or so ago and have been very impressed by it <br>
> :-)<br>
>> <br>
>> I think one of the performance neck is MemorySegment because all of <br>
>> on-heap regions should be copied into off-heap region (native segment) <br>
>> when they are referred from foreign function. So I'm expecting to <br>
>> implement sort of pinning operation for on-heap MemorySegment like a <br>
>> JNI. I guess it is mentioned in FFM update in last month [2], however <br>
>> "Pinning of heap segments" does not have any links - I guess nobody is <br>
>> working for this yet. Do you have any updates for pinning?<br>
>> <br>
>> I've played them with both OpenJDK 22 with pinning support [3] and <br>
>> ffmasm (hand-assembler for Java powered by FFM) [4]. I added pin/unpin <br>
>> method into Unsafe, and they are called by HeapMemorySegmentImpl. <br>
>> Finally I got about 16x performance gain compared to non-pinning code <br>
>> [5] on my laptop.<br>
>> <br>
>> I guess FFM API reaches to goal step by step, but it is still a <br>
>> preview in JDK 21. I hope that pinning feature is supported into JDK <br>
>> 22 because I believe we can leverage FFM for more fields! I'm happy to <br>
>> contribute/help to implement pinning feature if it needs.<br>
> <br>
> While there's no doubt that in some applications and use cases pinning<br>
> provides a significant performance boost, there are some challenges:<br>
> <br>
> 1. scope of pinning: is pinning allowed on a per-native-call basis? Or<br>
> is it something more general?<br>
> 2. does the garbage collection support region-based pinning [1] ?<br>
> 3. why is pinning needed in the first place?<br>
> <br>
> (1) and (2) are very much linked. Not all garbage collectors support<br>
> fine-grained pinning mechanism. Which means that, in most of them, if<br>
> you pin, you effectively block GC for the entire duration of the pin<br>
> operation (GC locker mechanism). This is something that, as I'm sure<br>
> you understand, is not very desirable. For this reason, it might be<br>
> better to consider a pinning API which only pins for the duration of a<br>
> native call (e.g. in the shape of an additional linker option). While<br>
> FFM could support more complex pinning policies (e.g. pin a segment<br>
> inside an Arena, so that segment is unpinned when the arena is<br>
> closed), given the uneven support for fine-grained pinning across GCs,<br>
> I'm not sure such a general API (which is similar to your "MS::pin"<br>
> method) would be a good idea. We're doing some experiments for adding<br>
> a new linker option which allows for pin heap segments to be pinned<br>
> when calling a downcall method handle, we're not yet sure of its<br>
> inclusion, but it would be something worth publishing somewhere (when<br>
> ready) so that developers (like you) can play with it and provide<br>
> feedback.<br>
> <br>
> Then there's (3). Most of the times, pinning is used in order to<br>
> interact with native calls from public-facing APIs that are "stuck"<br>
> using array syntax. That is, in order to be user friendly, such API<br>
> work with arrays - but then a problem arises when trying to use the<br>
> contents of the array off-heap. But what if the memory was off-heap to<br>
> begin with? Then no memory copy would be required. I believe the<br>
> biggest impediment for off-heap memory being used directly has to do<br>
> with the fact that, for users, interacting with an `int[]` is<br>
> significantly easier than interacting with a `MemorySegment`, or a<br>
> `ByteBuffer`. But what if we could provide some mechanism to create an<br>
> "array view" over an off-heap memory region? Now clients would be able<br>
> to use the beloved `[]` syntax, even if memory access remained<br>
> off-heap.<br>
> <br>
> While we don't have any concrete proposal on this latter point, we do<br>
> believe that the topic of making memory segments (or byte buffer)<br>
> easier to access for "legacy clients" is inextricably linked to the<br>
> topic of pinning of heap memory.<br>
> <br>
> [1] - <a href="https://openjdk.org/jeps/423" rel="noreferrer" target="_blank">https://openjdk.org/jeps/423</a><br>
> <br>
>> <br>
>> <br>
>> Thanks,<br>
>> <br>
>> Yasumasa<br>
>> <br>
>> <br>
>> [1] <a href="https://github.com/YaSuenag/ffmasm" rel="noreferrer" target="_blank">https://github.com/YaSuenag/ffmasm</a><br>
>> [2] <br>
>> <a href="https://mail.openjdk.org/pipermail/panama-dev/2023-July/019510.html" rel="noreferrer" target="_blank">https://mail.openjdk.org/pipermail/panama-dev/2023-July/019510.html</a><br>
>> [3] <br>
>> <a href="https://github.com/YaSuenag/jdk/commit/f0a9b3705b3ecdf3dbb6b80cac9d53456f08f967" rel="noreferrer" target="_blank">https://github.com/YaSuenag/jdk/commit/f0a9b3705b3ecdf3dbb6b80cac9d53456f08f967</a><br>
>> [4] <br>
>> <a href="https://github.com/YaSuenag/ffmasm/commit/925608538b936db1b311ae84e12fa0252058b7f4" rel="noreferrer" target="_blank">https://github.com/YaSuenag/ffmasm/commit/925608538b936db1b311ae84e12fa0252058b7f4</a><br>
>> [5] <br>
>> <a href="https://github.com/YaSuenag/ffmasm/blob/ffm-pinning/benchmarks/vectorapi/src/main/java/com/yasuenag/ffmasm/benchmark/vectorapi/VectorOpComparison.java" rel="noreferrer" target="_blank">https://github.com/YaSuenag/ffmasm/blob/ffm-pinning/benchmarks/vectorapi/src/main/java/com/yasuenag/ffmasm/benchmark/vectorapi/VectorOpComparison.java</a><br>
</blockquote></div>