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 Slide

  2. View Slide

  3. About me
    Edoardo Vacchi – @evacchi

    View Slide

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

  5. Motivation

    View Slide

  6. 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 Slide


  7. Control over memory allocation

    Control over memory layout
    – for performance
    – for interop

    View Slide

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

  9. 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 Slide

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

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

    View Slide

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

  13. 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 Slide

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

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

    View Slide

  16. View Slide

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

  18. View Slide

  19. Loom

    View Slide

  20. View Slide

  21. Valhalla

    View Slide

  22. 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 Slide

  23. 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 Slide

  24. OptionalInt

    View Slide

  25. 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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

  29. Monomorphization

    View Slide

  30. List

    View Slide

  31. List

    View Slide

  32. class List { ... }

    View Slide

  33. List xs = …

    View Slide

  34. Minimal Value Types

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

    Generate bytecode

    Use MethodHandles to access the values

    View Slide

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

  36. Amber

    View Slide

  37. var

    View Slide

  38. The infamous bug 4459053

    View Slide

  39. The infamous bug 4459053

    View Slide

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

    View Slide

  41. 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 Slide

  42. 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 Slide

  43. Data Classes

    View Slide

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

    View Slide

  45. 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 Slide

  46. 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 Slide

  47. 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 Slide

  48. 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 Slide

  49. 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 Slide

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

    View Slide

  51. Panama

    View Slide

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

    View Slide

  53. 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 Slide

  54. View Slide

  55. View Slide

  56. Q&
    A

    View Slide

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

    View Slide

  58. 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 Slide

  59. 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 Slide