Upgrade to Pro — share decks privately, control downloads, hide ads and more …

History of a Value or Storia di un ImpieDato

History of a Value or Storia di un ImpieDato

A glimpse into the future of the JVM

Edoardo Vacchi

May 03, 2018
Tweet

More Decks by Edoardo Vacchi

Other Decks in Programming

Transcript

  1. About me • Edoardo Vacchi – @evacchi – Language Implementation

    Frameworks @ UniMi (+Mate) – Distributed and High-Performance Streaming @ UniCredit R&D – Currently Drools & JBPM team @ Red Hat
  2. High Performance Streaming • Market Prices • Different from Reactive

    Streams • Performance – e.g. cache locality • X-Language Interop – Multi-lang analytics platform – Possibly, interface with HW
  3. Making a Point{} struct Point { double x; double y;

    }; auto p = Point{1.0, 2.0}; Point ps[] = { Point{1.0, 2.0}, Point{1.1, 2.1}, Point{2.0, 3.0} };
  4. Making a new Point() public class Point { public double

    x; public double y; public Point(double x_, double y_) { x = x_; y = y_; } } var p = new Point(1.0, 2.0); Point[] ps = { new Point(1.0, 2.0), new Point(1.1, 2.1), new Point(2.0, 3.0), };
  5. Making a new Point() public class Point { public double

    x; public double y; public Point(double x_, double y_) { x = x_; y = y_; } } var p = new Point(1.0, 2.0); Point[] ps = new Point[] { new Point(1.0, 2.0), new Point(1.1, 2.1), new Point(2.0, 3.0), }; http://bit.ly/java-struct
  6. Memory Layout in C++ 1.0 2.0 1.1 2.1 2.0 3.0

    1 Point ps[] = { Point{…}, … }; 2 double* pps = (double*) ps; 3 pps[0] // 1.0 4 pps[1] // 2.0 5 pps[2] // 1.1 6 //. ps[1] ps[2] ps[3]
  7. Control over layout • Objects are 8 bytes aligned in

    memory (address A is K aligned if A % K == 0) • All felds are type-aligned (long/double is 8 aligned, integer/foat 4, short/char 2) • Fields are packed in the order of their size, except for references (last) Nitsan Wakart - Know Thy Java Object Memory Layout http://psy-lob-saw.blogspot.it/2013/05/know-thy-java-object-memory-layout.html
  8. Java Object Layout $ java -jar jol-cli/target/jol-cli.jar internals java.util.HashMap Running

    64-bit HotSpot VM. Using compressed oop with 3-bit shift. Using compressed klass with 3-bit shift. Objects are 8 bytes aligned. Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] java.util.HashMap object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 00 00 00 (0000 0101 0000 0000 0000 0000 0000 0000) 4 4 (object header) 00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000) 8 4 (object header) 8c 3b 00 f8 (1000 1100 0011 1011 0000 0000 1111 1000) 12 4 Set AbstractMap.keySet null 16 4 Collection AbstractMap.values null 20 4 int HashMap.size 0 24 4 int HashMap.modCount 0 28 4 int HashMap.threshold 0 32 4 float HashMap.loadFactor 0.75 36 4 Node[] HashMap.table null 40 4 Set HashMap.entrySet null 44 4 (loss due to the next object alignment) Instance size: 48 bytes (reported by Instrumentation API) Space losses: 0 bytes internal + 4 bytes external = 4 bytes total http://openjdk.java.net/projects/code-tools/jol/
  9. Projects • Metropolis. Java-on-Java & AOT • Loom. Lightweight Threads

    (Fibers) • GC. ZGC, Shenandoah, EpsilonGC • Valhalla. Value Types and Generic Specialization • Amber. Data Classes and pattern matching • Panama. Native Interop
  10. Valhalla • Codes like a class, works like an int

    • Allow representation of ubiquitous types currently not well supported on the JVM, including complex numbers, vector values, and tuples. • Avoid boxed types in generics
  11. Value-based classes • fnal and immutable • equals, hashCode, and

    toString solely from the instance's state and not from its identity • no use of identity-sensitive operations such as reference equality (==) between instances, identity hash code of instances, or synchronization on an instances's intrinsic lock; • equal solely based on equals(), not based on reference equality (==); • no accessible constructors, instead instantiated through factory methods which make no committment as to the identity of returned instances; • freely substitutable when equal
  12. Values • Pure data aggregates – Can’t extend other classes,

    cannot be extended – Can’t have felds of the type being declared (no recursion!) – Structural equality, not identity – No wait/notify – All fnal felds – Non-nullable
  13. Minimal Value Types • Let the VM derive a value

    class from a POJO – Annotated • Generate bytecode • Use MethodHandles to access the values
  14. Making a Point() @jvm.internal.value.ValueCapableClass final class Point { final double

    x; final double y; public Point(double x_, double y_) { x = x_; y = y_; } }
  15. var

  16. But really List<String> names = Collections.emptyList(); List<String> names = new

    ArrayList/>(); Consumer<String> consumer = s /> System.out.println(s); Consumer<String> consumer = System.out/:println;
  17. Pattern Matching String formatted = "unknown"; if (obj instanceof Integer)

    { int i = ((Integer) obj).intValue(); formatted = String.format("int %d", i); } if (obj matches Integer i) { formatted = String.format("int %d", i); }
  18. Pattern Matching String formatted = exprswitch (obj) { case Integer

    i /> String.format("int %d", i); case Byte b /> String.format("byte %d", b); case Long l /> String.format("long %d", l); case Double d /> String.format(“double %f", d); default /> String.format("String %s", s); };
  19. Data Classes record Point(int x, int y) { } //

    desugars to final class Point extends java.lang.DataClass { final int x; final int y; public Point(int x, int y) { this.x = x; this.y = y; } // destructuring pattern for Point(int x, int y) // state-based equals, hashCode, and toString // public read accessors x() and y() }
  20. Data Classes interface Shape { } record Point(int x, int

    y); record Rect(Point p1, Point p2) implements Shape; record Circle(Point center, int radius) implements Shape;
  21. Data Classes interface Node { } abstract record BinaryOpNode(Node left,

    Node right) implements Node; record PlusNode(Node left, Node right) extends BinaryOperatorNode(left, right); record MulNode(Node left, Node right) extends BinaryOperatorNode(left, right); record IntNode(int constant) implements Node;
  22. Pattern Matching int eval(Node n) { return switch(n) { case

    IntNode(int i) /> i; case NegNode(Node n) /> -eval(n); case AddNode(Node left, Node right) /> eval(left) + eval(right); case MulNode(Node left, Node right) /> eval(left) * eval(right); default: throw new IllegalStateException(n); }; } // nesting case AddNode(IntNode(0), Node right) /> //.
  23. Pattern Matching int eval(Node n) { return switch(n) { case

    IntNode(int i) /> i; case NegNode(var n) /> -eval(n); case AddNode(var left, var right) /> eval(left) + eval(right); case MulNode(var left, var right) /> eval(left) * eval(right); default /> throw new IllegalStateException(n); }; }
  24. Panama – Header fle extraction tools (Groveler) – Layout description

    language (LDL, Little Language) – Access to structured data on and off-heap – Native function calling from JVM to C/C++ – Intrinsic types to leverage CPU vector instructions
  25. Bonus the reason for diamond class Foo { Foo(X x)

    { } Foo get(X x) { return this; } } new Foo(1).get("");
  26. public class X<T> { public X(T t) {} public T

    get() { return null; } public static int f(String s) { return 1; } public static int f(Object o) { return 2; } public static void main(String[] args) { f(new X/>("").get()); // 1 f(new X("").get()); // 2 } } http://mail.openjdk.java.net/pipermail/coin-dev/2011-February/003082.html http://tronicek.blogspot.it/2011/03/do-we-really-need-in-diamond-operator.html
  27. If we were to add reifed generics to Java, it

    is very likely that we will have to support runtime raw types (!!) for backwards compatibility – so the syntactic distinction between diamond and raw turns out to be quite sweet. http://mail.openjdk.java.net/pipermail/coin-dev/2011-February/003083.html