SlideShare a Scribd company logo
1 of 107
What the JVM Does
 With Your Bytecode
When Nobody’s Looking
JVM JIT for Dummies
    And the rest of you, too.
Intro
• Charles Oliver Nutter
 • “JRuby Guy”
 • Sun Microsystems 2006-2009
 • Engine Yard 2009-
• Primarily responsible for compiler, perf
 • Lots of bytecode generation
What We Won’t

• GC tuning
• GC monitoring with VisualVM
 • Google ‘visualgc’, it’s awesome
What We Will Lean

• How the JVM’s JIT works
• Monitoring the JIT
• Finding problems
• Dumping assembly (don’t be scared!)
JIT

• Just-In-Time compilation
• Compiled when needed
 • Maybe immediately before execution
 • ...or when we decide it’s important
 • ...or never?
Mixed-Mode
• Interpreted
 • Bytecode-walking
 • Artificial stack
• Compiled
 • Direct native operations
 • Native registers, memory, etc
Profiling

• Gather data about code while interpreting
 • Invariants (types, constants, nulls)
 • Statistics (branches, calls)
• Use that information to optimize
 • Educated guess?
The Golden Rule of
   Optimization

  Don’t do unnecessary work.
Optimization
• Method inlining
• Loop unrolling
• Lock coarsening/eliding
• Dead code elimination
• Duplicate code elimination
• Escape analysis
Inlining?

• Combine caller and callee into one unit
 • e.g. based on profile
 • Perhaps with a guard/test
• Optimize as a whole
 • More code means better visibility
Inlining
int addAll(int max) {
  int accum = 0;
  for (int i = 0; i < max; i++) {
    accum = add(accum, i);
  }
  return accum;
}

int add(int a, int b) {
  return a + b;
}
Inlining
int addAll(int max) {
  int accum = 0;
  for (int i = 0; i < max; i++) {
    accum = add(accum, i);
  }
  return accum;
                   Only one target is   ever seen
}

int add(int a, int b) {
  return a + b;
}
Inlining

int addAll(int max) {
  int accum = 0;
  for (int i = 0; i < max; i++) {
    accum = accum + i;
  }
  return accum;   Don’t bother making   the call
}
Loop Unrolling

• Works for small, constant loops
• Avoid tests, branching
• Allow inlining a single call as many
Loop Unrolling
private static final String[] options =
                   { "yes", "no", "maybe"};
public void looper() {
    for (String option : options) {
        process(option);
    }
}
                  Small loop, constant stride,
                         constant size
Loop Unrolling
private static final String[] options =
                   { "yes", "no", "maybe"};
public void looper() {
    process(options[0]);
    process(options[1]);       Unrolled!
    process(options[2]);
}
Lock Coarsening
public void needsLocks() {
    for (option : options) {
        process(option);
    }                           Repeatedly locking
}

private synchronized String process(String option) {
    // some wacky thread-unsafe code
}
Lock Coarsening
public void needsLocks() {         Lock once
    synchronized (this) {
        for (option : options) {
            // some wacky thread-unsafe code
        }
    }
}
Lock Eliding
public void overCautious() {       Synchronize on
    List l = new ArrayList();
    synchronized (l) {
                                     new Object
        for (option : options) {
            l.add(process(option));
        }
    }
}
                But we know it
               never escapes this
                   thread...
Lock Eliding
public void overCautious() {
    List l = new ArrayList();
    for (option : options) {
        l.add(
          /* process()’s code */);
    }
}
                          No need to lock
Escape Analysis
private static class Foo {
    public String a;
    public String b;
    Foo(String a, String b) {
        this.a = a;
        this.b = b;
    }
}
Escape Analysis
public void bar() {
    Foo f = new Foo("Hello", "Øredev");
    baz(f);
}

public void baz(Foo f) {        Same object all
    System.out.print(f.a);
    System.out.print(", ");    the way through
    quux(f);
}
                               Never “escapes”
public void quux(Foo f) {      these methods
    System.out.print(f.b);
    System.out.println('!');
}
Escape Analysis

public secret awesome inlinedBarBazQuux() {
    System.out.print("Hello");
    System.out.print(", ");
    System.out.print("Øredev");
    System.out.println('!');
}
                            Don’t bother allocating
                                 Foo object!
Perf Sinks
• Memory accesses
 • By far the biggest expense
• Calls
 • Memory ref + branch kills pipeline
 • Call stack, register juggling costs
• Locks and volatile writes
Volatile?
• Each CPU maintains a memory cache
• Caches may be out of sync
 • If it doesn’t matter, no problem
 • If it does matter, threads disagree!
• Volatile forces synchronization of cache
 • Across cores and to main memory
Call Site
• The place where you make a call
• Monomorphic (“one shape”)
 • Single target class
• Bimorphic (“two shapes”)
• Polymorphic (“many shapes”)
• Megamorphic (“you’re screwed”)
Blah.java
System.currentTimeMillis(); // static, monomorphic

List list1 = new ArrayList(); // constructor, monomorphic
List list2 = new LinkedList();

for (List list : new List[]{ list1, list2 }) {
  list.add("hello"); // bimorphic
}

for (Object obj : new Object[]{ 'foo', list1, new Object() }) {
  obj.toString(); // polymorphic
}
Hotspot
•   -client mode (C1) inlines, less aggressive
    •   Fewer opportunities to optimize
•   -server mode (C2) inlines aggressively
    •   Based on richer runtime profiling
    •   We’ll focus on this
•   Tiered mode combines them
    •   -XX:+TieredCompilation
C2 “server” Inlining
• Profile to find “hot spots”
 • Call sites
 • Branch statistics
 • Profile until 10k calls
• Inline mono/bimorphic calls
• Other mechanisms for polymorphic calls
Tuning Inlining
• -XX:+MaxInlineSize=35
 • Largest inlinable method (bytecode)
• -XX:+InlineSmallCode=#
 • Largest inlinable compiled method
• -XX:+FreqInlineSize=#
 • Largest frequently-called method...
Tuning Inlining

• -XX:+MaxInlineLevel=9
 • How deep does the rabbit hole go?
• -XX:+MaxRecursiveInlineLevel=#
 • Recursive inlining
Now it gets fun!
Monitoring the JIT

• Dozens of flags
• Reams of output
• Always evolving
• How can you understand it?
public class Accumulator {
  public static void main(String[] args) {
    int max = Integer.parseInt(args[0]);
    System.out.println(addAll(max));
  }

    static int addAll(int max) {
      int accum = 0;
      for (int i = 0; i < max; i++) {
        accum = add(accum, i);
      }
      return accum;
    }

    static int add(int a, int b) {
      return a + b;
    }
}
$ java -version
openjdk version "1.7.0-b147"
OpenJDK Runtime Environment (build 1.7.0-
b147-20110927)
OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode)

$ javac Accumulator.java

$ java Accumulator 1000
499500
Print Compilation

• -XX:+PrintCompilation
• Print methods as they JIT
 • Class + name + size
$ java -XX:+PrintCompilation Accumulator 1000
     53    1             java.lang.String::hashCode (67 bytes)
499500
$ java -XX:+PrintCompilation Accumulator 1000
     53    1             java.lang.String::hashCode (67 bytes)
499500


                    Where’s our code?!?
$ java -XX:+PrintCompilation Accumulator 1000
     53    1             java.lang.String::hashCode (67 bytes)
499500


                    Where’s our code?!?
                         Remember...10k calls before JIT
10k loop, 10k calls to add


$ java -XX:+PrintCompilation Accumulator 10000
     53    1             java.lang.String::hashCode (67 bytes)
     64    2             Accumulator::add (4 bytes)
49995000




                               Hooray!
But what’s this?


$ java -XX:+PrintCompilation Accumulator 10000
     53    1             java.lang.String::hashCode (67 bytes)
     64    2             Accumulator::add (4 bytes)
49995000

                Class loading, security logic, other stuff...
Dear god...there’s zombies in my code?!?
1401   70         java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
1412   71         java.lang.String::indexOf (7 bytes)
1420   72   !     java.io.BufferedReader::readLine (304 bytes)
1420   73         sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
1422   42         java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
1435   74     n   java.lang.Object::hashCode (0 bytes)
1443   29   !     sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
1443   25         sun.misc.URLClassPath::getResource (74 bytes)    made zombie
1443   36         sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
1443   43         java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
1449   75         java.lang.String::endsWith (15 bytes)
1631    1 %       sun.misc.URLClassPath::getResource @ 39 (74 bytes)
1665   76         java.lang.ClassLoader::checkName (43 bytes)
Dear god...there’s zombies in my code?!?
1401   70         java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
1412   71         java.lang.String::indexOf (7 bytes)
1420   72   !     java.io.BufferedReader::readLine (304 bytes)
1420   73         sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
1422   42         java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
1435   74     n   java.lang.Object::hashCode (0 bytes)
1443   29   !     sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
1443   25         sun.misc.URLClassPath::getResource (74 bytes)    made zombie
1443   36         sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
1443   43         java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
1449   75         java.lang.String::endsWith (15 bytes)
1631    1 %       sun.misc.URLClassPath::getResource @ 39 (74 bytes)
1665   76         java.lang.ClassLoader::checkName (43 bytes)



                                   Not entrant? What the heck?
Optimistic Compilers

• Assume profile is accurate
• Aggressively optimize based on profile
• Bail out if we’re wrong
 • ...and hope that we’re usually right
Deoptimization

• Bail out of running code
• Monitoring flags describe process
 • “uncommon trap” - we were wrong
 • “not entrant” - don’t let new calls enter
 • “zombie” - on its way to deadness
No JIT At All?


• Code is too big
• Code isn’t called enough
That looks exciting!

1401   70            java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
1412   71            java.lang.String::indexOf (7 bytes)
1420   72   !        java.io.BufferedReader::readLine (304 bytes)
1420   73            sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
1422   42            java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
1435   74     n      java.lang.Object::hashCode (0 bytes)
1443   29   !        sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
1443   25            sun.misc.URLClassPath::getResource (74 bytes)    made zombie
1443   36            sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
1443   43            java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
1449   75            java.lang.String::endsWith (15 bytes)
1631    1 %          sun.misc.URLClassPath::getResource @ 39 (74 bytes)
1665   76            java.lang.ClassLoader::checkName (43 bytes)
Exception handling in here (boring!)

1401   70         java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
1412   71         java.lang.String::indexOf (7 bytes)
1420   72   !     java.io.BufferedReader::readLine (304 bytes)
1420   73         sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
1422   42         java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
1435   74     n   java.lang.Object::hashCode (0 bytes)
1443   29   !     sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
1443   25         sun.misc.URLClassPath::getResource (74 bytes)    made zombie
1443   36         sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
1443   43         java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
1449   75         java.lang.String::endsWith (15 bytes)
1631    1 %       sun.misc.URLClassPath::getResource @ 39 (74 bytes)
1665   76         java.lang.ClassLoader::checkName (43 bytes)
What’s this “n” all about?

1401   70         java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
1412   71         java.lang.String::indexOf (7 bytes)
1420   72   !     java.io.BufferedReader::readLine (304 bytes)
1420   73         sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
1422   42         java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
1435   74     n   java.lang.Object::hashCode (0 bytes)
1443   29   !     sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
1443   25         sun.misc.URLClassPath::getResource (74 bytes)    made zombie
1443   36         sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
1443   43         java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
1449   75         java.lang.String::endsWith (15 bytes)
1631    1 %       sun.misc.URLClassPath::getResource @ 39 (74 bytes)
1665   76         java.lang.ClassLoader::checkName (43 bytes)
This method is native...maybe “intrinsic”

1401   70         java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
1412   71         java.lang.String::indexOf (7 bytes)
1420   72   !     java.io.BufferedReader::readLine (304 bytes)
1420   73         sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
1422   42         java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
1435   74     n   java.lang.Object::hashCode (0 bytes)
1443   29   !     sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
1443   25         sun.misc.URLClassPath::getResource (74 bytes)    made zombie
1443   36         sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
1443   43         java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
1449   75         java.lang.String::endsWith (15 bytes)
1631    1 %       sun.misc.URLClassPath::getResource @ 39 (74 bytes)
1665   76         java.lang.ClassLoader::checkName (43 bytes)



        We’ll come back to that...
And this one?

  1401   70         java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
  1412   71         java.lang.String::indexOf (7 bytes)
  1420   72   !     java.io.BufferedReader::readLine (304 bytes)
  1420   73         sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
  1422   42         java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
  1435   74     n   java.lang.Object::hashCode (0 bytes)
  1443   29   !     sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
  1443   25         sun.misc.URLClassPath::getResource (74 bytes)    made zombie
  1443   36         sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
  1443   43         java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
  1449   75         java.lang.String::endsWith (15 bytes)
  1631    1 %       sun.misc.URLClassPath::getResource @ 39 (74 bytes)
  1665   76         java.lang.ClassLoader::checkName (43 bytes)



Method has been replaced while running (OSR)
Millis from JVM start
1401   70         java.util.concurrent.ConcurrentHashMap::hash (49 bytes)
1412   71         java.lang.String::indexOf (7 bytes)
1420   72   !     java.io.BufferedReader::readLine (304 bytes)
1420   73         sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes)
1422   42         java.util.zip.ZipCoder::getBytes (192 bytes)    made not entrant
1435   74     n   java.lang.Object::hashCode (0 bytes)
1443   29   !     sun.misc.URLClassPath$JarLoader::getResource (91 bytes)    made zombie
1443   25         sun.misc.URLClassPath::getResource (74 bytes)    made zombie
1443   36         sun.misc.URLClassPath::getResource (74 bytes)    made not entrant
1443   43         java.util.zip.ZipCoder::encoder (35 bytes)    made not entrant
1449   75         java.lang.String::endsWith (15 bytes)
1631    1 %       sun.misc.URLClassPath::getResource @ 39 (74 bytes)
1665   76         java.lang.ClassLoader::checkName (43 bytes)



       Sequence number of compilation
Print Inlining

• -XX:+UnlockDiagnosticVMOptions
  -XX:+PrintInlining
• Display hierarchy of inlined methods
• Include reasons for not inlining
• More, better output on OpenJDK 7
$ java -XX:+UnlockDiagnosticVMOptions 
>      -XX:+PrintInlining 
>      Accumulator 10000
49995000
$ java -XX:+UnlockDiagnosticVMOptions 
>      -XX:+PrintInlining 
>      Accumulator 10000
49995000
             Um...I don’t see anything inlining
public class Accumulator {
  public static void main(String[] args) {
    int max = Integer.parseInt(args[0]);
    System.out.println(addAll(max));
  }

    static int addAll(int max) {   Called   only once
      int accum = 0;
      for (int i = 0; i < max; i++) {
        accum = add(accum, i);
      }
      return accum;
    }

    static int add(int a, int b) {
      return a + b;
    }
}
public class Accumulator {
  public static void main(String[] args) {
    int max = Integer.parseInt(args[0]);
    System.out.println(addAll(max));
  }

    static int addAll(int max) {   Called only   once
      int accum = 0;
      for (int i = 0; i < max; i++) {
        accum = add(accum, i);
      }
      return accum;
                          Called 10k times
    }

    static int add(int a, int b) {
      return a + b;
    }
}
public class Accumulator {
  public static void main(String[] args) {
    int max = Integer.parseInt(args[0]);
    System.out.println(addAll(max));
  }

    static int addAll(int max) {   Called only   once
      int accum = 0;
      for (int i = 0; i < max; i++) {
        accum = add(accum, i);
      }
      return accum;
                          Called 10k times
    }

    static int add(int a, int b) {    JITs as expected
      return a + b;
    }
}
public class Accumulator {
  public static void main(String[] args) {
    int max = Integer.parseInt(args[0]);
    System.out.println(addAll(max));
  }

    static int addAll(int max) {   Called only   once
      int accum = 0;
      for (int i = 0; i < max; i++) {
        accum = add(accum, i);
      }
      return accum;
                          Called 10k times
    }

    static int add(int a, int b) {    JITs as expected
      return a + b;
    }
}                       But makes no calls!
static double addAllSqrts(int max) {
  double accum = 0;
  for (int i = 0; i < max; i++) {
    accum = addSqrt(accum, i);
  }
  return accum;
}

static int addSqrt(double a, int b) {
  return a + sqrt(b);
}

static double sqrt(int a) {
  return Math.sqrt(b);
}
$ java -XX:+UnlockDiagnosticVMOptions 
>       -XX:+PrintInlining 
>       -XX:+PrintCompilation 
>       Accumulator 10000
     53     1             java.lang.String::hashCode (67 bytes)
     65     2             Accumulator::addSqrt (7 bytes)
            @ 3   Accumulator::sqrt (6 bytes)    inline (hot)
              @ 2   java.lang.Math::sqrt (5 bytes)    (intrinsic)
     65     3             Accumulator::sqrt (6 bytes)
            @ 2   java.lang.Math::sqrt (5 bytes)    (intrinsic)
666616.4591971082
$ java -XX:+UnlockDiagnosticVMOptions 
>       -XX:+PrintInlining                   HOT HOT HOT!
>       -XX:+PrintCompilation 
>       Accumulator 10000
     53     1             java.lang.String::hashCode (67 bytes)
     65     2             Accumulator::addSqrt (7 bytes)
            @ 3   Accumulator::sqrt (6 bytes)    inline (hot)
              @ 2   java.lang.Math::sqrt (5 bytes)    (intrinsic)
     65     3             Accumulator::sqrt (6 bytes)
            @ 2   java.lang.Math::sqrt (5 bytes)    (intrinsic)
666616.4591971082
LogCompilation

• -XX:+LogCompilation
• Worst. XML. Evar.
• <JDK>/hotspot/src/share/tools/LogCompilation
   • or http://github.com/headius/logc
scopes_pcs_offset='1384' dependencies_offset='1576' handler_table_offset='1592' nul_chk_table_offset='1736'
oops_offset='992' method='org/jruby/lexer/yacc/ByteArrayLexerSource$ByteArrayCursor read ()I' bytes='49'
count='5296' backedge_count='1' iicount='10296' stamp='0.412'/>
<writer thread='4425007104'/>
<nmethod compile_id='21' compiler='C2' entry='4345862528' size='1152' address='4345862160'
relocation_offset='288' insts_offset='368' stub_offset='688' scopes_data_offset='840' scopes_pcs_offset='904'
dependencies_offset='1016' handler_table_offset='1032' oops_offset='784' method='org/jruby/lexer/yacc/
ByteArrayLexerSource forward (I)I' bytes='111' count='5296' backedge_count='1' iicount='10296' stamp='0.412'/>
<writer thread='4300214272'/>
<task_queued compile_id='22' method='org/jruby/lexer/yacc/ByteArrayLexerSource read ()I' bytes='10'
count='5000' backedge_count='1' iicount='10000' stamp='0.433' comment='count' hot_count='10000'/>
<writer thread='4426067968'/>
<nmethod compile_id='22' compiler='C2' entry='4345885984' size='1888' address='4345885584'
relocation_offset='288' insts_offset='400' stub_offset='912' scopes_data_offset='1104'
scopes_pcs_offset='1496' dependencies_offset='1704' handler_table_offset='1720' nul_chk_table_offset='1864'
oops_offset='1024' method='org/jruby/lexer/yacc/ByteArrayLexerSource read ()I' bytes='10' count='5044'
backedge_count='1' iicount='10044' stamp='0.435'/>
<writer thread='4300214272'/>
<task_queued compile_id='23' method='java/util/HashMap hash (I)I' bytes='23' count='5000' backedge_count='1'
iicount='10000' stamp='0.442' comment='count' hot_count='10000'/>
<writer thread='4425007104'/>
<nmethod compile_id='23' compiler='C2' entry='4345887808' size='440' address='4345887504'
relocation_offset='288' insts_offset='304' stub_offset='368' scopes_data_offset='392' scopes_pcs_offset='400'
dependencies_offset='432' method='java/util/HashMap hash (I)I' bytes='23' count='5039' backedge_count='1'
iicount='10039' stamp='0.442'/>
<writer thread='4300214272'/>
<dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource'
x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource'
stamp='0.456'/>
<dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource'
x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource'
stamp='0.456'/>
<dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource'
x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource'
stamp='0.456'/>
<dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource'
x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource'
stamp='0.456'/>
$ java -jar logc.jar hotspot.log
1    java.lang.String::hashCode (67 bytes)
2    Accumulator::addSqrt (7 bytes)
3    Accumulator::sqrt (6 bytes)
$ java -jar logc.jar hotspot.log
1    java.lang.String::hashCode (67 bytes)
2    Accumulator::addSqrt (7 bytes)
    @ 2 Accumulator::sqrt (6 bytes) (end time: 0.0660 nodes: 36)
      @ 2 java.lang.Math::sqrt (5 bytes)
3    Accumulator::sqrt (6 bytes)
    @ 2 java.lang.Math::sqrt (5 bytes)
8     sun.nio.cs.UTF_8$Encoder::encode (361 bytes)
6 uncommon trap null_check make_not_entrant
   @8 java/lang/String equals (Ljava/lang/Object;)Z
6 make_not_entrant
9     java.lang.String::equals (88 bytes)
10     java.util.LinkedList::indexOf (73 bytes)
Hotspot sees it’s 100% String
   10     java.util.LinkedList::indexOf (73 bytes)
        @ 52 java.lang.Object::equals (11 bytes)
          type profile java/lang/Object -> java/lang/String (100%)
        @ 52 java.lang.String::equals (88 bytes)
   11     java.lang.String::indexOf (87 bytes)
        @ 83 java.lang.String::indexOfSupplementary too big




                              Too big to inline! Could be bad?
Intrinsic?

• Known to the JIT
 • Don’t inline bytecode
 • Do insert “best” native code
   • e.g. kernel-level memory operation
   • e.g. optimized sqrt in machine code
$ java -XX:+UnlockDiagnosticVMOptions 
>       -XX:+PrintInlining 
>       -XX:+PrintCompilation 
>       Accumulator 10000
     53     1             java.lang.String::hashCode (67 bytes)
     65     2             Accumulator::addSqrt (7 bytes)
            @ 3   Accumulator::sqrt (6 bytes)    inline (hot)
              @ 2   java.lang.Math::sqrt (5 bytes)    (intrinsic)
     65     3             Accumulator::sqrt (6 bytes)
            @ 2   java.lang.Math::sqrt (5 bytes)    (intrinsic)
666616.4591971082

                                Calls treated specially by JIT
Common Intrinsics
• String#equals
• Most (all?) Math methods
• System.arraycopy
• Object#hashCode
• Object#getClass
• sun.misc.Unsafe methods
Did someone say
MACHINE CODE?!
The Red Pill

• Knowing code compiles is good
• Knowing code inlines is better
• Seeing the actual assembly is best!
Caveat


• I don’t really know assembly.
• But I fake it really well.
Print Assembly

• -XX:+PrintAssembly
• Google “hotspot printassembly”
• http://wikis.sun.com/display/
  HotSpotInternals/PrintAssembly
• Assembly-dumping plugin for Hotspot
Alternative

• -XX:+PrintOptoAssembly
• Only in debug/fastdebug builds
• Not as pretty
Wednesday, July 27, 2011




    ~/oscon ! java -XX:+UnlockDiagnosticVMOptions 
    >              -XX:+PrintAssembly 
    >              Accumulator 10000
    OpenJDK 64-Bit Server VM warning: PrintAssembly is enabled;
    turning on DebugNonSafepoints to gain additional output
    Loaded disassembler from hsdis-amd64.dylib
    ...
Decoding compiled method 11343cbd0:
Code:
[Disassembling for mach='i386:x86-64']
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} 'add' '(II)I' in 'Accumulator'
  # parm0:    rsi        = int
  # parm1:    rdx        = int
  #           [sp+0x20] (sp of caller)
  11343cd00: push   %rbp
  11343cd01: sub    $0x10,%rsp
  11343cd05: nop                              ;*synchronization entry
                                              ; - Accumulator::add@-1 (line 16)
  11343cd06: mov    %esi,%eax
  11343cd08: add    %edx,%eax                 ;*iadd
                                              ; - Accumulator::add@2 (line 16)
  11343cd0a: add    $0x10,%rsp
  11343cd0e: pop    %rbp
  11343cd0f: test   %eax,-0x1303fd15(%rip)      # 1003fd000
                                              ;   {poll_return}
  11343cd15: retq
Woah there buddy...
x86_64 Assembly 101
       add                Two’s complement add
       sub                        ...subtract
      mov*                Move data from a to b
       jmp                            goto
je, jne, jl, jge, ...     Jump if ==, !=, <, >=, ...
   push, pop               Call stack operations
   call*, ret*          Call, return from subroutine
eax, ebx, esi, ...              32-bit registers
rax, rbx, rsi, ...              64-bit registers
Register Machine

• Instead of stack moves, we have “slots”
• Move data into slots
• Trigger operations that manipulate data
• Get new data out of slots
• JVM stack, locals end up as register ops
Stack?

• Native code has a stack too
 • Maintains registers from call to call
• Various calling conventions
 • Caller saves registers?
 • Callee saves registers?
Decoding compiled method 11343cbd0:           <= address of new compiled code
Code:
[Disassembling for mach='i386:x86-64']        <= architecture
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} 'add' '(II)I' in 'Accumulator'   <=   method, signature, class
  # parm0:    rsi       = int                 <=   first parm to method goes in rsi
  # parm1:    rdx       = int                 <=   second parm goes in rdx
  #           [sp+0x20] (sp of caller)        <=   caller’s pointer into native stack
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



 rbp points at current stack frame, so we save it off.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



     Two args, so we bump stack pointer by 0x10.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



          Do nothing, e.g. to memory-align code.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq

     At the “-1” instruction of our add() method...
                     i.e. here we go!
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



                       Move parm1 into eax.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



       Add parm0 and parm1, store result in eax.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



 How nice, Hotspot shows us this is our “iadd” op!
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



            Put stack pointer back where it was.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



                     Restore rbp from stack.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



   Poll a “safepoint”...give JVM a chance to GC, etc.
11343cd00: push   %rbp
11343cd01: sub    $0x10,%rsp
11343cd05: nop                             ;*synchronization entry
                                           ; - Accumulator::add@-1 (line 16)
11343cd06: mov    %esi,%eax
11343cd08: add    %edx,%eax                ;*iadd
                                           ; - Accumulator::add@2 (line 16)
11343cd0a: add    $0x10,%rsp
11343cd0e: pop    %rbp
11343cd0f: test   %eax,-0x1303fd15(%rip)     # 1003fd000
                                           ;   {poll_return}
11343cd15: retq



                                 All done!
Things to Watch For

• CALL operations
 • Indicates something failed to inline
• LOCK operations
 • Cache-busting, e.g. volatility
CALL
  1134858f5: xchg    %ax,%ax
  1134858f7: callq   113414aa0   ; OopMap{off=316}
                                 ;*invokespecial addAsBignum
                                 ; - org.jruby.RubyFixnum::addFixnum@29 (line 348)
                                 ;   {optimized virtual_call}
  1134858fc: jmpq    11348586d




Ruby integer adds might overflow into Bignum, leading to
addAsBignum call. In this case, it’s never called, so Hotspot
          emits callq assuming we won’t hit it.
LOCK
Code from a RubyBasicObject’s default constructor.
11345d823: mov    0x70(%r8),%r9d    ;*getstatic NULL_OBJECT_ARRAY
                                    ; - org.jruby.RubyBasicObject::<init>@5 (line 76)
                                    ; - org.jruby.RubyObject::<init>@2 (line 118)
                                    ; - org.jruby.RubyNumeric::<init>@2 (line 111)
                                    ; - org.jruby.RubyInteger::<init>@2 (line 95)
                                    ; - org.jruby.RubyFixnum::<init>@5 (line 112)
                                    ; - org.jruby.RubyFixnum::newFixnum@25 (line 173)
11345d827: mov    %r9d,0x14(%rax)
11345d82b: lock addl $0x0,(%rsp)    ;*putfield varTable
                                    ; - org.jruby.RubyBasicObject::<init>@8 (line 76)
                                    ; - org.jruby.RubyObject::<init>@2 (line 118)
                                    ; - org.jruby.RubyNumeric::<init>@2 (line 111)
                                    ; - org.jruby.RubyInteger::<init>@2 (line 95)
                                    ; - org.jruby.RubyFixnum::<init>@5 (line 112)
                                    ; - org.jruby.RubyFixnum::newFixnum@25 (line 173)


Why are we doing a volatile write in the constructor?
LOCK
public class RubyBasicObject ... {
    private static final boolean DEBUG = false;
    private static final Object[] NULL_OBJECT_ARRAY = new Object[0];

    // The class of this object
    protected transient RubyClass metaClass;

    // zeroed by jvm
    protected int flags;

    // variable table, lazily allocated as needed (if needed)
    private volatile Object[] varTable = NULL_OBJECT_ARRAY;



 Maybe it’s not such a good idea to pre-init a volatile?
LOCK

~/projects/jruby ! git log 2f935de1e40bfd8b29b3a74eaed699e519571046 -1 | cat
commit 2f935de1e40bfd8b29b3a74eaed699e519571046
Author: Charles Oliver Nutter <headius@headius.com>
Date:   Tue Jun 14 02:59:41 2011 -0500

    Do not eagerly initialize volatile varTable field in RubyBasicObject;
speeds object creation significantly.




   LEVEL UP!
invokedynamic?

• Largely, it works the same
 • MethodHandles optimize to x86 asm
 • Inlining as normal
• Performance nearly the same as static!
• And that’s exactly the point!
What Have We Learned?

 • How Hotspot’s JIT works
 • How to monitor the JIT
 • How to find problems
 • How to fix problems we find
What We Missed

• Tuning GC settings in JVM
• Monitoring GC with VisualVM
 • Google ‘visualgc’...it’s awesome
You’re no dummy now!
          ;-)
Thank you!

• headius@headius.com, @headius
• http://blog.headius.com
• “java virtual machine specification”
• “jvm opcodes”

More Related Content

What's hot

Do we need Unsafe in Java?
Do we need Unsafe in Java?Do we need Unsafe in Java?
Do we need Unsafe in Java?Andrei Pangin
 
Embulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderEmbulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderSadayuki Furuhashi
 
JVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir IvanovJVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir IvanovZeroTurnaround
 
Intrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMIntrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMKris Mok
 
Cours système d’exploitation partie1
Cours système d’exploitation partie1Cours système d’exploitation partie1
Cours système d’exploitation partie1manou2008
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to CeleryIdan Gazit
 
すごい配列楽しく学ぼう
すごい配列楽しく学ぼうすごい配列楽しく学ぼう
すごい配列楽しく学ぼうxenophobia__
 
ビットバンクで求められるプロジェクトマネジメント
ビットバンクで求められるプロジェクトマネジメントビットバンクで求められるプロジェクトマネジメント
ビットバンクで求められるプロジェクトマネジメントbitbank, Inc. Tokyo, Japan
 
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020Johnny Sung
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.jsYoshiiro Ueno
 
Allaitement et diversification1
Allaitement et diversification1Allaitement et diversification1
Allaitement et diversification1rabah zerrouki
 
Obésité chez les enfants
Obésité chez les enfantsObésité chez les enfants
Obésité chez les enfantsfatimasleiman3
 
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013Ryo Sakamoto
 
Woo: Writing a fast web server @ ELS2015
Woo: Writing a fast web server @ ELS2015Woo: Writing a fast web server @ ELS2015
Woo: Writing a fast web server @ ELS2015fukamachi
 
Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfacesFranck SIMON
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Roman Elizarov
 
JavaScript難読化読経
JavaScript難読化読経JavaScript難読化読経
JavaScript難読化読経Yosuke HASEGAWA
 

What's hot (20)

Do we need Unsafe in Java?
Do we need Unsafe in Java?Do we need Unsafe in Java?
Do we need Unsafe in Java?
 
Embulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderEmbulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loader
 
Halide for Memory
Halide for MemoryHalide for Memory
Halide for Memory
 
JVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir IvanovJVM JIT compilation overview by Vladimir Ivanov
JVM JIT compilation overview by Vladimir Ivanov
 
Intrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMIntrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VM
 
Cours système d’exploitation partie1
Cours système d’exploitation partie1Cours système d’exploitation partie1
Cours système d’exploitation partie1
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to Celery
 
How2heap
How2heap How2heap
How2heap
 
すごい配列楽しく学ぼう
すごい配列楽しく学ぼうすごい配列楽しく学ぼう
すごい配列楽しく学ぼう
 
ビットバンクで求められるプロジェクトマネジメント
ビットバンクで求められるプロジェクトマネジメントビットバンクで求められるプロジェクトマネジメント
ビットバンクで求められるプロジェクトマネジメント
 
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js
 
Algorithmes de tri
Algorithmes de triAlgorithmes de tri
Algorithmes de tri
 
Allaitement et diversification1
Allaitement et diversification1Allaitement et diversification1
Allaitement et diversification1
 
Obésité chez les enfants
Obésité chez les enfantsObésité chez les enfants
Obésité chez les enfants
 
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
 
Woo: Writing a fast web server @ ELS2015
Woo: Writing a fast web server @ ELS2015Woo: Writing a fast web server @ ELS2015
Woo: Writing a fast web server @ ELS2015
 
Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfaces
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
JavaScript難読化読経
JavaScript難読化読経JavaScript難読化読経
JavaScript難読化読経
 

Viewers also liked

sizeof(Object): how much memory objects take on JVMs and when this may matter
sizeof(Object): how much memory objects take on JVMs and when this may mattersizeof(Object): how much memory objects take on JVMs and when this may matter
sizeof(Object): how much memory objects take on JVMs and when this may matterDawid Weiss
 
Referring physicians presentation short
Referring physicians presentation shortReferring physicians presentation short
Referring physicians presentation shortAnthony DeSalvo
 
Java memory presentation
Java memory presentationJava memory presentation
Java memory presentationYury Bubnov
 
MQTT, Eclipse Paho and Java - Messaging for the Internet of Things
MQTT, Eclipse Paho and Java - Messaging for the Internet of ThingsMQTT, Eclipse Paho and Java - Messaging for the Internet of Things
MQTT, Eclipse Paho and Java - Messaging for the Internet of ThingsAndy Piper
 
Java Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and TuningJava Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and TuningCarol McDonald
 
Powering your next IoT application with MQTT - JavaOne 2014 tutorial
Powering your next IoT application with MQTT - JavaOne 2014 tutorialPowering your next IoT application with MQTT - JavaOne 2014 tutorial
Powering your next IoT application with MQTT - JavaOne 2014 tutorialBenjamin Cabé
 
Refactoring to Java 8 (Devoxx UK)
Refactoring to Java 8 (Devoxx UK)Refactoring to Java 8 (Devoxx UK)
Refactoring to Java 8 (Devoxx UK)Trisha Gee
 

Viewers also liked (10)

sizeof(Object): how much memory objects take on JVMs and when this may matter
sizeof(Object): how much memory objects take on JVMs and when this may mattersizeof(Object): how much memory objects take on JVMs and when this may matter
sizeof(Object): how much memory objects take on JVMs and when this may matter
 
Referring physicians presentation short
Referring physicians presentation shortReferring physicians presentation short
Referring physicians presentation short
 
Java memory presentation
Java memory presentationJava memory presentation
Java memory presentation
 
Java memory model
Java memory modelJava memory model
Java memory model
 
The Java memory model made easy
The Java memory model made easyThe Java memory model made easy
The Java memory model made easy
 
MQTT, Eclipse Paho and Java - Messaging for the Internet of Things
MQTT, Eclipse Paho and Java - Messaging for the Internet of ThingsMQTT, Eclipse Paho and Java - Messaging for the Internet of Things
MQTT, Eclipse Paho and Java - Messaging for the Internet of Things
 
Java Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and TuningJava Garbage Collection, Monitoring, and Tuning
Java Garbage Collection, Monitoring, and Tuning
 
Powering your next IoT application with MQTT - JavaOne 2014 tutorial
Powering your next IoT application with MQTT - JavaOne 2014 tutorialPowering your next IoT application with MQTT - JavaOne 2014 tutorial
Powering your next IoT application with MQTT - JavaOne 2014 tutorial
 
Refactoring to Java 8 (Devoxx UK)
Refactoring to Java 8 (Devoxx UK)Refactoring to Java 8 (Devoxx UK)
Refactoring to Java 8 (Devoxx UK)
 
Down the Rabbit Hole
Down the Rabbit HoleDown the Rabbit Hole
Down the Rabbit Hole
 

Similar to Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When You're Not Looking)

Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...
Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...
Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...Víctor Bolinches
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsAzul Systems, Inc.
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?Doug Hawkins
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/OJussi Pohjolainen
 
Tips and tricks for building high performance android apps using native code
Tips and tricks for building high performance android apps using native codeTips and tricks for building high performance android apps using native code
Tips and tricks for building high performance android apps using native codeKenneth Geisshirt
 
Blocks & GCD
Blocks & GCDBlocks & GCD
Blocks & GCDrsebbe
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevMattias Karlsson
 
ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...
ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...
ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...Muhammad Ulhaque
 
A topology of memory leaks on the JVM
A topology of memory leaks on the JVMA topology of memory leaks on the JVM
A topology of memory leaks on the JVMRafael Winterhalter
 
Down the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandDown the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandCharles Nutter
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015Charles Nutter
 
Ahead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java ApplicationsAhead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java ApplicationsNikita Lipsky
 
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers Nikita Lipsky
 

Similar to Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When You're Not Looking) (20)

Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...
Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...
Paradigma FP y OOP usando técnicas avanzadas de Programación | Programacion A...
 
Why learn Internals?
Why learn Internals?Why learn Internals?
Why learn Internals?
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/O
 
Tips and tricks for building high performance android apps using native code
Tips and tricks for building high performance android apps using native codeTips and tricks for building high performance android apps using native code
Tips and tricks for building high performance android apps using native code
 
Blocks & GCD
Blocks & GCDBlocks & GCD
Blocks & GCD
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
Java Language fundamental
Java Language fundamentalJava Language fundamental
Java Language fundamental
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from Oredev
 
ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...
ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...
ECSE 221 - Introduction to Computer Engineering - Tutorial 1 - Muhammad Ehtas...
 
A topology of memory leaks on the JVM
A topology of memory leaks on the JVMA topology of memory leaks on the JVM
A topology of memory leaks on the JVM
 
Down the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM WonderlandDown the Rabbit Hole: An Adventure in JVM Wonderland
Down the Rabbit Hole: An Adventure in JVM Wonderland
 
Java 7 LavaJUG
Java 7 LavaJUGJava 7 LavaJUG
Java 7 LavaJUG
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 
Ahead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java ApplicationsAhead-Of-Time Compilation of Java Applications
Ahead-Of-Time Compilation of Java Applications
 
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers
 
Jvm memory model
Jvm memory modelJvm memory model
Jvm memory model
 
Java
JavaJava
Java
 

More from Charles Nutter

The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018Charles Nutter
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Charles Nutter
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMCharles Nutter
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015Charles Nutter
 
Open Source Software Needs You!
Open Source Software Needs You!Open Source Software Needs You!
Open Source Software Needs You!Charles Nutter
 
InvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method HandlesInvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method HandlesCharles Nutter
 
Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Charles Nutter
 
Doing Open Source the Right Way
Doing Open Source the Right WayDoing Open Source the Right Way
Doing Open Source the Right WayCharles Nutter
 
Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014Charles Nutter
 
Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Charles Nutter
 
Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Charles Nutter
 
Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Charles Nutter
 
The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013Charles Nutter
 
High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013Charles Nutter
 
Invokedynamic in 45 Minutes
Invokedynamic in 45 MinutesInvokedynamic in 45 Minutes
Invokedynamic in 45 MinutesCharles Nutter
 
Invokedynamic: Tales from the Trenches
Invokedynamic: Tales from the TrenchesInvokedynamic: Tales from the Trenches
Invokedynamic: Tales from the TrenchesCharles Nutter
 
Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012Charles Nutter
 
Aloha RubyConf 2012 - JRuby
Aloha RubyConf 2012 - JRubyAloha RubyConf 2012 - JRuby
Aloha RubyConf 2012 - JRubyCharles Nutter
 
High Performance Ruby - Golden Gate RubyConf 2012
High Performance Ruby - Golden Gate RubyConf 2012High Performance Ruby - Golden Gate RubyConf 2012
High Performance Ruby - Golden Gate RubyConf 2012Charles Nutter
 

More from Charles Nutter (20)

The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVM
 
JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015JRuby 9000 - Taipei Ruby User's Group 2015
JRuby 9000 - Taipei Ruby User's Group 2015
 
Open Source Software Needs You!
Open Source Software Needs You!Open Source Software Needs You!
Open Source Software Needs You!
 
InvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method HandlesInvokeBinder: Fluent Programming for Method Handles
InvokeBinder: Fluent Programming for Method Handles
 
Over 9000: JRuby in 2015
Over 9000: JRuby in 2015Over 9000: JRuby in 2015
Over 9000: JRuby in 2015
 
Doing Open Source the Right Way
Doing Open Source the Right WayDoing Open Source the Right Way
Doing Open Source the Right Way
 
JRuby: The Hard Parts
JRuby: The Hard PartsJRuby: The Hard Parts
JRuby: The Hard Parts
 
Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014Bringing Concurrency to Ruby - RubyConf India 2014
Bringing Concurrency to Ruby - RubyConf India 2014
 
Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013
 
Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013Beyond JVM - YOW! Brisbane 2013
Beyond JVM - YOW! Brisbane 2013
 
Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013Beyond JVM - YOW Melbourne 2013
Beyond JVM - YOW Melbourne 2013
 
The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013The Future of JRuby - Baruco 2013
The Future of JRuby - Baruco 2013
 
High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013High Performance Ruby - E4E Conference 2013
High Performance Ruby - E4E Conference 2013
 
Invokedynamic in 45 Minutes
Invokedynamic in 45 MinutesInvokedynamic in 45 Minutes
Invokedynamic in 45 Minutes
 
Invokedynamic: Tales from the Trenches
Invokedynamic: Tales from the TrenchesInvokedynamic: Tales from the Trenches
Invokedynamic: Tales from the Trenches
 
Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012Why JRuby? - RubyConf 2012
Why JRuby? - RubyConf 2012
 
Aloha RubyConf 2012 - JRuby
Aloha RubyConf 2012 - JRubyAloha RubyConf 2012 - JRuby
Aloha RubyConf 2012 - JRuby
 
High Performance Ruby - Golden Gate RubyConf 2012
High Performance Ruby - Golden Gate RubyConf 2012High Performance Ruby - Golden Gate RubyConf 2012
High Performance Ruby - Golden Gate RubyConf 2012
 

Recently uploaded

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 

Recently uploaded (20)

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 

Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When You're Not Looking)

  • 1. What the JVM Does With Your Bytecode When Nobody’s Looking
  • 2. JVM JIT for Dummies And the rest of you, too.
  • 3. Intro • Charles Oliver Nutter • “JRuby Guy” • Sun Microsystems 2006-2009 • Engine Yard 2009- • Primarily responsible for compiler, perf • Lots of bytecode generation
  • 4. What We Won’t • GC tuning • GC monitoring with VisualVM • Google ‘visualgc’, it’s awesome
  • 5. What We Will Lean • How the JVM’s JIT works • Monitoring the JIT • Finding problems • Dumping assembly (don’t be scared!)
  • 6. JIT • Just-In-Time compilation • Compiled when needed • Maybe immediately before execution • ...or when we decide it’s important • ...or never?
  • 7. Mixed-Mode • Interpreted • Bytecode-walking • Artificial stack • Compiled • Direct native operations • Native registers, memory, etc
  • 8. Profiling • Gather data about code while interpreting • Invariants (types, constants, nulls) • Statistics (branches, calls) • Use that information to optimize • Educated guess?
  • 9. The Golden Rule of Optimization Don’t do unnecessary work.
  • 10. Optimization • Method inlining • Loop unrolling • Lock coarsening/eliding • Dead code elimination • Duplicate code elimination • Escape analysis
  • 11. Inlining? • Combine caller and callee into one unit • e.g. based on profile • Perhaps with a guard/test • Optimize as a whole • More code means better visibility
  • 12. Inlining int addAll(int max) { int accum = 0; for (int i = 0; i < max; i++) { accum = add(accum, i); } return accum; } int add(int a, int b) { return a + b; }
  • 13. Inlining int addAll(int max) { int accum = 0; for (int i = 0; i < max; i++) { accum = add(accum, i); } return accum; Only one target is ever seen } int add(int a, int b) { return a + b; }
  • 14. Inlining int addAll(int max) { int accum = 0; for (int i = 0; i < max; i++) { accum = accum + i; } return accum; Don’t bother making the call }
  • 15. Loop Unrolling • Works for small, constant loops • Avoid tests, branching • Allow inlining a single call as many
  • 16. Loop Unrolling private static final String[] options = { "yes", "no", "maybe"}; public void looper() { for (String option : options) { process(option); } } Small loop, constant stride, constant size
  • 17. Loop Unrolling private static final String[] options = { "yes", "no", "maybe"}; public void looper() { process(options[0]); process(options[1]); Unrolled! process(options[2]); }
  • 18. Lock Coarsening public void needsLocks() { for (option : options) { process(option); } Repeatedly locking } private synchronized String process(String option) { // some wacky thread-unsafe code }
  • 19. Lock Coarsening public void needsLocks() { Lock once synchronized (this) { for (option : options) { // some wacky thread-unsafe code } } }
  • 20. Lock Eliding public void overCautious() { Synchronize on List l = new ArrayList(); synchronized (l) { new Object for (option : options) { l.add(process(option)); } } } But we know it never escapes this thread...
  • 21. Lock Eliding public void overCautious() { List l = new ArrayList(); for (option : options) { l.add( /* process()’s code */); } } No need to lock
  • 22. Escape Analysis private static class Foo { public String a; public String b; Foo(String a, String b) { this.a = a; this.b = b; } }
  • 23. Escape Analysis public void bar() { Foo f = new Foo("Hello", "Øredev"); baz(f); } public void baz(Foo f) { Same object all System.out.print(f.a); System.out.print(", "); the way through quux(f); } Never “escapes” public void quux(Foo f) { these methods System.out.print(f.b); System.out.println('!'); }
  • 24. Escape Analysis public secret awesome inlinedBarBazQuux() { System.out.print("Hello"); System.out.print(", "); System.out.print("Øredev"); System.out.println('!'); } Don’t bother allocating Foo object!
  • 25. Perf Sinks • Memory accesses • By far the biggest expense • Calls • Memory ref + branch kills pipeline • Call stack, register juggling costs • Locks and volatile writes
  • 26. Volatile? • Each CPU maintains a memory cache • Caches may be out of sync • If it doesn’t matter, no problem • If it does matter, threads disagree! • Volatile forces synchronization of cache • Across cores and to main memory
  • 27. Call Site • The place where you make a call • Monomorphic (“one shape”) • Single target class • Bimorphic (“two shapes”) • Polymorphic (“many shapes”) • Megamorphic (“you’re screwed”)
  • 28. Blah.java System.currentTimeMillis(); // static, monomorphic List list1 = new ArrayList(); // constructor, monomorphic List list2 = new LinkedList(); for (List list : new List[]{ list1, list2 }) { list.add("hello"); // bimorphic } for (Object obj : new Object[]{ 'foo', list1, new Object() }) { obj.toString(); // polymorphic }
  • 29. Hotspot • -client mode (C1) inlines, less aggressive • Fewer opportunities to optimize • -server mode (C2) inlines aggressively • Based on richer runtime profiling • We’ll focus on this • Tiered mode combines them • -XX:+TieredCompilation
  • 30. C2 “server” Inlining • Profile to find “hot spots” • Call sites • Branch statistics • Profile until 10k calls • Inline mono/bimorphic calls • Other mechanisms for polymorphic calls
  • 31. Tuning Inlining • -XX:+MaxInlineSize=35 • Largest inlinable method (bytecode) • -XX:+InlineSmallCode=# • Largest inlinable compiled method • -XX:+FreqInlineSize=# • Largest frequently-called method...
  • 32. Tuning Inlining • -XX:+MaxInlineLevel=9 • How deep does the rabbit hole go? • -XX:+MaxRecursiveInlineLevel=# • Recursive inlining
  • 33. Now it gets fun!
  • 34. Monitoring the JIT • Dozens of flags • Reams of output • Always evolving • How can you understand it?
  • 35. public class Accumulator { public static void main(String[] args) { int max = Integer.parseInt(args[0]); System.out.println(addAll(max)); } static int addAll(int max) { int accum = 0; for (int i = 0; i < max; i++) { accum = add(accum, i); } return accum; } static int add(int a, int b) { return a + b; } }
  • 36. $ java -version openjdk version "1.7.0-b147" OpenJDK Runtime Environment (build 1.7.0- b147-20110927) OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode) $ javac Accumulator.java $ java Accumulator 1000 499500
  • 37. Print Compilation • -XX:+PrintCompilation • Print methods as they JIT • Class + name + size
  • 38. $ java -XX:+PrintCompilation Accumulator 1000 53 1 java.lang.String::hashCode (67 bytes) 499500
  • 39. $ java -XX:+PrintCompilation Accumulator 1000 53 1 java.lang.String::hashCode (67 bytes) 499500 Where’s our code?!?
  • 40. $ java -XX:+PrintCompilation Accumulator 1000 53 1 java.lang.String::hashCode (67 bytes) 499500 Where’s our code?!? Remember...10k calls before JIT
  • 41. 10k loop, 10k calls to add $ java -XX:+PrintCompilation Accumulator 10000 53 1 java.lang.String::hashCode (67 bytes) 64 2 Accumulator::add (4 bytes) 49995000 Hooray!
  • 42. But what’s this? $ java -XX:+PrintCompilation Accumulator 10000 53 1 java.lang.String::hashCode (67 bytes) 64 2 Accumulator::add (4 bytes) 49995000 Class loading, security logic, other stuff...
  • 43. Dear god...there’s zombies in my code?!? 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes)
  • 44. Dear god...there’s zombies in my code?!? 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes) Not entrant? What the heck?
  • 45. Optimistic Compilers • Assume profile is accurate • Aggressively optimize based on profile • Bail out if we’re wrong • ...and hope that we’re usually right
  • 46. Deoptimization • Bail out of running code • Monitoring flags describe process • “uncommon trap” - we were wrong • “not entrant” - don’t let new calls enter • “zombie” - on its way to deadness
  • 47. No JIT At All? • Code is too big • Code isn’t called enough
  • 48. That looks exciting! 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes)
  • 49. Exception handling in here (boring!) 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes)
  • 50. What’s this “n” all about? 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes)
  • 51. This method is native...maybe “intrinsic” 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes) We’ll come back to that...
  • 52. And this one? 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes) Method has been replaced while running (OSR)
  • 53. Millis from JVM start 1401 70 java.util.concurrent.ConcurrentHashMap::hash (49 bytes) 1412 71 java.lang.String::indexOf (7 bytes) 1420 72 ! java.io.BufferedReader::readLine (304 bytes) 1420 73 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (543 bytes) 1422 42 java.util.zip.ZipCoder::getBytes (192 bytes) made not entrant 1435 74 n java.lang.Object::hashCode (0 bytes) 1443 29 ! sun.misc.URLClassPath$JarLoader::getResource (91 bytes) made zombie 1443 25 sun.misc.URLClassPath::getResource (74 bytes) made zombie 1443 36 sun.misc.URLClassPath::getResource (74 bytes) made not entrant 1443 43 java.util.zip.ZipCoder::encoder (35 bytes) made not entrant 1449 75 java.lang.String::endsWith (15 bytes) 1631 1 % sun.misc.URLClassPath::getResource @ 39 (74 bytes) 1665 76 java.lang.ClassLoader::checkName (43 bytes) Sequence number of compilation
  • 54. Print Inlining • -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining • Display hierarchy of inlined methods • Include reasons for not inlining • More, better output on OpenJDK 7
  • 55. $ java -XX:+UnlockDiagnosticVMOptions > -XX:+PrintInlining > Accumulator 10000 49995000
  • 56. $ java -XX:+UnlockDiagnosticVMOptions > -XX:+PrintInlining > Accumulator 10000 49995000 Um...I don’t see anything inlining
  • 57. public class Accumulator { public static void main(String[] args) { int max = Integer.parseInt(args[0]); System.out.println(addAll(max)); } static int addAll(int max) { Called only once int accum = 0; for (int i = 0; i < max; i++) { accum = add(accum, i); } return accum; } static int add(int a, int b) { return a + b; } }
  • 58. public class Accumulator { public static void main(String[] args) { int max = Integer.parseInt(args[0]); System.out.println(addAll(max)); } static int addAll(int max) { Called only once int accum = 0; for (int i = 0; i < max; i++) { accum = add(accum, i); } return accum; Called 10k times } static int add(int a, int b) { return a + b; } }
  • 59. public class Accumulator { public static void main(String[] args) { int max = Integer.parseInt(args[0]); System.out.println(addAll(max)); } static int addAll(int max) { Called only once int accum = 0; for (int i = 0; i < max; i++) { accum = add(accum, i); } return accum; Called 10k times } static int add(int a, int b) { JITs as expected return a + b; } }
  • 60. public class Accumulator { public static void main(String[] args) { int max = Integer.parseInt(args[0]); System.out.println(addAll(max)); } static int addAll(int max) { Called only once int accum = 0; for (int i = 0; i < max; i++) { accum = add(accum, i); } return accum; Called 10k times } static int add(int a, int b) { JITs as expected return a + b; } } But makes no calls!
  • 61. static double addAllSqrts(int max) { double accum = 0; for (int i = 0; i < max; i++) { accum = addSqrt(accum, i); } return accum; } static int addSqrt(double a, int b) { return a + sqrt(b); } static double sqrt(int a) { return Math.sqrt(b); }
  • 62. $ java -XX:+UnlockDiagnosticVMOptions > -XX:+PrintInlining > -XX:+PrintCompilation > Accumulator 10000 53 1 java.lang.String::hashCode (67 bytes) 65 2 Accumulator::addSqrt (7 bytes) @ 3 Accumulator::sqrt (6 bytes) inline (hot) @ 2 java.lang.Math::sqrt (5 bytes) (intrinsic) 65 3 Accumulator::sqrt (6 bytes) @ 2 java.lang.Math::sqrt (5 bytes) (intrinsic) 666616.4591971082
  • 63. $ java -XX:+UnlockDiagnosticVMOptions > -XX:+PrintInlining HOT HOT HOT! > -XX:+PrintCompilation > Accumulator 10000 53 1 java.lang.String::hashCode (67 bytes) 65 2 Accumulator::addSqrt (7 bytes) @ 3 Accumulator::sqrt (6 bytes) inline (hot) @ 2 java.lang.Math::sqrt (5 bytes) (intrinsic) 65 3 Accumulator::sqrt (6 bytes) @ 2 java.lang.Math::sqrt (5 bytes) (intrinsic) 666616.4591971082
  • 64. LogCompilation • -XX:+LogCompilation • Worst. XML. Evar. • <JDK>/hotspot/src/share/tools/LogCompilation • or http://github.com/headius/logc
  • 65. scopes_pcs_offset='1384' dependencies_offset='1576' handler_table_offset='1592' nul_chk_table_offset='1736' oops_offset='992' method='org/jruby/lexer/yacc/ByteArrayLexerSource$ByteArrayCursor read ()I' bytes='49' count='5296' backedge_count='1' iicount='10296' stamp='0.412'/> <writer thread='4425007104'/> <nmethod compile_id='21' compiler='C2' entry='4345862528' size='1152' address='4345862160' relocation_offset='288' insts_offset='368' stub_offset='688' scopes_data_offset='840' scopes_pcs_offset='904' dependencies_offset='1016' handler_table_offset='1032' oops_offset='784' method='org/jruby/lexer/yacc/ ByteArrayLexerSource forward (I)I' bytes='111' count='5296' backedge_count='1' iicount='10296' stamp='0.412'/> <writer thread='4300214272'/> <task_queued compile_id='22' method='org/jruby/lexer/yacc/ByteArrayLexerSource read ()I' bytes='10' count='5000' backedge_count='1' iicount='10000' stamp='0.433' comment='count' hot_count='10000'/> <writer thread='4426067968'/> <nmethod compile_id='22' compiler='C2' entry='4345885984' size='1888' address='4345885584' relocation_offset='288' insts_offset='400' stub_offset='912' scopes_data_offset='1104' scopes_pcs_offset='1496' dependencies_offset='1704' handler_table_offset='1720' nul_chk_table_offset='1864' oops_offset='1024' method='org/jruby/lexer/yacc/ByteArrayLexerSource read ()I' bytes='10' count='5044' backedge_count='1' iicount='10044' stamp='0.435'/> <writer thread='4300214272'/> <task_queued compile_id='23' method='java/util/HashMap hash (I)I' bytes='23' count='5000' backedge_count='1' iicount='10000' stamp='0.442' comment='count' hot_count='10000'/> <writer thread='4425007104'/> <nmethod compile_id='23' compiler='C2' entry='4345887808' size='440' address='4345887504' relocation_offset='288' insts_offset='304' stub_offset='368' scopes_data_offset='392' scopes_pcs_offset='400' dependencies_offset='432' method='java/util/HashMap hash (I)I' bytes='23' count='5039' backedge_count='1' iicount='10039' stamp='0.442'/> <writer thread='4300214272'/> <dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource' x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource' stamp='0.456'/> <dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource' x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource' stamp='0.456'/> <dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource' x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource' stamp='0.456'/> <dependency_failed type='abstract_with_unique_concrete_subtype' ctxk='org/jruby/lexer/yacc/LexerSource' x='org/jruby/lexer/yacc/ByteArrayLexerSource' witness='org/jruby/lexer/yacc/InputStreamLexerSource' stamp='0.456'/>
  • 66. $ java -jar logc.jar hotspot.log 1 java.lang.String::hashCode (67 bytes) 2 Accumulator::addSqrt (7 bytes) 3 Accumulator::sqrt (6 bytes)
  • 67. $ java -jar logc.jar hotspot.log 1 java.lang.String::hashCode (67 bytes) 2 Accumulator::addSqrt (7 bytes) @ 2 Accumulator::sqrt (6 bytes) (end time: 0.0660 nodes: 36) @ 2 java.lang.Math::sqrt (5 bytes) 3 Accumulator::sqrt (6 bytes) @ 2 java.lang.Math::sqrt (5 bytes)
  • 68. 8 sun.nio.cs.UTF_8$Encoder::encode (361 bytes) 6 uncommon trap null_check make_not_entrant @8 java/lang/String equals (Ljava/lang/Object;)Z 6 make_not_entrant 9 java.lang.String::equals (88 bytes) 10 java.util.LinkedList::indexOf (73 bytes)
  • 69. Hotspot sees it’s 100% String 10 java.util.LinkedList::indexOf (73 bytes) @ 52 java.lang.Object::equals (11 bytes) type profile java/lang/Object -> java/lang/String (100%) @ 52 java.lang.String::equals (88 bytes) 11 java.lang.String::indexOf (87 bytes) @ 83 java.lang.String::indexOfSupplementary too big Too big to inline! Could be bad?
  • 70. Intrinsic? • Known to the JIT • Don’t inline bytecode • Do insert “best” native code • e.g. kernel-level memory operation • e.g. optimized sqrt in machine code
  • 71. $ java -XX:+UnlockDiagnosticVMOptions > -XX:+PrintInlining > -XX:+PrintCompilation > Accumulator 10000 53 1 java.lang.String::hashCode (67 bytes) 65 2 Accumulator::addSqrt (7 bytes) @ 3 Accumulator::sqrt (6 bytes) inline (hot) @ 2 java.lang.Math::sqrt (5 bytes) (intrinsic) 65 3 Accumulator::sqrt (6 bytes) @ 2 java.lang.Math::sqrt (5 bytes) (intrinsic) 666616.4591971082 Calls treated specially by JIT
  • 72. Common Intrinsics • String#equals • Most (all?) Math methods • System.arraycopy • Object#hashCode • Object#getClass • sun.misc.Unsafe methods
  • 74.
  • 75.
  • 76. The Red Pill • Knowing code compiles is good • Knowing code inlines is better • Seeing the actual assembly is best!
  • 77. Caveat • I don’t really know assembly. • But I fake it really well.
  • 78. Print Assembly • -XX:+PrintAssembly • Google “hotspot printassembly” • http://wikis.sun.com/display/ HotSpotInternals/PrintAssembly • Assembly-dumping plugin for Hotspot
  • 79. Alternative • -XX:+PrintOptoAssembly • Only in debug/fastdebug builds • Not as pretty
  • 80. Wednesday, July 27, 2011 ~/oscon ! java -XX:+UnlockDiagnosticVMOptions > -XX:+PrintAssembly > Accumulator 10000 OpenJDK 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output Loaded disassembler from hsdis-amd64.dylib ...
  • 81. Decoding compiled method 11343cbd0: Code: [Disassembling for mach='i386:x86-64'] [Entry Point] [Verified Entry Point] [Constants] # {method} 'add' '(II)I' in 'Accumulator' # parm0: rsi = int # parm1: rdx = int # [sp+0x20] (sp of caller) 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq
  • 83. x86_64 Assembly 101 add Two’s complement add sub ...subtract mov* Move data from a to b jmp goto je, jne, jl, jge, ... Jump if ==, !=, <, >=, ... push, pop Call stack operations call*, ret* Call, return from subroutine eax, ebx, esi, ... 32-bit registers rax, rbx, rsi, ... 64-bit registers
  • 84. Register Machine • Instead of stack moves, we have “slots” • Move data into slots • Trigger operations that manipulate data • Get new data out of slots • JVM stack, locals end up as register ops
  • 85. Stack? • Native code has a stack too • Maintains registers from call to call • Various calling conventions • Caller saves registers? • Callee saves registers?
  • 86. Decoding compiled method 11343cbd0: <= address of new compiled code Code: [Disassembling for mach='i386:x86-64'] <= architecture [Entry Point] [Verified Entry Point] [Constants] # {method} 'add' '(II)I' in 'Accumulator' <= method, signature, class # parm0: rsi = int <= first parm to method goes in rsi # parm1: rdx = int <= second parm goes in rdx # [sp+0x20] (sp of caller) <= caller’s pointer into native stack
  • 87. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq rbp points at current stack frame, so we save it off.
  • 88. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq Two args, so we bump stack pointer by 0x10.
  • 89. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq Do nothing, e.g. to memory-align code.
  • 90. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq At the “-1” instruction of our add() method... i.e. here we go!
  • 91. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq Move parm1 into eax.
  • 92. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq Add parm0 and parm1, store result in eax.
  • 93. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq How nice, Hotspot shows us this is our “iadd” op!
  • 94. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq Put stack pointer back where it was.
  • 95. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq Restore rbp from stack.
  • 96. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq Poll a “safepoint”...give JVM a chance to GC, etc.
  • 97. 11343cd00: push %rbp 11343cd01: sub $0x10,%rsp 11343cd05: nop ;*synchronization entry ; - Accumulator::add@-1 (line 16) 11343cd06: mov %esi,%eax 11343cd08: add %edx,%eax ;*iadd ; - Accumulator::add@2 (line 16) 11343cd0a: add $0x10,%rsp 11343cd0e: pop %rbp 11343cd0f: test %eax,-0x1303fd15(%rip) # 1003fd000 ; {poll_return} 11343cd15: retq All done!
  • 98. Things to Watch For • CALL operations • Indicates something failed to inline • LOCK operations • Cache-busting, e.g. volatility
  • 99. CALL 1134858f5: xchg %ax,%ax 1134858f7: callq 113414aa0 ; OopMap{off=316} ;*invokespecial addAsBignum ; - org.jruby.RubyFixnum::addFixnum@29 (line 348) ; {optimized virtual_call} 1134858fc: jmpq 11348586d Ruby integer adds might overflow into Bignum, leading to addAsBignum call. In this case, it’s never called, so Hotspot emits callq assuming we won’t hit it.
  • 100. LOCK Code from a RubyBasicObject’s default constructor. 11345d823: mov 0x70(%r8),%r9d ;*getstatic NULL_OBJECT_ARRAY ; - org.jruby.RubyBasicObject::<init>@5 (line 76) ; - org.jruby.RubyObject::<init>@2 (line 118) ; - org.jruby.RubyNumeric::<init>@2 (line 111) ; - org.jruby.RubyInteger::<init>@2 (line 95) ; - org.jruby.RubyFixnum::<init>@5 (line 112) ; - org.jruby.RubyFixnum::newFixnum@25 (line 173) 11345d827: mov %r9d,0x14(%rax) 11345d82b: lock addl $0x0,(%rsp) ;*putfield varTable ; - org.jruby.RubyBasicObject::<init>@8 (line 76) ; - org.jruby.RubyObject::<init>@2 (line 118) ; - org.jruby.RubyNumeric::<init>@2 (line 111) ; - org.jruby.RubyInteger::<init>@2 (line 95) ; - org.jruby.RubyFixnum::<init>@5 (line 112) ; - org.jruby.RubyFixnum::newFixnum@25 (line 173) Why are we doing a volatile write in the constructor?
  • 101. LOCK public class RubyBasicObject ... { private static final boolean DEBUG = false; private static final Object[] NULL_OBJECT_ARRAY = new Object[0]; // The class of this object protected transient RubyClass metaClass; // zeroed by jvm protected int flags; // variable table, lazily allocated as needed (if needed) private volatile Object[] varTable = NULL_OBJECT_ARRAY; Maybe it’s not such a good idea to pre-init a volatile?
  • 102. LOCK ~/projects/jruby ! git log 2f935de1e40bfd8b29b3a74eaed699e519571046 -1 | cat commit 2f935de1e40bfd8b29b3a74eaed699e519571046 Author: Charles Oliver Nutter <headius@headius.com> Date: Tue Jun 14 02:59:41 2011 -0500 Do not eagerly initialize volatile varTable field in RubyBasicObject; speeds object creation significantly. LEVEL UP!
  • 103. invokedynamic? • Largely, it works the same • MethodHandles optimize to x86 asm • Inlining as normal • Performance nearly the same as static! • And that’s exactly the point!
  • 104. What Have We Learned? • How Hotspot’s JIT works • How to monitor the JIT • How to find problems • How to fix problems we find
  • 105. What We Missed • Tuning GC settings in JVM • Monitoring GC with VisualVM • Google ‘visualgc’...it’s awesome
  • 106. You’re no dummy now! ;-)
  • 107. Thank you! • headius@headius.com, @headius • http://blog.headius.com • “java virtual machine specification” • “jvm opcodes”

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n