<div dir="ltr"><div dir="ltr">Today I did some more tests about the scenario, and what surprised me is that this problem has a wide influence.<div><br></div><div>I am not an expert in C or C++, and I am not familiar with the underlying JVM source codes, I could only judge from the results and let you guys find out what's really wrong.</div><div><br></div><div>This copy then loadlibrary mechanism has been used by a lot of famous open-source projects, such as Netty or RocksDB, in fact I learned from them when I was developing my own framework.</div><div>So I tested a really really simple example to prove my idea.</div><div><br></div><div><div style="background-color:rgb(30,31,34);color:rgb(188,190,196)"><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(207,142,109)">package </span>com.example.demo;<br><br><span style="color:rgb(207,142,109)">import </span>io.netty.channel.kqueue.KQueue;<br><br><span style="color:rgb(207,142,109)">public class </span>NativeTest {<br>    <span style="color:rgb(207,142,109)">public static void </span><span style="color:rgb(86,168,245)">main</span>(String[] args) {<br>        <span style="color:rgb(207,142,109)">long </span>l = System.<span style="font-style:italic">currentTimeMillis</span>();<br>        KQueue.<span style="font-style:italic">isAvailable</span>();<br>        System.<span style="color:rgb(199,125,187);font-style:italic">out</span>.println(System.<span style="font-style:italic">currentTimeMillis</span>() - l);<br>    }<br>}</pre></div></div></div><div><br></div><div>The Kqueue static block will load the underlying Kqueue dylib library into the process, and this single line cost 900ms on my M1-pro Macbook, while starting a tcp server cost about 1000ms, which is to say that most of the time was consumed by this mechanism.</div><div><br></div><div>Just try the code above, I don't know why this is happening, and hope you experts could prove me wrong. cheers!</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Sebastian Stenzel <<a href="mailto:sebastian.stenzel@gmail.com">sebastian.stenzel@gmail.com</a>> 于2023年5月27日周六 13:54写道:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr">Have you tried copying and dlopen'ing the .dylib from a C program?</div><div dir="ltr">If you think that copying it is the culprit, it may be some other OS security feature, since it is the first time for the OS to open the binary from a new location…?</div><br><div dir="ltr"><blockquote type="cite">Am 27.05.2023 um 04:18 schrieb 刘希晨 <<a href="mailto:benrush0705@gmail.com" target="_blank">benrush0705@gmail.com</a>>:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr">The temp folder is not an influence factor, it will happen in any folder that calling System.load() or SymbolLookup.librarylookup() on a new copied dynamic library, as long as the target dynamic library was just created in filesystem by copy() or other mechanism. Calling for the first time is even worse, might take a second to do the job, since then it becomes 300ms per call. I also tested changing the file size of the .dylib, which seems to have no effect on the time consumption.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">刘希晨 <<a href="mailto:benrush0705@gmail.com" target="_blank">benrush0705@gmail.com</a>> 于2023年5月27日周六 08:16写道:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Sorry guys, fall asleep last night, cause it's late in my country.<div><br></div><div>I have run some more tests, and now I am 100% percent sure that the problem is not about System.load() or SymbolLookup.librarylookup() and I am pretty sure it should be reproducible.</div><div><br></div><div>here is the minimal version of the reproducible code:</div><div><br></div><div>```</div><div><div style="background-color:rgb(30,31,34);color:rgb(188,190,196)"><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(207,142,109)">private static final </span>String <span style="color:rgb(199,125,187);font-style:italic">s </span>= <span style="color:rgb(106,171,115)">"/Users/liuxichen/workspace/demo/src/main/resources/lib/libcrypto.3.dylib"</span>;<br><span style="color:rgb(207,142,109)">public static void </span><span style="color:rgb(86,168,245)">main</span>(String[] args) <span style="color:rgb(207,142,109)">throws </span>IOException {<br>    <span style="color:rgb(207,142,109)">long </span>start = System.<span style="font-style:italic">currentTimeMillis</span>();<br>    FileInputStream fileInputStream = <span style="color:rgb(207,142,109)">new </span>FileInputStream(<span style="color:rgb(199,125,187);font-style:italic">s</span>);<br>    File f = File.<span style="font-style:italic">createTempFile</span>(<span style="color:rgb(106,171,115)">"test"</span>, <span style="color:rgb(106,171,115)">".dylib"</span>);<br>    Path p = f.toPath();<br>    Files.<span style="font-style:italic">copy</span>(fileInputStream, p, StandardCopyOption.<span style="color:rgb(199,125,187);font-style:italic">REPLACE_EXISTING</span>);<br>    f.deleteOnExit();<br>    System.<span style="color:rgb(199,125,187);font-style:italic">out</span>.println(<span style="color:rgb(106,171,115)">"File operation cost : " </span>+ (System.<span style="font-style:italic">currentTimeMillis</span>() - start));<br>    SymbolLookup symbolLookup = SymbolLookup.<span style="font-style:italic">libraryLookup</span>(p, SegmentScope.<span style="font-style:italic">global</span>());<br>    System.<span style="color:rgb(199,125,187);font-style:italic">out</span>.println(<span style="color:rgb(106,171,115)">"all cost : " </span>+ (System.<span style="font-style:italic">currentTimeMillis</span>() - start));<br>    fileInputStream.close();<br>}</pre></div></div><div>```</div><div><br></div><div>here is my test results :</div><div>1. Just running System.load() or SymbolLookup.librarylookup() will have no problem and that should cost just about 3ms, no matter it's in the normal folder or in the tmp folder.</div><div>2. If using mechanism in the above codes, which is directly call SymbolLookup.librarylookup() right after copying file to tmp folder, the operation is quite slow, it takes about 300ms each time on my M1-pro chips</div><div>3. The performance drop using above code is not that obvious on Windows or Linux, cost about 20ms</div><div><br></div><div>I think my OpenSSL library is right in arm architecture, since I install it using homebrew:</div><div>❯ openssl version -a<br>OpenSSL 3.1.0 14 Mar 2023 (Library: OpenSSL 3.1.0 14 Mar 2023)<br>built on: Tue Mar 14 12:59:07 2023 UTC<br>platform: darwin64-arm64-cc<br>options:  bn(64,64)<br>compiler: clang -fPIC -arch arm64 -O3 -Wall -DL_ENDIAN -DOPENSSL_PIC -D_REENTRANT -DOPENSSL_BUILDING_OPENSSL -DNDEBUG<br>OPENSSLDIR: "/opt/homebrew/etc/openssl@3"<br>ENGINESDIR: "/opt/homebrew/Cellar/openssl@3/3.1.0/lib/engines-3"<br>MODULESDIR: "/opt/homebrew/Cellar/openssl@3/3.1.0/lib/ossl-modules"<br>Seeding source: os-specific<br>CPUINFO: OPENSSL_armcap=0x187d<br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Sebastian Stenzel <<a href="mailto:sebastian.stenzel@gmail.com" target="_blank">sebastian.stenzel@gmail.com</a>> 于2023年5月27日周六 02:22写道:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Is it reproducible? Maybe your openssl .dylib is x86_64 and Rosetta kicked in on first use?<br>
<br>
> Am 26.05.2023 um 18:21 schrieb Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com" target="_blank">maurizio.cimadamore@oracle.com</a>>:<br>
> <br>
> <br>
>> On 26/05/2023 16:51, 刘希晨 wrote:<br>
>> I noticed a weird problem about SymbolLookup.libraryLookup() with SegmentScope.global when I was testing on my M1-pro macbook using JDK20, the method took about 700ms to finish when loading OpenSSL's dynamic library, this result is quite slow. I tested on Windows and Linux(using WSL on Windows) with older hardware (AMD Ryzen 3700x) and it takes around 100ms. Please run some tests about this situation and correct me if I am wrong. Thanks for your help!<br>
> Hi,<br>
> <br>
> this seems very odd, we will look into it.<br>
> <br>
> Note that SymbolLookup::libraryLookup just ends up straight into a dlopen call. There are not many strings attached, really. 700ms (but even 100ms) seems quite a lot to me.<br>
> <br>
> Can you also try with System::loadLibrary - is it faster that way (I very much doubt it, since the underlying code is the same?)<br>
> <br>
> Cheers<br>
> Maurizio<br>
> <br>
</blockquote></div>
</blockquote></div>
</div></blockquote></div></blockquote></div></div>