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

Miniboxing Library - Scala.world

Vlad Ureche
September 13, 2016

Miniboxing Library - Scala.world

Miniboxing Library - Scala.world

Vlad Ureche

September 13, 2016
Tweet

More Decks by Vlad Ureche

Other Decks in Programming

Transcript

  1. scala-miniboxing.org @miniboxing
    12th of September 2016
    scala.world
    Penrith, UK
    The Story of a Parallel Scala Library

    View Slide

  2. scala-miniboxing.org @miniboxing
    The Story of a Parallel Scala Library
    The constructs used by miniboxing to optimize your code
    12th of September 2016
    scala.world
    Penrith, UK

    View Slide

  3. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing

    Compiler transformation

    View Slide

  4. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing

    Compiler transformation

    Improves performance of generics
    – When instantiated by primitive types

    View Slide

  5. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing

    Compiler transformation

    Improves performance of generics
    – When instantiated by primitive types

    Introduces optimized constructs
    – Automatically
    – Or with programmer help

    View Slide

  6. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing

    Compiler transformation

    Improves performance of generics
    – When instantiated by primitive types

    Introduces optimized constructs
    – Automatically
    – Or with programmer help

    View Slide

  7. scala-miniboxing.org @miniboxing
    STOP
    Please ask if things
    are not clear!

    View Slide

  8. scala-miniboxing.org @miniboxing
    Motivation
    Motivation

    We build cool new constructs and paradigms
    for {
    conn getConnection \/> "Could not connect"

    ids conn.get("id") \/> "Coult not get ids"

    } yield user

    View Slide

  9. scala-miniboxing.org @miniboxing
    Motivation
    Motivation

    We build cool new constructs and paradigms

    But some constructs are deeply integrated

    Functions

    Tuples

    Arrays

    Ordering

    Numeric
    for {
    conn getConnection \/> "Could not connect"

    ids conn.get("id") \/> "Coult not get ids"

    } yield user

    View Slide

  10. scala-miniboxing.org @miniboxing
    Motivation
    Motivation
    val x = (x: Int) => x

    View Slide

  11. scala-miniboxing.org @miniboxing
    Motivation
    Motivation
    val x = (x: Int) => x
    Function syntax is sugar
    for anonymous classes
    extending FunctionX traits
    (or for Java8 lambdas)

    View Slide

  12. scala-miniboxing.org @miniboxing
    Motivation
    Motivation
    val x = (x: Int) => x
    Extending Function1 behavior?
    Sure, add an implicit.
    Function syntax is sugar
    for anonymous classes
    extending FunctionX traits
    (or for Java8 lambdas)

    View Slide

  13. scala-miniboxing.org @miniboxing
    Motivation
    Motivation
    val x = (x: Int) => x
    Extending Function1 behavior?
    Sure, add an implicit.
    Changing behavior (e.g. PartialFunction)?
    This is what we'll talk about today.
    Function syntax is sugar
    for anonymous classes
    extending FunctionX traits
    (or for Java8 lambdas)

    View Slide

  14. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class

    View Slide

  15. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface

    View Slide

  16. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface
    Changing a
    method's
    signature

    View Slide

  17. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface
    Changing a
    method's
    signature
    Updating
    the body of
    a method

    View Slide

  18. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface
    Changing a
    method's
    signature
    Updating
    the body of
    a method
    Changing the
    fields of a class

    View Slide

  19. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface
    Changing a
    method's
    signature
    Updating
    the body of
    a method
    Changing the
    fields of a class
    Extending behavior Changing behavior

    View Slide

  20. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Why would you need that?
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface
    Changing a
    method's
    signature
    Updating
    the body of
    a method
    Changing the
    fields of a class
    Extending behavior Changing behavior

    View Slide

  21. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing

    View Slide

  22. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Data Representation
    Mixing Representations
    Library Interoperation

    View Slide

  23. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Data Representation
    Mixing Representations
    Library Interoperation

    View Slide

  24. scala-miniboxing.org @miniboxing
    Erased Generics
    Erased Generics
    def identity[T](t: T): T = t
    def identity(t: Object): Object = t
    scalac / javac

    View Slide

  25. scala-miniboxing.org @miniboxing
    Erased Generics
    Erased Generics
    identity(5)
    identity(java.lang.Integer.valueOf(5))
    scalac / javac

    View Slide

  26. scala-miniboxing.org @miniboxing
    Erased Generics
    Erased Generics
    identity(5)
    identity(java.lang.Integer.valueOf(5))
    scalac / javac
    boxed data representation

    View Slide

  27. scala-miniboxing.org @miniboxing
    Erased Generics
    Erased Generics
    java.lang.Integer.valueOf(5)
    boxing is not great ...
    boxing is not great ...
    inflates heap requirements
    produces garbage
    value is accessed indirectly (slow)
    breaks locality guarantees

    View Slide

  28. scala-miniboxing.org @miniboxing
    Specialization
    Specialization
    def identity[T](t: T): T = t
    def identity(t: Object): Object = t
    specialization
    def identity_Z(t: bool): bool = t

    View Slide

  29. scala-miniboxing.org @miniboxing
    Specialization
    Specialization
    def identity[T](t: T): T = t
    def identity(t: Object): Object = t
    specialization
    def identity_Z(t: bool): bool = t
    def identity_C(t: char): char = t

    View Slide

  30. scala-miniboxing.org @miniboxing
    Specialization
    Specialization
    def identity[T](t: T): T = t
    def identity(t: Object): Object = t
    specialization
    def identity_Z(t: bool): bool = t
    def identity_C(t: char): char = t
    … (7 other variants)

    View Slide

  31. scala-miniboxing.org @miniboxing
    Specialization
    Specialization
    identity(5)
    identity_I(5)
    specialization

    View Slide

  32. scala-miniboxing.org @miniboxing
    Specialization
    Specialization
    identity(5)
    identity_I(5)
    specialization
    No boxing, it automatically
    calls the specialized
    variant for integers

    View Slide

  33. scala-miniboxing.org @miniboxing
    Specialization
    Specialization
    def tupled[T1, T2](t1: T1, t2: T2) ...
    // 100 methods (102)
    specialization

    View Slide

  34. scala-miniboxing.org @miniboxing
    Specialization
    Specialization
    def tupled[T1, T2](t1: T1, t2: T2) ...
    // 100 methods (102)
    specialization
    Can we do
    better?

    View Slide

  35. scala-miniboxing.org @miniboxing
    The idea behind
    The idea behind
    ...
    LONG
    DOUBLE
    INT
    FLOAT
    SHORT
    ...
    LONG
    DOUBLE
    INT
    FLOAT
    SHORT
    a long integer
    miniboxing
    miniboxing

    View Slide

  36. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing
    def identity[T](t: T): T = t
    def identity(t: Object): Object = t
    miniboxing
    def identity_M(..., t: long): long = t

    View Slide

  37. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing
    def identity[T](t: T): T = t
    def identity(t: Object): Object = t
    miniboxing
    def identity_M(..., t: long): long = t
    long encodes all
    primitive types

    View Slide

  38. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing
    def identity[T](t: T): T = t
    def identity(t: Object): Object = t
    miniboxing
    def identity_M(..., t: long): long = t
    Only 2n variants
    long encodes all
    primitive types

    View Slide

  39. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing
    identity(3)
    identity_M(..., int2minibox(3))
    miniboxing

    View Slide

  40. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing
    identity(3)
    identity_M(..., int2minibox(3))
    miniboxing
    The miniboxed
    variant of identity

    View Slide

  41. scala-miniboxing.org @miniboxing
    Miniboxing
    Miniboxing
    identity(3)
    identity_M(..., int2minibox(3))
    miniboxing
    The miniboxed
    variant of identity
    Unlike boxing,
    these conversions
    do not affect
    performance

    View Slide

  42. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Data Representation
    Mixing Representations
    Library Interoperation

    View Slide

  43. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Data Representation
    Mixing Representations
    Library Interoperation

    View Slide

  44. scala-miniboxing.org @miniboxing
    Call Graph
    Call Graph
    def foo[T](t: T): T = bar(t)
    def bar[T](t: T): T = baz(t)
    def baz[T](t: T): T = t
    call graph

    View Slide

  45. scala-miniboxing.org @miniboxing
    Call Graph
    Call Graph
    foo
    bar
    baz

    View Slide

  46. scala-miniboxing.org @miniboxing
    Miniboxed Call Graph
    Miniboxed Call Graph
    def foo[@miniboxed T](t: T): T = bar(t)
    def bar[@miniboxed T](t: T): T = baz(t)
    def baz[@miniboxed T](t: T): T = t
    miniboxing

    View Slide

  47. scala-miniboxing.org @miniboxing
    Miniboxed Call Graph
    Miniboxed Call Graph
    def foo(...): ... = bar(...)
    def foo_M(...): ... = bar_M(...)
    def bar(...): ... = baz(...)
    def bar_M(...): ... = baz_M(...)
    def baz(...): ... = t
    def baz_M(...): ... = t

    View Slide

  48. scala-miniboxing.org @miniboxing
    Miniboxed Call Graph
    Miniboxed Call Graph
    foo foo_M
    bar bar_M
    baz baz_M

    View Slide

  49. scala-miniboxing.org @miniboxing
    Miniboxed Call Graph
    Miniboxed Call Graph
    foo foo_M
    bar bar_M
    baz baz_M
    Data is passed in the
    miniboxed encoding
    no boxing necessary!

    View Slide

  50. scala-miniboxing.org @miniboxing
    Suboptimal Call Graph
    Suboptimal Call Graph
    def foo[@miniboxed T](t: T): T = bar(t)
    def bar[@miniboxed T](t: T): T = baz(t)
    def baz[@miniboxed T](t: T): T = t
    miniboxing

    View Slide

  51. scala-miniboxing.org @miniboxing
    Suboptimal Call Graph
    Suboptimal Call Graph
    foo foo_M
    bar
    baz baz_M

    View Slide

  52. scala-miniboxing.org @miniboxing
    Suboptimal Call Graph
    Suboptimal Call Graph
    foo foo_M
    bar
    baz baz_M
    no bar_M to call box

    View Slide

  53. scala-miniboxing.org @miniboxing
    Suboptimal Call Graph
    Suboptimal Call Graph
    foo foo_M
    bar
    baz baz_M
    no bar_M to call box

    View Slide

  54. scala-miniboxing.org @miniboxing
    Suboptimal Call Graph
    Suboptimal Call Graph
    foo foo_M
    bar
    baz baz_M
    no bar_M to call box

    View Slide

  55. scala-miniboxing.org @miniboxing
    Suboptimal Call Graph
    Suboptimal Call Graph
    foo foo_M
    bar
    baz baz_M
    no bar_M to call box

    not enough info to return
    to the optimized trace

    View Slide

  56. scala-miniboxing.org @miniboxing
    Suboptimal Call Graph
    Suboptimal Call Graph
    scala> object Test {
    | def foo[@miniboxed T](t: T): T = bar(t)
    | def bar[ T](t: T): T = baz(t)
    | def baz[@miniboxed T](t: T): T = t
    | }
    :10: warning: The method Test.bar would benefit
    from miniboxing type parameter T, since it is instantiated
    by miniboxed type parameter T of method foo:
    def foo[@miniboxed T](t: T): T = bar(t)
    ^
    :11: warning: The following code could benefit
    from miniboxing specialization if the type parameter T
    of method bar would be marked as "@miniboxed T":
    def bar[T](t: T): T = baz(t)
    ^
    defined object Test

    View Slide

  57. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Data Representation
    Mixing Representations
    Library Interoperation

    View Slide

  58. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Data Representation
    Mixing Representations
    Library Interoperation

    View Slide

  59. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation
    scala> def identityFun[T] = (t: T) => t
    defined method identityFun

    View Slide

  60. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation
    scala> def identityFun[T] = (t: T) => t
    defined method identityFun
    scala> identityFun(3)
    :11: warning: The method identityFun would benefit
    from miniboxing type parameter T, since it is instantiated
    by a primitive type.
    identityFun(3)
    ^
    res1: Int = 3

    View Slide

  61. scala-miniboxing.org @miniboxing
    scala> def identityFun[@miniboxed T] = (t: T) => t
    Library Interoperation
    Library Interoperation

    View Slide

  62. scala-miniboxing.org @miniboxing
    scala> def identityFun[@miniboxed T] = (t: T) => t
    :12: warning: The type parameter T1 of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    :12: warning: The type parameter R of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    defined method identityFun
    Library Interoperation
    Library Interoperation

    View Slide

  63. scala-miniboxing.org @miniboxing
    scala> def identityFun[@miniboxed T] = (t: T) => t
    :12: warning: The type parameter T1 of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    :12: warning: The type parameter R of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    defined method identityFun
    Library Interoperation
    Library Interoperation
    Not actionable

    View Slide

  64. scala-miniboxing.org @miniboxing
    scala> def identityFun[@miniboxed T] = (t: T) => t
    :12: warning: The type parameter T1 of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    :12: warning: The type parameter R of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    defined method identityFun
    Library Interoperation
    Library Interoperation
    Not actionable
    Need to fix it

    View Slide

  65. scala-miniboxing.org @miniboxing
    scala> def identityFun[@miniboxed T] = (t: T) => t
    :12: warning: The type parameter T1 of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    :12: warning: The type parameter R of trait
    scala.Function1 is specialized but to interoperate
    efficiently with miniboxing, it would have to be miniboxed.
    def identityFun[@miniboxed T] = (t: T) => t
    ^
    defined method identityFun
    Library Interoperation
    Library Interoperation
    Not actionable
    Need to fix it

    View Slide

  66. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation

    Multiple such constructs
    – Functions automatic, most interesting

    – Arrays need user intervention, warnings

    – Tuples automatic

    – Numeric automatic, but I was lazy

    View Slide

  67. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Data Representation
    Mixing Representations
    Library Interoperation

    View Slide

  68. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing

    View Slide

  69. scala-miniboxing.org @miniboxing
    MbFunctionX
    MbFunctionX

    Miniboxed replacement for FunctionX

    Assumptions
    – Function created once
    – Called multiple times optimize for calling

    overhead

    View Slide

  70. scala-miniboxing.org @miniboxing
    MbFunctionX
    MbFunctionX

    Miniboxed replacement for FunctionX

    Assumptions
    – Function created once
    – Called multiple times optimize for calling

    overhead
    Let's see how we
    transform

    View Slide

  71. scala-miniboxing.org @miniboxing
    MbFunctionX
    MbFunctionX

    Three approaches
    – trait Function0[@miniboxed @specialized R]

    Incompatible transformations, won't fly
    – Call-site adaptation (implicit + value class)

    call overhead
    – Replace FunctionX body

    no call overhead

    View Slide

  72. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation
    scala> def identityFun[@miniboxed T] = (t: T) => t
    defined method identityFun

    View Slide

  73. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation
    scala> def identityFun[@miniboxed T] = (t: T) => t
    defined method identityFun
    def identityFun[@miniboxed T]: MbFunction1[T, T] = ...

    View Slide

  74. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation
    scala> def identityFun[@miniboxed T] = (t: T) => t
    defined method identityFun
    def identityFun[@miniboxed T]: MbFunction1[T, T] = ...
    Once this is done,
    miniboxing does its magic

    View Slide

  75. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation
    scala> def identityFun[@miniboxed T] = (t: T) => t
    defined method identityFun
    def identityFun[@miniboxed T]: MbFunction1[T, T] = ...
    Once this is done,
    miniboxing does its magic
    def identityFun[T]: MbFunction1[T, T] = {
    class $anon extends MbFunction1_L[T, T] {
    def apply(t: T) = t
    }
    new $anon()
    }
    def identityFun_M[Tsp](...): MbFunction1[T, T] = {
    class $anon extends MbFunction1_M[T, T](...) {
    def apply_M(..., t: T) = t
    }
    new $anon()
    }

    View Slide

  76. scala-miniboxing.org @miniboxing
    Library Interoperation
    Library Interoperation

    Multiple such constructs
    – Functions automatic, most interesting

    – Arrays need user intervention, warnings

    – Tuples automatic

    – Numeric automatic, but I was lazy

    View Slide

  77. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface
    Changing a
    method's
    signature
    Updating
    the body of
    a method
    Changing the
    fields of a class
    Extending behavior Changing behavior

    View Slide

  78. scala-miniboxing.org @miniboxing
    Extending vs Changing Behavior
    Extending vs Changing Behavior
    Adding a new
    method to the
    trait/class
    Making it
    conform to an
    interface
    Changing a
    method's
    signature
    Updating
    the body of
    a method
    Changing the
    fields of a class
    Extending behavior Changing behavior
    Completely
    replacing a
    library class

    View Slide

  79. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing

    View Slide

  80. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Dependencies
    Reverse deps
    Object model

    View Slide

  81. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Dependencies
    Reverse deps
    Object model

    View Slide

  82. scala-miniboxing.org @miniboxing
    Dependencies
    Dependencies
    Your library

    View Slide

  83. scala-miniboxing.org @miniboxing
    Dependencies
    Dependencies
    Your library
    Scala stdlib Other library Other library dependencies

    View Slide

  84. scala-miniboxing.org @miniboxing
    Dependencies
    Dependencies
    Your library
    Scala stdlib Other library Other library dependencies

    View Slide

  85. scala-miniboxing.org @miniboxing
    Dependencies
    Dependencies
    Your library
    Scala stdlib Other library Other library dependencies
    Each library is free
    to use its desired
    FunctionX version

    View Slide

  86. scala-miniboxing.org @miniboxing
    Dependencies
    Dependencies
    Your library
    Scala stdlib Other library Other library dependencies
    Each library is free
    to use its desired
    FunctionX version
    Talk to each in its
    own "language"

    View Slide

  87. scala-miniboxing.org @miniboxing
    Dependencies
    Dependencies
    Your library
    Scala stdlib Other library Other library dependencies
    Each library is free
    to use its desired
    FunctionX version
    Talk to each in its
    own "language"
    Have to track of the
    transformations

    View Slide

  88. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    Source
    Signatures
    Bytecode
    Source
    Signatures
    Bytecode
    Source
    Signatures
    Bytecode
    JVM
    scalac
    scalac
    scalac

    View Slide

  89. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    Source
    Signatures
    Bytecode
    Source
    Signatures
    Bytecode
    Source
    Signatures
    Bytecode
    JVM
    scalac
    scalac
    scalac

    View Slide

  90. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    Source
    Signatures
    Bytecode
    Source
    Signatures
    Bytecode
    Source
    Signatures
    Bytecode
    JVM
    scalac
    scalac
    scalac

    View Slide

  91. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes

    Keep track of changes to
    – Methods
    – Fields
    – Classes
    – Traits

    Carry transformation info with types
    – Automatically annotate the code
    – The pickler phase stores them in signatures
    – Introduce conversions where necessary

    View Slide

  92. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes

    View Slide

  93. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes

    View Slide

  94. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes

    View Slide

  95. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    place a
    compiler
    phase here

    View Slide

  96. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    def identityFun[@miniboxed T] = (t: T) => t
    typer

    View Slide

  97. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    def identityFun[@miniboxed T] = (t: T) => t
    def identityFun[@miniboxed T]: Function1[T, T] =
    (t: T) => t
    typer
    interop-inject

    View Slide

  98. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    def identityFun[@miniboxed T] = (t: T) => t
    def identityFun[@miniboxed T]: Function1[T, T] =
    (t: T) => t
    typer
    interop-inject
    @...
    def identityFun[@miniboxed T]: Function1[T, T] @mbFun =
    (t: T) => t
    pickler

    View Slide

  99. scala-miniboxing.org @miniboxing
    Marking Changes
    Marking Changes
    def identityFun[@miniboxed T] = (t: T) => t
    def identityFun[@miniboxed T]: Function1[T, T] =
    (t: T) => t
    typer
    interop-inject
    @...
    def identityFun[@miniboxed T]: Function1[T, T] @mbFun =
    (t: T) => t
    Future compilation runs
    are aware of the change
    pickler

    View Slide

  100. scala-miniboxing.org @miniboxing
    Conversions
    Conversions

    What do to if
    – We have an MbFunction1 and
    – Callee expects Function1?

    Conversions
    – Between the two cases
    – Functions defined in miniboxed code

    Miniboxing-friendly and specialization-friendly
    – Functions defined in non-miniboxed code

    Specialization-friendly

    Need conversion Miniboxing friendly

    View Slide

  101. scala-miniboxing.org @miniboxing
    Conversions
    Conversions
    def identityFun[@miniboxed T] = Predef.identity
    typer

    View Slide

  102. scala-miniboxing.org @miniboxing
    Conversions
    Conversions
    def identityFun[@miniboxed T] = Predef.identity
    def identityFun[@miniboxed T]: Function1[T, T] =
    Predef.identity[T] // : Function1[T, T] from classpath
    typer
    interop-inject

    View Slide

  103. scala-miniboxing.org @miniboxing
    Conversions
    Conversions
    def identityFun[@miniboxed T] = Predef.identity
    def identityFun[@miniboxed T]: Function1[T, T] =
    Predef.identity[T] // : Function1[T, T] from classpath
    typer
    interop-inject
    @...
    def identityFun[@miniboxed T]: Function1[T, T] @mbFun =
    Predef.identity[T] // : Function1[T, T] no annotation
    interop-coerce

    View Slide

  104. scala-miniboxing.org @miniboxing
    @...
    def identityFun[@miniboxed T]: Function1[T, T] @mbFun =
    toMbFun(Predef.identity[T]) // : Function1[T, T] @mbFun
    Conversions
    Conversions
    def identityFun[@miniboxed T] = Predef.identity
    def identityFun[@miniboxed T]: Function1[T, T] =
    Predef.identity[T] // : Function1[T, T] from classpath
    typer
    interop-inject
    @...
    def identityFun[@miniboxed T]: Function1[T, T] @mbFun =
    Predef.identity[T] // : Function1[T, T] no annotation
    interop-coerce

    View Slide

  105. scala-miniboxing.org @miniboxing
    Conversions
    Conversions
    Conversions are introduced based on types
    See scala-miniboxing.org/ldl for details

    View Slide

  106. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Dependencies
    Reverse deps
    Object model

    View Slide

  107. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Dependencies
    Reverse deps
    Object model

    View Slide

  108. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    Your library

    View Slide

  109. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    Your library
    Scala stdlib Other library Other library dependencies

    View Slide

  110. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    Your library
    Scala stdlib Other library Other library
    Other lib 1 Other lib 2 Other lib 3
    dependencies
    reverse
    dependencies

    View Slide

  111. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    Your library
    Scala stdlib Other library Other library
    Other lib 1 Other lib 2 Other lib 3
    dependencies
    reverse
    dependencies

    View Slide

  112. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    Your library
    Scala stdlib Other library Other library
    Other lib 1 Other lib 2 Other lib 3
    dependencies
    reverse
    dependencies
    Libraries not compiled
    with the miniboxing
    plugin are not aware of
    the transformation →
    incorrect bytecode

    View Slide

  113. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    $ scala
    Welcome to Scala version 2.11.7 (Java HotSpot(TM)
    64-Bit Server VM, Java 1.8.0_101).
    Type in expressions to have them evaluated.
    Type :help for more information.
    scala> Test.identityFun(2)
    :11: error: This method was compiled with the
    miniboxing plugin and can only be called by code also
    compiled with the miniboxing plugin (see
    scala-miniboxing.org/compatibility)
    [mbox=0.4-M8,scala=2.11.7]
    Test.identityFun(2)
    ^

    View Slide

  114. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    def identityFun[@miniboxed T] = (t: T) => t
    def identityFun[@miniboxed T]: Function1[T, T] =
    (t: T) => t
    typer
    interop-inject
    @compileTimeOnly(...)
    def identityFun[@miniboxed T]: Function1[T, T] @mbFun =
    (t: T) => t
    pickler

    View Slide

  115. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    def identityFun[@miniboxed T] = (t: T) => t
    def identityFun[@miniboxed T]: Function1[T, T] =
    (t: T) => t
    typer
    interop-inject
    @compileTimeOnly(...)
    def identityFun[@miniboxed T]: Function1[T, T] @mbFun =
    (t: T) => t
    Built into the Scala stdlib
    and recognized by scalac
    (checked by refchecks)
    pickler

    View Slide

  116. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    miniboxing
    introduces
    annotation
    here

    View Slide

  117. scala-miniboxing.org @miniboxing
    Reverse Dependencies
    Reverse Dependencies
    miniboxing
    introduces
    annotation
    here
    ... and
    removes it
    just before
    refchecks

    View Slide

  118. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Dependencies
    Reverse deps
    Object model

    View Slide

  119. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Dependencies
    Reverse deps
    Object model

    View Slide

  120. scala-miniboxing.org @miniboxing
    Object Model
    Object Model
    trait IdentityFun {
    def identityFun[T]: T => T // = Function1 [T, T]
    }

    View Slide

  121. scala-miniboxing.org @miniboxing
    Object Model
    Object Model
    trait IdentityFun {
    def identityFun[T]: T => T // = Function1 [T, T]
    }
    object MbIdentityFun extends IdentityFun {
    def identityFun[@miniboxed T]: T => T = (t: T) => t
    }

    View Slide

  122. scala-miniboxing.org @miniboxing
    Object Model
    Object Model
    trait IdentityFun {
    def identityFun[T]: T => T // = Function1 [T, T]
    }
    object MbIdentityFun extends IdentityFun {
    def identityFun[@miniboxed T]: T => T = (t: T) => t
    }
    scala> MbIdentityFun.identityFun(2)
    :11: error: ...
    scala> val id: IdentityFun = MbIdentityFun
    id: IdentityFun = [email protected]
    scala> id.identityFun(3)
    res1: Int = 3

    View Slide

  123. scala-miniboxing.org @miniboxing
    Object Model
    Object Model
    trait IdentityFun {
    def identityFun[T]: T => T // = Function1 [T, T]
    }
    object MbIdentityFun extends IdentityFun {
    def identityFun[@miniboxed T]: T => T = (t: T) => t
    }
    scala> MbIdentityFun.identityFun(2)
    :11: error: ...
    scala> val id: IdentityFun = MbIdentityFun
    id: IdentityFun = [email protected]
    scala> id.identityFun(3)
    res1: Int = 3
    You can "hide" miniboxed
    code behind an interface

    View Slide

  124. scala-miniboxing.org @miniboxing
    Object Model
    Object Model

    Allows "hiding" miniboxed code
    – Under an erased interface (example)
    – Under a specialized interface

    Pro: no dependency on the plugin downstream

    Cons: have to write some glue code

    View Slide

  125. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing
    Dependencies
    Reverse deps
    Object model

    View Slide

  126. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing

    View Slide

  127. scala-miniboxing.org @miniboxing
    RRBVector Experiment
    RRBVector Experiment

    RRBVector is an immutable vector data structure
    – With constant-time split and merge (for parallel ops)

    Idea by Phil Bagwell and Tiark Rompf

    Implementation by Nicolas Stucki
    – 4 developer-weeks of work
    – Hand-tuned for maximum performance
    – Scaling almost linearly with the number of cores
    – Summing a vector is 2x as slow as summing an array

    Presented at ICFP '15

    View Slide

  128. scala-miniboxing.org @miniboxing
    RRBVector Experiment
    RRBVector Experiment

    Questions:
    – How difficult is it to specialize RRBVector with miniboxing?
    – What are the speedups obtained by miniboxing?

    Preparation:
    – Copied the Scala stdlib suppor necessary for RRBVector (3k LOC)
    – Eliminated the parallel execution support (3k 2k LOC)

    – Prepared benchmarks

    Subject: Milos Stojanovic
    – Master student working in the lab
    – Experienced with miniboxing
    – Never saw the RRBVector code base before

    View Slide

  129. scala-miniboxing.org @miniboxing
    RRBVector Experiment
    RRBVector Experiment

    It took 30 minutes to optimize the code base
    by following the miniboxing warnings → 0.3%
    of the development time
    Benchmark
    Microbenchmarks (5M elements) Macrobenchmark
    Builder map fold reverse*
    Least squares linear
    regression (5M points)
    Erased
    (seconds)
    43.2 103.0 94.1 31.4 4864.6
    Miniboxed
    (seconds)
    22.9 60.4 42.1 35.3 1818.1
    Speedup
    (ratio)
    1.88x 1.71x 2.24x 0.89x 2.68x
    * reversing a vector does not perform
    any operations that could benefit from
    miniboxing.

    View Slide

  130. scala-miniboxing.org @miniboxing
    RRBVector Experiment
    RRBVector Experiment

    Used library features
    – MbFunction
    – MbArray
    – Tuples
    – Numeric
    – Ordering

    View Slide

  131. scala-miniboxing.org @miniboxing
    RRBVector Experiment
    RRBVector Experiment

    Used library features
    – MbFunction
    – MbArray
    – Tuples
    – Numeric
    – Ordering
    Impossible to cover today

    View Slide

  132. scala-miniboxing.org @miniboxing

    View Slide

  133. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing

    View Slide

  134. scala-miniboxing.org @miniboxing
    Functions
    Transformation
    Experiment
    Conclusion
    Miniboxing

    View Slide

  135. scala-miniboxing.org @miniboxing
    Miniboxed Library
    Miniboxed Library

    Replaces deeply integrated Scala constructs
    – Preserve the syntactic sugar
    – No source code changes

    Scalac/miniboxing does a lot of the work

    Use cases
    – Miniboxing: performance

    View Slide

  136. scala-miniboxing.org @miniboxing
    scala-miniboxing.org
    Special thanks:
    Alexandru Nedelcu
    Milos Stojanovic
    Romain Beguet
    Nicolas Stucki
    Scala team @ EPFL

    View Slide