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. History of a Value
    A glimpse into the future of the JVM

    View full-size slide

  2. About me
    Edoardo Vacchi – @evacchi

    View full-size slide

  3. About me

    Edoardo Vacchi – @evacchi
    – Language Implementation Frameworks @ UniMi (+Mate)
    – Distributed and High-Performance Streaming @ UniCredit R&D
    – Currently Drools & JBPM team @ Red Hat

    View full-size slide

  4. 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

    View full-size slide


  5. Control over memory allocation

    Control over memory layout
    – for performance
    – for interop

    View full-size slide

  6. 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}
    };

    View full-size slide

  7. 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),
    };

    View full-size slide

  8. 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

    View full-size slide

  9. Memory Layout
    header
    header
    x1
    y1
    header
    x2
    y2
    header
    x3
    y3
    Point[] ps =

    View full-size slide

  10. 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]

    View full-size slide

  11. 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

    View full-size slide

  12. 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/

    View full-size slide

  13. Memory Layout
    header
    x1
    y1
    x2
    y2
    x3
    y3
    Point[] ps =

    View full-size slide

  14. 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

    View full-size slide

  15. 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

    View full-size slide

  16. 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

    View full-size slide

  17. 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

    View full-size slide

  18. Values
    value Point {
    double x;
    double y;
    }

    View full-size slide

  19. Recursion
    value Node {
    int value;
    Node next;
    }

    View full-size slide

  20. Memory Layout
    header
    x1
    y1
    x2
    y2
    x3
    y3
    Point[] ps =

    View full-size slide

  21. Monomorphization

    View full-size slide

  22. class List { ... }

    View full-size slide

  23. List xs = …

    View full-size slide

  24. Minimal Value Types

    Let the VM derive a value class from a POJO
    – Annotated

    Generate bytecode

    Use MethodHandles to access the values

    View full-size slide

  25. 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_;
    }
    }

    View full-size slide

  26. The infamous bug 4459053

    View full-size slide

  27. The infamous bug 4459053

    View full-size slide

  28. But really
    List names = Collections.emptyList();
    List names = new ArrayList/>();
    Consumer consumer = s /> System.out.println(s);
    Consumer consumer = System.out/:println;

    View full-size slide

  29. 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);
    }

    View full-size slide

  30. 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);
    };

    View full-size slide

  31. Data Classes

    View full-size slide

  32. Data Classes
    record Point(int x, int y);

    View full-size slide

  33. 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()
    }

    View full-size slide

  34. 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;

    View full-size slide

  35. 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;

    View full-size slide

  36. 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) /> //.

    View full-size slide

  37. 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);
    };
    }

    View full-size slide

  38. Bonus chatter
    case IntNode(int i):
    break i;

    View full-size slide

  39. Going Native
    http://bit.ly/yt-going-native

    View full-size slide

  40. 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

    View full-size slide

  41. Bonus the reason for diamond
    class Foo {
    Foo(X x) { }
    Foo get(X x) { return this; }
    }
    new Foo(1).get("");

    View full-size slide

  42. public class X {
    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

    View full-size slide

  43. 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

    View full-size slide