$30 off During Our Annual Pro Sale. View Details »

JVM Workshop

JVM Workshop

Jakub Kubryński

November 06, 2018
Tweet

More Decks by Jakub Kubryński

Other Decks in Programming

Transcript

  1. @jkubrynski / kubrynski.blog
    @jkubrynski / kubrynski.blog
    JVM DIVE FOR MERE MORTALS
    JVM DIVE FOR MERE MORTALS
    WORKSHOPS
    WORKSHOPS
    JAKUB KUBRYNSKI
    JAKUB KUBRYNSKI
    [email protected] / @jkubrynski / https://kubrynski.blog

    View Slide

  2. $ WHOAMI
    $ WHOAMI
    14+ YEARS PROFESSIONAL EXPERIENCE
    14+ YEARS PROFESSIONAL EXPERIENCE
    DEVSKILLER CO-FOUNDER
    DEVSKILLER CO-FOUNDER
    BOTTEGA TRAINER & AUDITOR
    BOTTEGA TRAINER & AUDITOR
    DEVOXX.PL PROGRAM COMMITTEE MEMBER
    DEVOXX.PL PROGRAM COMMITTEE MEMBER
    OPENSOURCE CONTRIBUTOR
    OPENSOURCE CONTRIBUTOR

    View Slide

  3. WHO ARE YOU?
    WHO ARE YOU?
    Bytecode ?
    Hashtable vs ConcurrentHashMap
    ?
    JIT ?
    Concurrent Mark-Sweep ?
    Re ection vs MethodHandle ?
    Invokedynamic ?

    View Slide

  4. PERFORMANCE TUNING PRINCIPLES
    PERFORMANCE TUNING PRINCIPLES
    measurement
    one change at a time
    deep understanding over stackover ow.com
    hints

    View Slide

  5. JAVA VIRTUAL MACHINE
    JAVA VIRTUAL MACHINE

    View Slide

  6. LIFE CYCLE
    LIFE CYCLE
    source -> javac -> bytecode
    bytecode -> classloader -> interpreter
    interpreter -> JIT -> optimized native code

    View Slide

  7. SOURCE CODE
    SOURCE CODE
    package com.random.company.app;
    public class StringUtilsHelper {
    public boolean isEmpty(String str) {
    return str != null && str.length() > 0;
    }
    }

    View Slide

  8. JAVAC
    JAVAC
    converts source code into byte
    code
    checks
    simple optimizations

    View Slide

  9. CLASS FILE
    CLASS FILE
    ClassFile
    u4 magic; // CAFEBABE
    u2 minor_version;
    u2 major_version;
    u2 constant_pool_count;
    cp_info constant_pool[constant_pool_count-1];
    u2 access_flags;
    u2 this_class;
    u2 super_class;
    u2 interfaces_count;
    u2 interfaces[interfaces_count];
    u2 fields_count;
    field_info fields[fields_count];
    u2 methods_count;
    method_info methods[methods_count];
    u2 attributes count;

    View Slide

  10. BYTECODE
    BYTECODE
    list of operation
    codes
    $xxd -p Test.class
    ...1b04a0000504ac2a1b0464b600021b68ac...
    1b => 27 => iload_1
    04 => 4 => iconst_1
    a0 => 160 => if_icmpne 7
    04 => 4 => iconst_1
    ac => 172 => ireturn
    2a => 42 => aload_0
    1b => 27 => iload_1
    04 => 4 => iconst_1
    64 => 100 => isub
    b6 => 182 => invokevirtual #5
    1b => 27 => iload_1
    68 => 104 => imul
    ac => 172 => ireturn

    View Slide

  11. BYTECODE - MORE INFO
    BYTECODE - MORE INFO
    current usage: 239/255
    $JDK/src/hotspot/share/interpreter/bytecodes.hpp
    class sun.jvm.hotspot.interpreter.Bytecodes
    http://www.javaworld.com/article/2077233/core-java/bytecode-
    basics.html

    View Slide

  12. JAVAC DEMO
    JAVAC DEMO
    HTTPS://GITHUB.COM/JKUBRYNSKI/JVM-WORKSHOP
    HTTPS://GITHUB.COM/JKUBRYNSKI/JVM-WORKSHOP

    View Slide

  13. CLASSLOADER
    CLASSLOADER
    dynamically loads
    classes
    hierarchies
    Bootstrap classloader
    Extension classloader
    Application
    classloader
    Custom classloader

    View Slide

  14. CLASSLOADING PHASES
    CLASSLOADING PHASES
    loading -> reads class le
    linking
    verifying -> veri es bytecode correctness
    preparing -> allocates memory
    resolving -> links with classes, interfaces, elds,
    methods
    initializing -> static initializers

    View Slide

  15. INTERPRETER
    INTERPRETER
    detects the critical hot spots in the
    program
    template interpreter
    java -XX:+UnlockDiagnosticVMOptions -XX:+PrintInterpreter -version

    View Slide

  16. INTERPRETER - MORE INFO
    INTERPRETER - MORE INFO
    $JDK/src/hotspot/share/interpreter/templateTable.cpp#TemplateTable::initialize
    https://openjdk.java.net/groups/hotspot/docs/RuntimeOverview.html#Interpreter|outline

    View Slide

  17. JIT
    JIT
    Just-In-Time
    optimizes code
    compiles methods into native
    code
    -client (C1) / -server (C2)
    runs up to 20 times faster

    View Slide

  18. INLINING
    INLINING
    public String getStringFromSupplier(Supplier supplier) {
    return supplier.get();
    }
    public String businessMethod(String param) {
    Supplier stringSupplier = new StringSupplier(”my” + param);
    return getStringFromSupplier(stringSupplier);
    }
    // turns to
    public String businessMethod(String param) {
    Supplier stringSupplier = new StringSupplier(”my” + param);
    return stringSupplier.get();
    }

    View Slide

  19. UNROLLING
    UNROLLING
    private static String[] options = {"yes", "no", "true", "false"}
    public void someMethod() {
    for (String opt : options) {
    process(opt);
    }
    }
    //turns into
    public void someMethod() {
    process("yes");
    process("no");
    process("true");
    process("false");
    }

    View Slide

  20. SCALAR REPLACEMENT
    SCALAR REPLACEMENT
    public record(int x, int y) {
    Point point = new Point(x, y);
    storePoint(point);
    }
    // inlining
    public record(int x, int y) {
    Point point = new Point(x, y);
    events.store("Added point", point.x, point.y);
    }
    // scalar replacement
    public record(int x, int y) {
    events.store("Added point", x, y);
    }

    View Slide

  21. DEAD CODE ELIMINATION
    DEAD CODE ELIMINATION
    public void myMethod() {
    for (int i = 0; i < THRESHOLD; i++) {
    new String("test");
    }
    }
    // turns into
    public void myMethod() {
    }

    View Slide

  22. LOCK ELISION
    LOCK ELISION
    public void process(List users) {
    List result = new ArrayList<>();
    synchronized(result) {
    fillResult(users);
    }
    }
    //turns into
    public void process(List users) {
    List result = new ArrayList<>();
    fillResult(users);
    }

    View Slide

  23. TYPE SHARPENING
    TYPE SHARPENING
    List users = new ArrayList<>();
    // turns into
    ArrayList users = new ArrayList<>();

    View Slide

  24. ON STACK REPLACEMENT
    ON STACK REPLACEMENT
    happens when the interpreter discovers that a method is looping
    converts an interpreted stack frame into a native compiled stack
    frame

    View Slide

  25. TIERED COMPILATION
    TIERED COMPILATION
    LEVELS
    LEVELS
    0: Interpreted code
    1: Simple C1 compiled code
    2: Limited C1 compiled
    code
    3: Full C1 compiled code
    4: C2 compiled code

    View Slide

  26. WHY SHOULD I CARE?
    WHY SHOULD I CARE?
    JIT does most of the optimizations we could do manually without "obfuscating" source
    code
    Performance/load tests should run only on "hot" application

    View Slide

  27. HOW TO TRACK?
    HOW TO TRACK?
    When after restarting your app is at the full
    speed?
    $ jstat -compiler 1s
    // or
    JDK9+ => -Xlog:jit*=debug
    JDK8 => -XX:+PrintCompilation

    View Slide

  28. -XLOG:JIT
    -XLOG:JIT
    $JDK/src/hotspot/share/compiler/compileTask.cpp#CompileTask::print_impl
    const char compile_type = is_osr_method ? '%' : ' ';
    const char sync_char = is_synchronized ? 's' : ' ';
    const char exception_char = has_exception_handler ? '!' : ' ';
    const char blocking_char = is_blocking ? 'b' : ' ';
    const char native_char = is_native ? 'n' : ' ';
    compile_id, compile_type, sync_char, exception_char, blocking_char, native_char, comp_level
    [0,090s][debug][jit,compilation] 104 3 java.lang.module.ModuleDescriptor$Exports::isQualified (18 bytes)
    [0,096s][debug][jit,compilation] 122 4 java.lang.module.ModuleDescriptor$Exports::isQualified (18 bytes)
    [0,097s][debug][jit,compilation] 104 3 java.lang.module.ModuleDescriptor$Exports::isQualified (18 bytes) made not entrant
    [0,032s][debug][jit,compilation] 1 3 java.util.concurrent.ConcurrentHashMap::tabAt (22 bytes)
    [0,032s][debug][jit,inlining ] @ 15 jdk.internal.misc.Unsafe::getObjectAcquire (7 bytes)
    [0,059s][debug][jit,compilation] 35 n 0 java.lang.Object::hashCode (native)
    [0,065s][debug][jit,compilation] 41 ! 3 java.util.concurrent.ConcurrentHashMap::putVal (432 bytes)

    View Slide

  29. JIT DEMO
    JIT DEMO

    View Slide

  30. EXECUTION COMPONENTS
    EXECUTION COMPONENTS
    program
    counter
    frame
    stack

    View Slide

  31. STACK TRACE
    STACK TRACE
    "main@1" prio=5 tid=0x1 nid=NA runnable
    java.lang.Thread.State: RUNNABLE
    at io.codearte.BlockBuilder.startBlock(BlockBuilder.groovy:21)
    at io.codearte.Generator.process(Generator.java:318)
    at io.codearte.ImportantApp.do(ImportantApp.java:64)
    at sun.reflect.NativeMethodImpl.invoke(NativeMethodImpl.java:18)
    at sun.reflect.NativeMethodImpl.invoke(NativeMethodImpl.java:62)
    at java.lang.reflect.Method.invoke(Method.java:497)

    View Slide

  32. DEBUGGING
    DEBUGGING

    View Slide

  33. DEBUGGING
    DEBUGGING

    View Slide

  34. MEMORY LAYOUT
    MEMORY LAYOUT

    View Slide

  35. OBJECT LAYOUT
    OBJECT LAYOUT
    com.eshop.model.Product object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 12 (object header) N/A
    12 4 int Product.id N/A
    16 4 String Product.name N/A
    20 4 (loss due to the next object alignment)
    Instance size: 24 bytes (estimated, the sample instance is not available)
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

    View Slide

  36. OBJECT LAYOUT
    OBJECT LAYOUT
    com.eshop.model.Product object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 12 (object header) N/A
    12 4 int Product.id N/A
    16 4 int Product.price N/A
    20 4 String Product.name N/A
    Instance size: 24 bytes (estimated, the sample instance is not available)
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

    View Slide

  37. OBJECT LAYOUT
    OBJECT LAYOUT
    com.eshop.model.Product object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 12 (object header) N/A
    12 4 int Product.id N/A
    16 4 int Product.price N/A
    20 1 boolean Product.available N/A
    21 3 (alignment/padding gap) N/A
    24 4 String Product.name N/A
    28 4 (loss due to the next object alignment)
    Instance size: 32 bytes (estimated, the sample instance is not available)
    Space losses: 3 bytes internal + 4 bytes external = 7 bytes total

    View Slide

  38. OBJECT LAYOUT
    OBJECT LAYOUT
    com.eshop.model.Product object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 16 (object header) N/A
    16 4 int Product.id N/A
    20 4 int Product.price N/A
    24 1 boolean Product.available N/A
    25 7 (alignment/padding gap) N/A
    32 8 String Product.name N/A
    Instance size: 40 bytes (estimated, the sample instance is not available)
    Space losses: 3 bytes internal + 0 bytes external = 3 bytes total

    View Slide

  39. JAVA OBJECT LAYOUT
    JAVA OBJECT LAYOUT
    https://openjdk.java.net/projects/code-tools/jol/

    View Slide

  40. JOL DEMO
    JOL DEMO

    View Slide

  41. GARBAGE COLLECTOR
    GARBAGE COLLECTOR
    cleans memory
    important performance
    factor
    vector algorithm
    stop the world in safepoints

    View Slide

  42. GC ALGORITHMS
    GC ALGORITHMS
    Serial
    Parallel
    Concurrent Mark Sweep
    G1
    Epsilon* (No-Op) - JEP 318
    ZGC* (Low Latency) - JEP
    333
    * Experimental

    View Slide

  43. VECTOR ALGORITHM
    VECTOR ALGORITHM
    mark_gc_roots()
    for (each_root_object) {
    mark_all_referenced_objects()
    }
    for (each_object_in_memory) {
    if (is_marked_as_reacheable) {
    unmark_the_object()
    } else {
    remove_object_and_reclaim_memory()
    }
    }

    View Slide

  44. GENERATIONAL HYPOTESIS
    GENERATIONAL HYPOTESIS
    Infant mortality
    young objects are much more probable to
    die
    Idea is to process both generations
    separately
    Tenuring threshold

    View Slide

  45. GENERATIONAL HYPOTESIS
    GENERATIONAL HYPOTESIS
    Does not work for caches
    Do not keep caches in the same heap as the
    application
    Go off-heap

    View Slide

  46. DISPATCH TYPES
    DISPATCH TYPES
    invokevirtual
    invokestatic
    invokespecial
    invokedynamic

    View Slide

  47. LAMBDAS
    LAMBDAS
    generated by javac
    bootstraped by
    LambdaMetafactory
    called with invokedynamic

    View Slide

  48. LAMBDA UNDER THE HOOD
    LAMBDA UNDER THE HOOD
    BigDecimal sumCreditEntries(Client client) {
    return sumEntries(client.getAccounts(),
    account -> account.getCreditEntries());
    }
    private static java.util.List lambda$sumCreditEntries$0(com.sandbox.Account);
    private Period period;
    BigDecimal sumCreditEntries(Client client) {
    return sumEntries(client.getAccounts(),
    account -> account.getCreditEntries(period));
    }
    private java.util.List lambda$sumCreditEntries$0(com.sandbox.Account);
    BigDecimal sumCreditEntries(Client client, Period period) {
    return sumEntries(client.getAccounts(), account -> account.credit(period));
    }
    private static java.util.List lambda$sumCreditEntries$0
    (java.time.Period, com.sandbox.Account);

    View Slide

  49. METHOD REFERENCE
    METHOD REFERENCE
    SIMILAR TO LAMBDAS, BUT NO NEED TO GENERATE A METHOD
    SIMILAR TO LAMBDAS, BUT NO NEED TO GENERATE A METHOD
    BECAUSE WE'RE CALLING A METHOD
    BECAUSE WE'RE CALLING A METHOD

    View Slide

  50. BENCHMARKS
    BENCHMARKS
    CallTypes.baseline avgt 30 4.163 ± 0.009 ns/op
    CallTypes.lambda avgt 30 4.174 ± 0.015 ns/op
    CallTypes.methodRef avgt 30 4.244 ± 0.049 ns/op
    CallTypesExternal.baseline avgt 30 50.055 ± 0.275 ns/op
    CallTypesExternal.lambda avgt 30 50.980 ± 0.650 ns/op
    CallTypesExternal.methodRef avgt 30 50.655 ± 0.376 ns/op

    View Slide

  51. METHODHANDLES
    METHODHANDLES

    View Slide

  52. METHODHANDLES
    METHODHANDLES
    is not a replacement for re ection (re ection is more for introspection of classes)
    re ection does access control during invocation while MethodHandle checks all during
    lookup

    View Slide

  53. EXAMPLE
    EXAMPLE
    MethodHandle toUpperCase = MethodHandles.lookup()
    .findVirtual(String.class, "toUpperCase",
    MethodType.methodType(String.class))
    Object result = toUpperCase.invoke("test"));
    String result = (String) toUpperCase.invokeExact("test"));

    View Slide

  54. TIME TO BENCHMARK
    TIME TO BENCHMARK

    View Slide

  55. BENCHMARKS
    BENCHMARKS
    1ns = 0.000 001 ms = 0.000 000 001 s
    Benchmark Mode Cnt Score Error Units
    Invocations.baseline avgt 30 35.761 ± 0.113 ns/op
    Invocations.reflectionWithoutLookup avgt 30 41.413 ± 0.223 ns/op
    Invocations.handleWithoutLookup avgt 30 42.002 ± 1.002 ns/op
    Invocations.handleExactWithoutLookup avgt 30 38.134 ± 0.153 ns/op
    Invocations.reflection avgt 30 71.207 ± 1.558 ns/op
    Invocations.handle avgt 30 858.148 ± 18.135 ns/op

    View Slide

  56. EXCEPTIONS
    EXCEPTIONS
    public class ClientAlreadyExistsException extends Throwable {
    @Override
    public synchronized Throwable fillInStackTrace() {
    return this;
    }
    }

    View Slide

  57. EXCEPTIONS
    EXCEPTIONS
    DEEP MEANS THERE ARE 4 MORE FRAMES
    DEEP MEANS THERE ARE 4 MORE FRAMES
    Benchmark Mode Cnt Score Error Units
    Exceptions.standardExcept avgt 30 1029.919 ± 5.026 ns/op
    Exceptions.standardExceptDeep avgt 30 1121.771 ± 6.615 ns/op
    Exceptions.stacklessExcept avgt 30 18.827 ± 0.066 ns/op
    Exceptions.stacklessExceptDeep avgt 30 19.835 ± 0.053 ns/op

    View Slide

  58. STREAMS
    STREAMS
    TIME TO BENCHMARK
    TIME TO BENCHMARK

    View Slide

  59. FURTHER READING
    FURTHER READING
    Optimizing Java - Benjamin J Evans, James Gough
    The Well-Grounded Java Developer - Benjamin J. Evans, Martijn
    Verburg
    Java Performance - Charlie Hunt, Binu John
    Java Performance: The De nitive Guide - Scott Oaks

    View Slide

  60. TOOLS
    TOOLS
    jdk
    Visual VM
    Mission Control
    JPro ler
    Honest Pro ler
    Java Object
    Layout

    View Slide

  61. I WANT MORE!
    I WANT MORE!
    THE JAVA® VIRTUAL MACHINE SPECIFICATION
    THE JAVA® VIRTUAL MACHINE SPECIFICATION
    HG CLONE
    HG CLONE HTTP://HG.OPENJDK.JAVA.NET/JDK11/JDK11/
    HTTP://HG.OPENJDK.JAVA.NET/JDK11/JDK11/
    HTTP://OPENJDK.JAVA.NET/PROJECTS/CODE-TOOLS/JMH
    HTTP://OPENJDK.JAVA.NET/PROJECTS/CODE-TOOLS/JMH

    View Slide

  62. BENCHMARKS
    BENCHMARKS
    HTTPS://GITHUB.COM/JKUBRYNSKI/JVM-WORKSHOP
    HTTPS://GITHUB.COM/JKUBRYNSKI/JVM-WORKSHOP

    View Slide

  63. QUESTIONS?
    QUESTIONS?

    View Slide

  64. THANKS!
    THANKS!

    View Slide