<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>Hi,<br>
      I'm not 100% this discussion is a good fit for this mailing list.
      The issue you are reporting seems to have nothing to do with the
      FFM API, or SymbolLookup.</p>
    <p>Honestly, from the kind of numbers you get, I tend to agree with
      Sebastian when he said this:</p>
    <p>
      <blockquote type="cite">
        <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>
      </blockquote>
      <br>
      E.g there seems to be something kicking in when that temporary
      folder is touched, anti-virus, or something else (this is a shared
      lib you are moving around, so it wouldn't be surprising if the OS
      looked at that operation suspiciously).</p>
    <p>For instance:</p>
    <p><a class="moz-txt-link-freetext" href="https://support.apple.com/en-ie/HT202491">https://support.apple.com/en-ie/HT202491</a></p>
    <p>Have you tried setting your OS to trust applications from any
      source? (temporarily of course). Does that make any difference?</p>
    <p>I think it would be good to capture the situation you are facing
      in a bug report - but before we do that, I guess it would be great
      if you could setup a repo somewhere with some reproducer that
      other people can just run (e.g. something with maven or gradle?).
      So that we can have a better ideas of what might be the culprit
      and/or which OS might be affected.</p>
    <p>Note that having a dependency on Netty might make things more
      confusing - when you access a static method on KQueue, you are
      going to run static initializers (I don't know off-hand how many),
      but it is not unusual for big frameworks to have a biggie startup
      time - since in Java classes are loaded and initialized on demand,
      you only see that cost when you call the KQueue method - but you
      are not just measuring how long does it take for that method to
      complete, you are also measuring the time the JVM takes to load
      _all_ the classes that might be required (and they might be more
      then you think) as well as running static initializers on some of
      them (which might pull in more classes, etc.).</p>
    <p>Try to run with the JVM `-verbose` option, which prints which
      classes are loaded and when, so that you can get an idea of how
      much stuff actually happens when you call that KQueue method.</p>
    <p>Cheers<br>
      Maurizio<br>
    </p>
    <div class="moz-cite-prefix">On 27/05/2023 18:34, 刘希晨 wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CABUmArT_OU-Hm8w4hCpFgF9tGK_rKuoW2Tn283MbsUCJU_MPog@mail.gmail.com">
      
      <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;

<span style="color:rgb(207,142,109)">import </span>io.netty.channel.kqueue.KQueue;

<span style="color:rgb(207,142,109)">public class </span>NativeTest {
    <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)">long </span>l = System.<span style="font-style:italic">currentTimeMillis</span>();
        KQueue.<span style="font-style:italic">isAvailable</span>();
        System.<span style="color:rgb(199,125,187);font-style:italic">out</span>.println(System.<span style="font-style:italic">currentTimeMillis</span>() - l);
    }
}</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" moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true" class="moz-txt-link-freetext">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>;
<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 {
    <span style="color:rgb(207,142,109)">long </span>start = System.<span style="font-style:italic">currentTimeMillis</span>();
    FileInputStream fileInputStream = <span style="color:rgb(207,142,109)">new </span>FileInputStream(<span style="color:rgb(199,125,187);font-style:italic">s</span>);
    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>);
    Path p = f.toPath();
    Files.<span style="font-style:italic">copy</span>(fileInputStream, p, StandardCopyOption.<span style="color:rgb(199,125,187);font-style:italic">REPLACE_EXISTING</span>);
    f.deleteOnExit();
    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));
    SymbolLookup symbolLookup = SymbolLookup.<span style="font-style:italic">libraryLookup</span>(p, SegmentScope.<span style="font-style:italic">global</span>());
    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));
    fileInputStream.close();
}</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:
                          <a class="moz-txt-link-rfc2396E" href="mailto:/opt/homebrew/Cellar/openssl@3/3.1.0/lib/engines-3">"/opt/homebrew/Cellar/openssl@3/3.1.0/lib/engines-3"</a><br>
                          MODULESDIR:
                          <a class="moz-txt-link-rfc2396E" href="mailto:/opt/homebrew/Cellar/openssl@3/3.1.0/lib/ossl-modules">"/opt/homebrew/Cellar/openssl@3/3.1.0/lib/ossl-modules"</a><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" moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true" class="moz-txt-link-freetext">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>
    </blockquote>
  </body>
</html>