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

Miniboxing presentation at ScalaDays 2014

Miniboxing presentation at ScalaDays 2014

Miniboxing presentation at ScalaDays 2014: http://scaladays.org/berlin2014/index.html

The recording is available on Parleys: https://www.parleys.com/tutorial/miniboxing-specialization-diet

Project website: http://scala-miniboxing.org

Vlad Ureche

June 17, 2014
Tweet

More Decks by Vlad Ureche

Other Decks in Programming

Transcript

  1. scala-miniboxing.org
    Miniboxing
    Miniboxing
    Fast Generics on the JVM
    ScalaDays, 18th of June 2014
    Vlad Ureche
    gh/twitter:@VladUreche

    View Slide

  2. 2
    scala-miniboxing.org
    class C[T](t: T)
    class C[T](t: T)

    View Slide

  3. 3
    scala-miniboxing.org
    class C[T](t: T)
    class C[T](t: T)
    scalac / javac

    View Slide

  4. 4
    scala-miniboxing.org
    class C(t: Object)
    class C(t: Object)
    class C[T](t: T)
    class C[T](t: T)
    scalac / javac

    View Slide

  5. 5
    scala-miniboxing.org
    class C(t: Object)
    class C(t: Object)
    class C[T](t: T)
    class C[T](t: T)
    The process is called erasure,
    and it replaces type paramerers
    by their upper bound
    scalac / javac

    View Slide

  6. 6
    scala-miniboxing.org
    class C(t: Object)
    class C(t: Object)
    Requires boxed primitive
    types (java.lang.Integer, ...)
    class C[T](t: T)
    class C[T](t: T)
    The process is called erasure,
    and it replaces type paramerers
    by their upper bound
    scalac / javac

    View Slide

  7. 7
    scala-miniboxing.org
    class C(t: Object)
    class C(t: Object)
    Requires boxed primitive
    types (java.lang.Integer, ...)
    class C[T](t: T)
    class C[T](t: T)
    The process is called erasure,
    and it replaces type paramerers
    by their upper bound
    scalac / javac
    You don't see it: scala.Int
    can be either int or j.l.Integer.
    Scalac does the work for you!

    View Slide

  8. 8
    scala-miniboxing.org
    class C(t: Object)
    class C(t: Object)
    Requires boxed primitive
    types (java.lang.Integer, ...)
    class C[T](t: T)
    class C[T](t: T)
    The process is called erasure,
    and it replaces type paramerers
    by their upper bound
    scalac / javac
    Yet boxing degrades performance
    - heap allocations / GC cycles ...
    - indirect reads, broken locality
    You don't see it: scala.Int
    can be either int or j.l.Integer.
    Scalac does the work for you!

    View Slide

  9. 9
    scala-miniboxing.org
    class C[T](t: T)
    class C[T](t: T)
    @specialized
    @specialized

    View Slide

  10. 10
    scala-miniboxing.org
    class C[T](t: T)
    class C[T](t: T)
    @miniboxed
    @miniboxed

    View Slide

  11. 11
    scala-miniboxing.org
    What is ?
    What is ?

    View Slide

  12. 12
    scala-miniboxing.org
    @miniboxed =

    View Slide

  13. 13
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =

    View Slide

  14. 14
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations

    View Slide

  15. 15
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat

    View Slide

  16. 16
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat
    opens the way to
    @miniboxed
    Scala collections

    View Slide

  17. 17
    scala-miniboxing.org
    @specialized
    @specialized

    View Slide

  18. 18
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)

    View Slide

  19. 19
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]

    View Slide

  20. 20
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]

    View Slide

  21. 21
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]
    new C[Int](4)

    View Slide

  22. 22
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]
    new C[Int](4) spec
    new C$mcI$sp(4)

    View Slide

  23. 23
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]
    new C[Int](4) spec
    new C$mcI$sp(4)
    Adapted to integers (t$mcI$sp: int)

    View Slide

  24. 24
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]
    new C[Int](4) spec
    new C$mcI$sp(4)
    Adapted to integers (t$mcI$sp: int)
    new C(“abc”)

    View Slide

  25. 25
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]
    new C[Int](4) spec
    new C$mcI$sp(4)
    Adapted to integers (t$mcI$sp: int)
    new C(“abc”) spec
    new C[String](“abc”)

    View Slide

  26. 26
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]
    new C[Int](4) spec
    new C$mcI$sp(4)
    * similar transformation for methods
    Adapted to integers (t$mcI$sp: int)
    new C(“abc”) spec
    new C[String](“abc”)

    View Slide

  27. 27
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    C[T]
    new C[Int](4) spec
    new C$mcI$sp(4)
    * similar transformation for methods
    Adapted to integers (t$mcI$sp: int)
    new C(“abc”) spec
    new C[String](“abc”)
    Can speed up
    certain code patterns
    by up to 20x

    View Slide

  28. 28
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat

    View Slide

  29. 29
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat

    duplicate fields

    broken inheriance

    View Slide

  30. 30
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)

    View Slide

  31. 31
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]

    View Slide

  32. 32
    scala-miniboxing.org
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others

    View Slide

  33. 33
    scala-miniboxing.org
    new C(“abc”) spec
    new C[String](“abc”)
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others

    View Slide

  34. 34
    scala-miniboxing.org
    new C(“abc”) spec
    new C[String](“abc”)
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    t: Object

    View Slide

  35. 35
    scala-miniboxing.org
    new C[Int](4) spec
    new C$mcI$sp(4)
    new C(“abc”) spec
    new C[String](“abc”)
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    t: Object

    View Slide

  36. 36
    scala-miniboxing.org
    new C[Int](4) spec
    new C$mcI$sp(4)
    new C(“abc”) spec
    new C[String](“abc”)
    t$mcI$sp: int
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    t: Object

    View Slide

  37. 37
    scala-miniboxing.org
    t$mcI$sp: int
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    t: Object

    View Slide

  38. 38
    scala-miniboxing.org
    t$mcI$sp: int
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    Carries two fields:

    t: Object

    t$mcI$sp: int
    t: Object

    View Slide

  39. 39
    scala-miniboxing.org
    t$mcI$sp: int
    class C[
    class C[@specialized
    @specialized T](t: T)
    T](t: T)
    C[T]
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    Carries two fields:

    t: Object

    t$mcI$sp: int
    That's bad:
    duplicate fields
    SI-3585
    t: Object

    View Slide

  40. 40
    scala-miniboxing.org
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    extends C[T]
    extends C[T]

    View Slide

  41. 41
    scala-miniboxing.org
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    extends C[T]
    extends C[T]
    C[T]
    D[T]

    View Slide

  42. 42
    scala-miniboxing.org
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    C[T]
    D[T]

    View Slide

  43. 43
    scala-miniboxing.org
    def foo(t2: T)
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    C[T]
    D[T]

    View Slide

  44. 44
    scala-miniboxing.org
    def foo(t2: T)
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    C[T]
    D[T]
    def foo$mcI$sp(t2: int)

    View Slide

  45. 45
    scala-miniboxing.org
    def foo(t2: T)
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    D$mcI$sp D$mcJ$sp D$mcD$sp … and 6 others
    C[T]
    D[T]
    def foo$mcI$sp(t2: int)

    View Slide

  46. 46
    scala-miniboxing.org
    def foo(t2: T)
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    D$mcI$sp D$mcJ$sp D$mcD$sp … and 6 others
    C[T]
    D[T]
    def foo$mcI$sp(t2: int)
    call foo$mcI$sp(t2: int)

    View Slide

  47. 47
    scala-miniboxing.org
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    D$mcI$sp D$mcJ$sp D$mcD$sp … and 6 others
    C[T]
    D[T]

    View Slide

  48. 48
    scala-miniboxing.org
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    D$mcI$sp D$mcJ$sp D$mcD$sp … and 6 others
    C[T]
    D[T]
    JVM: Single inheritance!

    View Slide

  49. 49
    scala-miniboxing.org
    class D[
    class D[@specialized
    @specialized T](t: T)
    T](t: T)
    C$mcI$sp C$mcJ$sp C$mcD$sp … and 6 others
    extends C[T]
    extends C[T]
    D$mcI$sp D$mcJ$sp D$mcD$sp … and 6 others
    C[T]
    D[T]
    JVM: Single inheritance!
    Specialized class
    inhertance doesn't work:
    SI-8405

    View Slide

  50. 50
    scala-miniboxing.org
    @miniboxing
    @miniboxing

    View Slide

  51. 51
    scala-miniboxing.org
    C[T]
    class C[
    class C[@miniboxed
    @miniboxed T](t: T)
    T](t: T)

    View Slide

  52. 52
    scala-miniboxing.org
    C_J[T] C_L[T]
    C[T]
    class C[
    class C[@miniboxed
    @miniboxed T](t: T)
    T](t: T)

    View Slide

  53. 53
    scala-miniboxing.org
    C_J[T] C_L[T]
    C[T]
    class C[
    class C[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    A single field t

    View Slide

  54. 54
    scala-miniboxing.org
    C_J[T] C_L[T]
    C[T]
    class C[
    class C[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    A single field t
    With specialized getters
    and setters declared
    in the interface

    View Slide

  55. 55
    scala-miniboxing.org
    C_J[T] C_L[T]
    C[T]
    class C[
    class C[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    A single field t
    With specialized getters
    and setters declared
    in the interface
    Fixed:
    duplicate fields
    SI-3585

    View Slide

  56. 56
    scala-miniboxing.org
    class D[
    class D[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    extends C[T]
    extends C[T]

    View Slide

  57. 57
    scala-miniboxing.org
    class D[
    class D[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    extends C[T]
    extends C[T]
    C_J[T] C_L[T]
    C[T]

    View Slide

  58. 58
    scala-miniboxing.org
    class D[
    class D[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    extends C[T]
    extends C[T]
    C_J[T] C_L[T]
    C[T]
    D_J[T] D_L[T]
    D[T]

    View Slide

  59. 59
    scala-miniboxing.org
    class D[
    class D[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    extends C[T]
    extends C[T]
    C_J[T] C_L[T]
    C[T]
    D_J[T] D_L[T]
    D[T]
    Fixed:
    class inhertance
    SI-8405

    View Slide

  60. 60
    scala-miniboxing.org
    class D[
    class D[@miniboxed
    @miniboxed T](t: T)
    T](t: T)
    extends C[T]
    extends C[T]
    C_J[T] C_L[T]
    C[T]
    D_J[T] D_L[T]
    D[T]
    But why so
    few classes?
    Fixed:
    class inhertance
    SI-8405

    View Slide

  61. 61
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat

    View Slide

  62. 62
    scala-miniboxing.org
    Where's the
    Where's the
    trait Function2[-T1, -T2, +R]
    bytecode bloat?
    bytecode bloat?

    View Slide

  63. 63
    scala-miniboxing.org
    Where's the
    Where's the
    trait Function2[-T1, -T2, +R]
    bytecode bloat?
    bytecode bloat?
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object

    View Slide

  64. 64
    scala-miniboxing.org
    Where's the
    Where's the
    trait Function2[-T1, -T2, +R]

    fully specializing Function2 → 103 traits
    bytecode bloat?
    bytecode bloat?
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object

    View Slide

  65. 65
    scala-miniboxing.org
    Where's the
    Where's the
    trait Function2[-T1, -T2, +R]

    fully specializing Function2 → 103 traits

    upfront bytecode (not on-demand)
    bytecode bloat?
    bytecode bloat?
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object

    View Slide

  66. 66
    scala-miniboxing.org
    Where's the
    Where's the
    trait Function2[-T1, -T2, +R]

    fully specializing Function2 → 103 traits

    upfront bytecode (not on-demand)

    too much for the Scala library
    bytecode bloat?
    bytecode bloat?
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object

    View Slide

  67. 67
    scala-miniboxing.org
    Where's the
    Where's the
    trait Function2[-T1, -T2, +R]

    fully specializing Function2 → 103 traits

    upfront bytecode (not on-demand)

    too much for the Scala library
    bytecode bloat?
    bytecode bloat?
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object
    Unit, Boolean, Byte, Char, Short,
    Int, Long, Float, Double, Object
    Still want to distribute it
    via maven, not via torrents

    View Slide

  68. 68
    scala-miniboxing.org
    But...
    But...
    we can do better
    we can do better

    View Slide

  69. 69
    scala-miniboxing.org
    But...
    But...
    we can do better
    we can do better
    One day in 2012
    Miguel Garcia walked
    into my office and
    said: “From a low-level
    perspective, there
    are only values and
    pointers. Maybe you
    can use that!”

    View Slide

  70. 70
    scala-miniboxing.org
    But...
    But...
    we can do better
    we can do better
    One day in 2012
    Miguel Garcia walked
    into my office and
    said: “From a low-level
    perspective, there
    are only values and
    pointers. Maybe you
    can use that!”
    ...
    LONG
    DOUBLE
    INT
    FLOAT
    SHORT

    View Slide

  71. 71
    scala-miniboxing.org
    But...
    But...
    we can do better
    we can do better
    One day in 2012
    Miguel Garcia walked
    into my office and
    said: “From a low-level
    perspective, there
    are only values and
    pointers. Maybe you
    can use that!”
    ...
    LONG
    DOUBLE
    INT
    FLOAT
    SHORT
    a long integer

    View Slide

  72. 72
    scala-miniboxing.org
    And then the
    And then the

    View Slide

  73. 73
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born

    View Slide

  74. 74
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)

    View Slide

  75. 75
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)
    Stores the
    original type

    View Slide

  76. 76
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)
    Stores the
    original type
    Stores the encoded value
    (as a long integer)

    View Slide

  77. 77
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)
    BOOL 0x1
    true =

    View Slide

  78. 78
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)
    BOOL 0x1
    true =
    INT 0x2A
    42 =

    View Slide

  79. 79
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)
    BOOL 0x1
    true =
    INT 0x2A
    42 =
    FLOAT bit representation
    5.0f =

    View Slide

  80. 80
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)

    somewhat similar to a boxed object

    View Slide

  81. 81
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)

    somewhat similar to a boxed object

    but not in the heap memory

    View Slide

  82. 82
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)

    somewhat similar to a boxed object

    but not in the heap memory

    direct access to the value

    View Slide

  83. 83
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    it started from the tagged union
    TAG DATA (VALUE)

    somewhat similar to a boxed object

    but not in the heap memory

    direct access to the value
    Same benefits as for
    unboxed values

    View Slide

  84. 84
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    we can reduce the number of variants
    C[T]

    View Slide

  85. 85
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    we can reduce the number of variants
    C_J[T]
    C[T]

    View Slide

  86. 86
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    we can reduce the number of variants
    C_J[T]
    C[T]
    C_L[T]

    View Slide

  87. 87
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    we can reduce the number of variants
    C_J[T]
    C[T]
    C_L[T]
    “From a low-level
    perspective, there
    are only values and
    pointers.”

    View Slide

  88. 88
    scala-miniboxing.org
    And then the
    And then the
    idea was born
    idea was born
    we can reduce the number of variants
    C_J[T]
    C[T]
    C_L[T]
    “From a low-level
    perspective, there
    are only values and
    pointers.”
    Let's take an example

    View Slide

  89. 89
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice[@miniboxed T](t1: T,
    t2: T): T =
    if (util.Random.nextBoolean())
    t1
    else
    t2

    View Slide

  90. 90
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice[@miniboxed T](t1: T,
    t2: T): T =
    if (util.Random.nextBoolean())
    t1
    else
    t2

    View Slide

  91. 91
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice[@miniboxed T](t1: T,
    t2: T): T =
    if (util.Random.nextBoolean())
    t1
    else
    t2
    We'll have a version for
    primitive types

    View Slide

  92. 92
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](t1: ...,
    t2: ...): ... =
    if (util.Random.nextBoolean())
    t1
    else
    t2

    View Slide

  93. 93
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](t1: ...,
    t2: ...): ... =
    if (util.Random.nextBoolean())
    t1
    else
    t2
    But what's the signature?

    View Slide

  94. 94
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](t1: (Tag,Value),
    t2: (Tag,Value)):(Tag,Value)=
    if (util.Random.nextBoolean())
    t1
    else
    t2

    View Slide

  95. 95
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](t1: (Tag,Value),
    t2: (Tag,Value)):(Tag,Value)=
    if (util.Random.nextBoolean())
    t1
    else
    t2
    This is naive tagged union

    View Slide

  96. 96
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](t1: (Tag,Value),
    t2: (Tag,Value)):(Tag,Value)=
    if (util.Random.nextBoolean())
    t1
    else
    t2
    That's wasteful: we carry
    the tag for T twice
    This is naive tagged union

    View Slide

  97. 97
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](t1: (Tag,Value),
    t2: (Tag,Value)):(Tag,Value)=
    if (util.Random.nextBoolean())
    t1
    else
    t2
    That's wasteful: we carry
    the tag for T twice
    And we even return it,
    despite the caller having
    passed it
    This is naive tagged union

    View Slide

  98. 98
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](t1: (Tag,Value),
    t2: (Tag,Value)):(Tag,Value)=
    if (util.Random.nextBoolean())
    t1
    else
    t2
    That's wasteful: we carry
    the tag for T twice
    And we even return it,
    despite the caller having
    passed it
    This is naive tagged union
    Insight: we're in a statically
    typed language, use that!

    View Slide

  99. 99
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](T_Tag: Tag, t1: Value,
    t2: Value):Value=
    if (util.Random.nextBoolean())
    t1
    else
    t2

    View Slide

  100. 100
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](T_Tag: Tag, t1: Value,
    t2: Value):Value=
    if (util.Random.nextBoolean())
    t1
    else
    t2
    T_Tag corresponds to
    the type parameter

    View Slide

  101. 101
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](T_Tag: Tag, t1: Value,
    t2: Value):Value=
    if (util.Random.nextBoolean())
    t1
    else
    t2
    T_Tag corresponds to
    the type parameter
    Sort of a class tag

    View Slide

  102. 102
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](T_Tag: Tag, t1: Value,
    t2: Value):Value=
    if (util.Random.nextBoolean())
    t1
    else
    t2
    T_Tag corresponds to
    the type parameter
    Sort of a class tag
    Encoded as Long

    View Slide

  103. 103
    scala-miniboxing.org
    Let's take
    Let's take
    an example
    an example
    def choice_J[T](T_Tag: Byte, t1: Long,
    t2: Long): Long=
    if (util.Random.nextBoolean())
    t1
    else
    t2

    View Slide

  104. 104
    scala-miniboxing.org
    So, back to the
    So, back to the
    bytecode issue
    bytecode issue
    trait Function2[-T1, -T2, +R]

    with specialization this produces 103 traits

    View Slide

  105. 105
    scala-miniboxing.org
    So, back to the
    So, back to the
    bytecode issue
    bytecode issue
    trait Function2[-T1, -T2, +R]

    with specialization this produces 103 traits

    with miniboxing only 23 (100x less bytecode)

    View Slide

  106. 106
    scala-miniboxing.org
    So, back to the
    So, back to the
    bytecode issue
    bytecode issue
    trait Function2[-T1, -T2, +R]

    with specialization this produces 103 traits

    with miniboxing only 23 (100x less bytecode)

    so we expect it will be usable on the library

    View Slide

  107. 107
    scala-miniboxing.org
    So, back to the
    So, back to the
    bytecode issue
    bytecode issue
    trait Function2[-T1, -T2, +R]

    with specialization this produces 103 traits

    with miniboxing only 23 (100x less bytecode)

    so we expect it will be usable on the library
    But before we wrap this up

    View Slide

  108. 108
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat

    View Slide

  109. 109
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat
    before the benchmarks:
    some internals

    View Slide

  110. 110
    scala-miniboxing.org
    this is where it
    gets complicated

    View Slide

  111. 111
    scala-miniboxing.org
    this is where it
    gets complicated
    time for the
    hardhats

    View Slide

  112. 112
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    def choice[@ miniboxed T](t1: T,
    t2: T): T =
    if (nextBoolean() && t1.hashCode != 13)
    t1
    else
    t2

    View Slide

  113. 113
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    def choice_J[T](T_Tag: Tag, t1: Long,
    t2: Long): Long =
    if (nextBoolean() && t1.hashCode != 13)
    t1
    else
    t2

    View Slide

  114. 114
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    def choice_J[T](T_Tag: Tag, t1: Long,
    t2: Long): Long =
    if (nextBoolean() && t1.hashCode != 13)
    t1
    else
    t2

    View Slide

  115. 115
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    t1.hashCode

    View Slide

  116. 116
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    t1.hashCode

    how to translate this?

    View Slide

  117. 117
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    t1.hashCode

    how to translate this?

    when t1 is miniboxed?

    View Slide

  118. 118
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    scala> true.hashCode
    res0: Int = 1231
    scala> false.hashCode
    res1: Int = 1237

    View Slide

  119. 119
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    scala> true.hashCode
    res0: Int = 1231
    scala> false.hashCode
    res1: Int = 1237
    So calling hashCode on the Long won't work

    View Slide

  120. 120
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    minibox2box[T](T_Tag, t).hashCode

    View Slide

  121. 121
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    minibox2box[T](T_Tag, t).hashCode

    conversions: minibox2box, box2minibox

    View Slide

  122. 122
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    minibox2box[T](T_Tag, t).hashCode

    conversions: minibox2box, box2minibox

    hash code

    View Slide

  123. 123
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    minibox2box[T](T_Tag, t).hashCode

    conversions: minibox2box, box2minibox

    hash code
    – box the value back

    View Slide

  124. 124
    scala-miniboxing.org
    Let's revisit
    Let's revisit
    the example
    the example
    minibox2box[T](T_Tag, t).hashCode

    conversions: minibox2box, box2minibox

    hash code
    – box the value back
    – execute the hashCode method

    View Slide

  125. 125
    scala-miniboxing.org
    Performance-wise
    Performance-wise

    View Slide

  126. 126
    scala-miniboxing.org
    Performance-wise
    Performance-wise
    this is okay
    this is okay

    View Slide

  127. 127
    scala-miniboxing.org
    Performance-wise
    Performance-wise
    this is okay
    this is okay

    conversions

    View Slide

  128. 128
    scala-miniboxing.org
    Performance-wise
    Performance-wise
    this is okay
    this is okay

    conversions
    – between minboxed and unboxed integer types

    free on x64

    View Slide

  129. 129
    scala-miniboxing.org
    Performance-wise
    Performance-wise
    this is okay
    this is okay

    conversions
    – between minboxed and unboxed integer types

    free on x64
    – between miniboxed and floating point types

    low overhead (not free*)
    * improved translation (thanks Rex!)

    View Slide

  130. 130
    scala-miniboxing.org
    Performance-wise
    Performance-wise
    this is okay
    this is okay

    conversions
    – between minboxed and unboxed integer types

    free on x64
    – between miniboxed and floating point types

    low overhead (not free*)
    – between miniboxed and boxed values

    avoided by @miniboxed!
    * improved translation (thanks Rex!)

    View Slide

  131. 131
    scala-miniboxing.org
    the last example
    before the benchmarks

    View Slide

  132. 132
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list[@miniboxed T](t1: T,
    t2: T): List[T] =
    List[T](t1, t2)

    View Slide

  133. 133
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list[@miniboxed T](t1: T,
    t2: T): List[T] =
    List[T](t1, t2)
    List.apply[T](t1, t2)

    View Slide

  134. 134
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list[@miniboxed T](t1: T,
    t2: T): List[T] =
    List.apply[T](t1, t2)

    View Slide

  135. 135
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list[@miniboxed T](t1: T,
    t2: T): List[T] =
    List.apply[T](t1, t2)
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): ... =
    List[T].apply(t1, t2)

    View Slide

  136. 136
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list[@miniboxed T](t1: T,
    t2: T): List[T] =
    List.apply[T](t1, t2)
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): ... =
    List[T].apply(t1, t2)
    How to transform List[T]?

    View Slide

  137. 137
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    List[T]
    what is List[T] when T is miniboxed?

    View Slide

  138. 138
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    List[T]
    what is List[T] when T is miniboxed?
    – for specialization:
    [T Int] List[T] => List[Int]

    View Slide

  139. 139
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    List[T]
    what is List[T] when T is miniboxed?
    – for specialization:
    [T Int] List[T] => List[Int]

    – for miniboxing:
    still List[T]

    View Slide

  140. 140
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    List[T]
    what is List[T] when T is miniboxed?
    – for specialization:
    [T Int] List[T] => List[Int]

    – for miniboxing:
    still List[T] List_J[T] List_L[T]
    List[T]

    View Slide

  141. 141
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    List[T]
    what is List[T] when T is miniboxed?
    – for specialization:
    [T Int] List[T] => List[Int]

    – for miniboxing:
    still List[T] List_J[T] List_L[T]
    List[T]
    But List[T] is an interface,
    we can still have an adapted
    implementation class (List_J)

    View Slide

  142. 142
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): List[T] =
    List.apply[T](t1, t2)

    View Slide

  143. 143
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): List[T] =
    List.apply[T](t1, t2)

    View Slide

  144. 144
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): List[T] =
    List.apply[T](t1, t2)
    expected: T
    found: Long

    View Slide

  145. 145
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): List[T] =
    List.apply[T](minibox2box[T](T_Tag,t1),
    minibox2box[T](T_Tag,t2))

    View Slide

  146. 146
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): List[T] =
    List.apply[T](minibox2box[T](T_Tag,t1),
    minibox2box[T](T_Tag,t2))

    View Slide

  147. 147
    scala-miniboxing.org
    The last example
    The last example
    before the benchmarks
    before the benchmarks
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): List[T] =
    List.apply[T](minibox2box[T](T_Tag,t1),
    minibox2box[T](T_Tag,t2))
    def list_J[T](T_Tag: Byte, t1: Long,
    t2: Long): List[T] =
    List.apply_J[T](T_Tag, t1, t2)

    View Slide

  148. 148
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    View Slide

  149. 149
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    essentially a very general mechanism

    View Slide

  150. 150
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    essentially a very general mechanism

    and Eugene (xeno-by) gave it a shot

    View Slide

  151. 151
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    essentially a very general mechanism

    and Eugene (xeno-by) gave it a shot
    – in a week he implemented

    View Slide

  152. 152
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    essentially a very general mechanism

    and Eugene (xeno-by) gave it a shot
    – in a week he implemented
    – a value class plugin

    View Slide

  153. 153
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    essentially a very general mechanism

    and Eugene (xeno-by) gave it a shot
    – in a week he implemented
    – a value class plugin
    – with multi-param value classes

    View Slide

  154. 154
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    essentially a very general mechanism

    and Eugene (xeno-by) gave it a shot
    – in a week he implemented
    – a value class plugin
    – with multi-param value classes
    https://github.com/miniboxing/value-plugin

    View Slide

  155. 155
    scala-miniboxing.org
    It turns out there's
    It turns out there's
    more here
    more here

    essentially a very general mechanism

    and Eugene (xeno-by) gave it a shot
    – in a week he implemented
    – a value class plugin
    – with multi-param value classes
    https://github.com/miniboxing/value-plugin

    View Slide

  156. 156
    scala-miniboxing.org
    Benchmarks

    View Slide

  157. 157
    scala-miniboxing.org
    Linked List

    View Slide

  158. 158
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library
    on the Scala library

    work with Aymeric Genet (github: @MelodyLucid)

    mock-up of Scala linked list
    – Function1 / Function2 / Tuple2
    – Traversable / TraversableLike
    – Iterator / Iterable / IterableLike
    – LinearSeqOptimized
    – Builder / CanBuildFrom

    View Slide

  159. 159
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library
    on the Scala library

    work with Aymeric Genet (github: @MelodyLucid)

    mock-up of Scala linked list
    – Function1 / Function2 / Tuple2
    – Traversable / TraversableLike
    – Iterator / Iterable / IterableLike
    – LinearSeqOptimized
    – Builder / CanBuildFrom

    View Slide

  160. 160
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library
    on the Scala library

    benchmark: Least Squares Method

    View Slide

  161. 161
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library
    on the Scala library

    benchmark: Least Squares Method

    View Slide

  162. 162
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library (inf. heap)
    on the Scala library (inf. heap)

    View Slide

  163. 163
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library (inf. heap)
    on the Scala library (inf. heap)
    1.7x
    faster

    View Slide

  164. 164
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library (with GC)
    on the Scala library (with GC)
    3x
    faster

    View Slide

  165. 165
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Scala library (bytecode)
    on the Scala library (bytecode)
    generic
    miniboxed
    specialized

    View Slide

  166. 166
    scala-miniboxing.org
    non/spire

    View Slide

  167. 167
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Spire library (Complex)
    on the Spire library (Complex)
    miniboxed
    specialized
    generic

    View Slide

  168. 168
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Spire library (RexBench)
    on the Spire library (RexBench)
    miniboxed
    specialized
    generic

    View Slide

  169. 169
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Spire library (bytecode)
    on the Spire library (bytecode)
    generic
    miniboxed
    specialized

    View Slide

  170. 170
    scala-miniboxing.org
    Benchmarks
    Benchmarks
    on the Spire library (bytecode)
    on the Spire library (bytecode)
    generic
    miniboxed
    specialized
    Spire is optimized for specialization

    View Slide

  171. 171
    scala-miniboxing.org
    Credits
    Credits

    Cristian Talau - developed the initial prototype, as a semester project

    Eugene Burmako - the value class plugin based on the LDL transformation

    Aymeric Genet - developing collection-like benchmarks for the miniboxing plugin

    Martin Odersky, for his patient guidance

    Iulian Dragos, for his work on specialization and many explanations

    Miguel Garcia, for his original insights that spawned the miniboxing idea

    Michel Schinz, for his wonderful comments and enlightening ACC course

    Andrew Myers and Roland Ducournau for the discussions we had and the feedback provided

    Heather Miller for the eye-opening discussions we had

    Vojin Jovanovic, Sandro Stucki, Manohar Jonalagedda and the whole LAMP laboratory in EPFL for the extraordinary atmosphere

    Adriaan Moors, for the miniboxing name which stuck :))

    Thierry Coppey, Vera Salvisberg and George Nithin, who patiently listened to many presentations and provided valuable feedback

    Grzegorz Kossakowski, for the many brainstorming sessions on specialization

    Erik Osheim, Tom Switzer and Rex Kerr for their guidance on the Scala community side

    OOPSLA paper and artifact reviewers, who reshaped the paper with their feedback

    Sandro, Vojin, Nada, Heather, Manohar - reviews and discussions on the LDL paper

    Hubert Plociniczak for the type notation in the LDL paper

    Denys Shabalin, Dmitry Petrashko for their patient reviews of the LDL paper

    View Slide

  172. 172
    scala-miniboxing.org
    @specialized
    @specialized
    @miniboxed =
    - the limitations
    - bytecode bloat

    View Slide

  173. scala-miniboxing.org
    visit
    visit scala-miniboxing.org
    scala-miniboxing.org!
    !
    for Scala collections!

    View Slide