Vlákno názorů k článku Nechte Go plavat, teď sviští Java od atarist - Bylo by možná dobré připomenout jeden z důvodů,...

  • Článek je starý, nové názory již nelze přidávat.
  • 4. 12. 2018 8:30

    atarist (neregistrovaný)

    Bylo by možná dobré připomenout jeden z důvodů, proč se Go relativně dobře rozšířilo. Je to mj. i díky gorutinám a kanálům, jak jejich podpoře v jazyku, tak i jejich "lehkotonážnost" při použití. Co takto namísto mikrobenchmarků nahodit něco paralelního, kde se dají kanály a gorutiny použít?

  • 4. 12. 2018 10:12

    Jaroslav Tulach (neregistrovaný)

    Ano, na potřebu "skutečného" benčmárku jsme již také narazili. Hrál si s tím Michal, můj kolega z jiného týmu a patra. Vytvořil web-fmwks-perf-comparision, kde chce testovat reálné scénáře: HTTP, parsování JSONu, přístup do databáze, atd. Zatím je tam to HTTP.

    Pomáhal jsem mu to uchodit s native-image. Bylo dost těžké Go dohnat, ale nakonec se to snad povedlo. Akorát jsem musel nahradit Netty za NanoHTTPD. Zdá se, že v Netty je příliš mnoho abstrakcí a na obyčejném Hello World příkladu to příliš zpomaluje. Po přepsání a znovu využití vláken ta Java verze přeložená native-image dokázala odpovědět na patnáct tisíc dotazů za sekundu. Asi tak stejně jako Go.

    Ale zrovna HTTP server je příklad použití, kde by normální JVM po dosažení optimálního stavu (po pár tisících dotazech) zřejmě fungovala rychleji než native-image...

  • 4. 12. 2018 10:50

    vv (neregistrovaný)

    "Pomáhal jsem mu to uchodit s native-image"
    ono to teda neni jednoduchy na pouziti?

  • 4. 12. 2018 11:24

    Martin (neregistrovaný)

    Chtěl jsem zkusit ten native-image, rychlý start pro cli programy by byl pěkný.

    $ java -version
    openjdk version "1.8.0_192"
    OpenJDK Runtime Environment (build 1.8.0_192-20181024121959.buildslave.jdk8u-src-tar--b12)
    GraalVM 1.0.0-rc9 (build 25.192-b12-jvmci-0.49, mixed mode)
    
    $ cat HelloWorld.java
    public class HelloWorld {
        public static void main(String[] args) throws Exception {
            System.out.println("Hello, World");
        }
    }
    
    $ javac HelloWorld.java && java HelloWorld
    Hello, World
    
    $ native-image --static -cp . HelloWorld
    Build on Server(pid: 32471, port: 44227)
    [helloworld:32471]    classlist:     171.66 ms
    [helloworld:32471]        (cap):     103.20 ms
    [helloworld:32471]        setup:     174.61 ms
    fatal error: com.oracle.svm.core.util.VMError$HostedError: java.nio.charset.UnmappableCharacterException: Input length = 1
            at com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:70)
            at com.oracle.svm.hosted.c.codegen.CSourceCodeWriter.writeFile(CSourceCodeWriter.java:183)
            at com.oracle.svm.hosted.c.codegen.CSourceCodeWriter.writeFile(CSourceCodeWriter.java:160)
    ... zkráceno
    Error: Processing image build request failed

    Zdá se, že to ještě má mouchy, ale třeba jsem tomu jen nevěnoval dost času...

  • 4. 12. 2018 13:10

    Jaroslav Tulach (neregistrovaný)

    Děkuji za vyzkoušení. Je mi líto, že to spadlo. Můžete zadat chybu na https://github.com/oracle/graal/issues a přidat nějaké detaily, protože mně to na Kubuntu 16.04 prošlo...

  • 4. 12. 2018 14:03

    Snoopy (neregistrovaný)

    Tohle se děje, když je GraalVM nainstalováno v nějakém adresáři s diakritikou. V jakém adresáři je vaše instalace?

  • 4. 12. 2018 15:17

    Martin (neregistrovaný)

    Bingo! Přeci jenom funguje, tak uvidím jak si povede až zkusím něco reálnějšího.
    Třeba ještě dostane java šanci i pro cli nástroje...

    Jasně, že hello world není reprezentativní program, ale zaujalo mě několik věcí:
    Velikost ~7MB u staticky linkované binárky je dost (ale chápu, že tam je runtime s gc a ostatním příslušenstvím), dynamicky linkované ~6MB je pořád dost. Z GO padají binárky o podobné velikosti. Kompilace do binárky trvá u hello world 20sec - to mi přijde jako hodně, ale zase kompilaci člověk nepouští tak často. Start výsledné binárky je okamžitý, subjketivně rychlejší než klasické jvm.

    $ mv ~/Stažené/graalvm-ce-1.0.0-rc9 ~/Sandbox
    
    $ export PATH=~/Sandbox/graalvm-ce-1.0.0-rc9/bin:$PATH
    
    $ javac HelloWorld.java && java HelloWorld && native-image --static -cp . HelloWorld
    Hello, World
    Build on Server(pid: 8989, port: 35763)*
    [helloworld:8989]    classlist:   1,090.04 ms
    [helloworld:8989]        (cap):   1,032.43 ms
    [helloworld:8989]        setup:   2,087.33 ms
    [helloworld:8989]   (typeflow):   4,684.50 ms
    [helloworld:8989]    (objects):   2,183.62 ms
    [helloworld:8989]   (features):      79.43 ms
    [helloworld:8989]     analysis:   7,054.64 ms
    [helloworld:8989]     universe:     323.77 ms
    [helloworld:8989]      (parse):     831.03 ms
    [helloworld:8989]     (inline):   1,367.12 ms
    [helloworld:8989]    (compile):   5,685.21 ms
    [helloworld:8989]      compile:   8,498.63 ms
    [helloworld:8989]        image:     726.43 ms
    [helloworld:8989]        write:     201.11 ms
    [helloworld:8989]      [total]:  20,041.28 ms
    
    $ time ./helloworld
    Hello, World
    ./helloworld  0,00s user 0,00s system 93% cpu 0,002 total
    
    $ ls -lah helloworld
    -rwxr-xr-x 1 martin martin 7,1M  4. pro 14.51 helloworld
    
    $ ldd helloworld
            není dynamickým spustitelným kódem
    
    $ native-image -cp . HelloWorld
    zsh: correct 'HelloWorld' to 'helloworld' [nyae]? n
    Build on Server(pid: 8989, port: 35763)
    [helloworld:8989]    classlist:     190.99 ms
    [helloworld:8989]        (cap):     601.78 ms
    [helloworld:8989]        setup:   1,002.38 ms
    [helloworld:8989]   (typeflow):   3,407.67 ms
    [helloworld:8989]    (objects):   1,644.25 ms
    [helloworld:8989]   (features):      69.44 ms
    [helloworld:8989]     analysis:   5,211.27 ms
    [helloworld:8989]     universe:     164.07 ms
    [helloworld:8989]      (parse):     516.41 ms
    [helloworld:8989]     (inline):     577.43 ms
    [helloworld:8989]    (compile):   3,090.78 ms
    [helloworld:8989]      compile:   4,514.93 ms
    [helloworld:8989]        image:     418.64 ms
    [helloworld:8989]        write:     113.15 ms
    [helloworld:8989]      [total]:  11,644.94 ms
    
    $ time ./helloworld
    Hello, World
    ./helloworld  0,00s user 0,00s system 93% cpu 0,003 total
    
    $ ls -lah helloworld
    -rwxr-xr-x 1 martin martin 6,3M  4. pro 14.59 helloworld
    
    $ ldd helloworld
            linux-vdso.so.1 (0x00007ffc5a7fb000)
            libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f7e71422000)
            libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f7e7141d000)
            libz.so.1 => /usr/lib/libz.so.1 (0x00007f7e71206000)
            librt.so.1 => /usr/lib/librt.so.1 (0x00007f7e711fc000)
            libcrypt.so.1 => /usr/lib/libcrypt.so.1 (0x00007f7e711c2000)
            libc.so.6 => /usr/lib/libc.so.6 (0x00007f7e70ffe000)
            /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f7e71a56000)
  • 4. 12. 2018 13:31

    Jaroslav Tulach (neregistrovaný)

    Pokud vše funguje, jak má, tak je to jednoduché. Ale pokud se něco zadrhne, začne to být obtížnější. Například výsledný "exáč" se ladí pomocí gdb a to je při přechodu z tradiční Javy takové hodně dřevní. A tak dále.

  • 4. 12. 2018 17:34

    Franta Kučera

    Dají se vůbec při ladění "napárovat" ty nativní instrukce na původní zdroják v Javě (nebo jiném jazyce)?

  • 4. 12. 2018 18:32

    Jaroslav Tulach (neregistrovaný)

    Ano. Lze to. Pokud tomu rozumím, tak se používá třída NodeSourcePosi­tion. Pozice se obvykle vyskytuje v bajtkódu a po naparsování do grafu se přiřadí k jednotlivým vrcholům. Kompilátor ten graf pak různě mění, ale i když nějaké vrcholy zahodí a vytvoří místo nich jiné, tak jim předá vhodnou pozici. Vrcholy, které zbudou v poslední fázi (a generují nativní instrukce), tak stále mají jakýsi vztah k původním pozicím. Tak asi tak. Více jsem to nezkoumal.