Share
Embed
What do auto(un)boxing, specialization and value classes have in common?
Late Data Layout presentation at the Scala Bay Area Meetup (thanks Vlad Patryshev!): What do auto(un)boxing, specialization and value classes have in common?
The recording is available on youtube:
https://www.youtube.com/watch?v=HPqNmaAUAJc
Project website: http://scala-miniboxing.org
Vlad Ureche
August 01, 2014
Transcript
276 slides
-
scala-miniboxing.org 1st of August 2014 Scala Bay Area Meetup Linkedin
HQ, Mountain View -
scala-miniboxing.org Vlad URECHE PhD student in the Scala Team @
EPFL Miniboxing guy. Also worked on specialization, the backend and scaladoc. @ @VladUreche @VladUreche [email protected] -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? What are they? -
7 scala-miniboxing.org Auto(un)boxing Auto(un)boxing def identity[T](t: T): T = t
def identity(t: Object): Object = t scalac / javac -
8 scala-miniboxing.org Auto(un)boxing Auto(un)boxing def identity[T](t: T): T = t
def identity(t: Object): Object = t The process is called erasure, and is the simplest translation of generics to bytecode. scalac / javac -
13 scala-miniboxing.org Auto(un)boxing Auto(un)boxing identity(5) identity(j.l.Integer.valueOf(5)).intValue scalac / javac inflates
heap requirements Object representation -
14 scala-miniboxing.org Auto(un)boxing Auto(un)boxing identity(5) identity(j.l.Integer.valueOf(5)).intValue scalac / javac produces
garbage inflates heap requirements Object representation -
15 scala-miniboxing.org Auto(un)boxing Auto(un)boxing identity(5) identity(j.l.Integer.valueOf(5)).intValue scalac / javac produces
garbage inflates heap requirements indirect (slow) access to the value Object representation -
16 scala-miniboxing.org Auto(un)boxing Auto(un)boxing identity(5) identity(j.l.Integer.valueOf(5)).intValue scalac / javac produces
garbage breaks locality guarantees inflates heap requirements indirect (slow) access to the value Object representation -
18 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 scala.Int
behaves like an object (has methods, can be used with generics) -
19 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 scalac
scala.Int behaves like an object (has methods, can be used with generics) -
20 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 val
five: int = 5 scalac scala.Int behaves like an object (has methods, can be used with generics) -
21 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 val
five: int = 5 scalac Unboxed integer scala.Int behaves like an object (has methods, can be used with generics) -
22 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 val
five: int = 5 scalac Unboxed integer five + 3 scala.Int behaves like an object (has methods, can be used with generics) -
23 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 val
five: int = 5 scalac Unboxed integer five + 3 scalac scala.Int behaves like an object (has methods, can be used with generics) -
24 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 val
five: int = 5 scalac Unboxed integer five + 3 five + 3 scalac scala.Int behaves like an object (has methods, can be used with generics) -
25 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = 5 val
five: int = 5 scalac Unboxed integer five + 3 five + 3 scalac Unboxed addition scala.Int behaves like an object (has methods, can be used with generics) -
29 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = identity(5) val
five: int = identity(I.valueOf(5)).intValue scalac -
30 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = identity(5) val
five: int = identity(I.valueOf(5)).intValue scalac Boxing coercion -
31 scala-miniboxing.org Auto(un)boxing Auto(un)boxing val five: Int = identity(5) val
five: int = identity(I.valueOf(5)).intValue scalac Boxing coercion Unboxing coercion -
34 scala-miniboxing.org Auto(un)boxing Auto(un)boxing scala.Int int • fast access •
no garbage collection • locality -
35 scala-miniboxing.org Auto(un)boxing Auto(un)boxing scala.Int int • fast access •
no garbage collection • locality • indirect access • object allocation • and thus garbage collection • no locality guarantees • compatible with erased generics java.lang.Integer -
36 scala-miniboxing.org Auto(un)boxing Auto(un)boxing scala.Int int • fast access •
no garbage collection • locality • indirect access • object allocation • and thus garbage collection • no locality guarantees • compatible with erased generics java.lang.Integer incompatible → coercions -
40 scala-miniboxing.org Specialization Specialization def identity[T](t: T): T = t
def identity(t: Object): Object = t specialization -
41 scala-miniboxing.org Specialization Specialization def identity[T](t: T): T = t
def identity(t: Object): Object = t specialization def identity_Z(t: bool): bool = t -
42 scala-miniboxing.org 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 -
43 scala-miniboxing.org 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) -
47 scala-miniboxing.org Specialization Specialization identity(5) identity_I(5) specialization The variant of
identity specialized for int -
48 scala-miniboxing.org Specialization Specialization identity(5) identity_I(5) specialization The variant of
identity specialized for int // no boxing! -
51 scala-miniboxing.org Specialization Specialization def tupled[T1, T2](t1: T1, t2: T2)
... // 100 methods (102) specialization -
52 scala-miniboxing.org Specialization Specialization def tupled[T1, T2](t1: T1, t2: T2)
... // 100 methods (102) specialization -
53 scala-miniboxing.org Specialization Specialization def tupled[T1, T2](t1: T1, t2: T2)
... // 100 methods (102) specialization Can we do something about this? -
54 scala-miniboxing.org Specialization Specialization def tupled[T1, T2](t1: T1, t2: T2)
... // 100 methods (102) specialization Can we do something about this? -
57 scala-miniboxing.org Miniboxing Miniboxing def identity[T](t: T): T = t
def identity(t: Object): Object = t miniboxing -
58 scala-miniboxing.org Miniboxing Miniboxing def identity[T](t: T): T = t
def identity(t: Object): Object = t miniboxing def identity_M(..., t: long): long = t -
59 scala-miniboxing.org 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 -
60 scala-miniboxing.org 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 -
65 scala-miniboxing.org Miniboxing Miniboxing identity(3) identity_M(..., int2minibox(3)) miniboxing Coercion The
miniboxed variant of identity -
69 scala-miniboxing.org Miniboxing Miniboxing T long • preferred encoding •
fallback encoding • compatible with • method calls • supertypes • erased generics T (erased to Object) -
70 scala-miniboxing.org Miniboxing Miniboxing T long • preferred encoding •
fallback encoding • compatible with • method calls • supertypes • erased generics T (erased to Object) incompatible → coercions -
73 scala-miniboxing.org Value Classes Value Classes def abs(c: Complex): Double
= ... value class transformation -
74 scala-miniboxing.org Value Classes Value Classes def abs(c: Complex): Double
= ... def abs(c_re: Double, c_im: Double): Double = ... value class transformation -
75 scala-miniboxing.org Value Classes Value Classes def abs(c: Complex): Double
= ... def abs(c_re: Double, c_im: Double): Double = ... value class transformation No object created! -
77 scala-miniboxing.org Value Classes Value Classes val c: Complex =
Complex(2,1) value class transformation -
78 scala-miniboxing.org Value Classes Value Classes val c: Complex =
Complex(2,1) val c_re: Double = 2 val c_im: Double = 1 value class transformation -
79 scala-miniboxing.org Value Classes Value Classes val c: Complex =
Complex(2,1) val c_re: Double = 2 val c_im: Double = 1 value class transformation No object created! -
81 scala-miniboxing.org Value Classes Value Classes val a: Any =
c value class transformation -
82 scala-miniboxing.org Value Classes Value Classes val a: Any =
c val a: Object = new Complex(c_re, c_im) value class transformation -
83 scala-miniboxing.org Value Classes Value Classes val a: Any =
c val a: Object = new Complex(c_re, c_im) value class transformation Coercion! -
86 scala-miniboxing.org Value Classes Value Classes value class structure (by-val)
• preferred encoding -
87 scala-miniboxing.org Value Classes Value Classes value class structure (by-val)
• preferred encoding • fallback encoding • compatible with • supertypes • erased generics class (by-ref) -
88 scala-miniboxing.org Value Classes Value Classes value class structure (by-val)
• preferred encoding • fallback encoding • compatible with • supertypes • erased generics class (by-ref) incompatible → coercions -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Multi-stage programs too, but we won't go there! -
92 scala-miniboxing.org Auto(un)boxing Auto(un)boxing scala.Int int • fast access •
no garbage collection • locality • indirect access • garbage collection • and object allocation • no locality guarantees • compatible with erased generics java.lang.Integer incompatible → coercions -
93 scala-miniboxing.org Miniboxing Miniboxing T long • preferred encoding •
fallback encoding • compatible with • method calls • supertypes • erased generics T (erased to Object) incompatible → coercions -
94 scala-miniboxing.org Value Classes Value Classes value class structure (by-val)
• preferred encoding • fallback encoding • compatible with • supertypes • erased generics class (by-ref) incompatible → coercions -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Starting from a high-level concept: -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Starting from a high-level concept: (1) split it into multiple representations based on external constaints -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Starting from a high-level concept: (1) split it into multiple representations based on external constaints (2) introduce the necessary coercions when the representation has to be converted -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion -
106 scala-miniboxing.org Late Data Layout (LDL) Late Data Layout (LDL)
concept repr. 1 repr. 2 -
107 scala-miniboxing.org Late Data Layout (LDL) Late Data Layout (LDL)
concept repr. 1 … repr. n repr. 2 -
108 scala-miniboxing.org Late Data Layout (LDL) Late Data Layout (LDL)
concept repr. 1 … repr. n repr. 2 Constraints from the interaction with other language features: • generics • subtyping • virtual dispatch • DSL semantics (staging) -
109 scala-miniboxing.org Late Data Layout (LDL) Late Data Layout (LDL)
concept repr. 1 … repr. n repr. 2 Constraints from the interaction with other language features: • generics • subtyping • virtual dispatch • DSL semantics (staging) We've seen this pattern over and over again: • autounboxing • specialization • value classes • multi-stage programming • function representation • collection representation -
111 scala-miniboxing.org Collection Representation Collection Representation List[T] Stream[T] • preferred
encoding • for pure comprehensions -
112 scala-miniboxing.org Collection Representation Collection Representation List[T] Stream[T] • preferred
encoding • for pure comprehensions • for impure comprehensions • more expensive (needs to be materialized at each step) List[T] -
113 scala-miniboxing.org Collection Representation Collection Representation List[T] Stream[T] • preferred
encoding • for pure comprehensions • for impure comprehensions • more expensive (needs to be materialized at each step) List[T] incompatible → coercions -
114 scala-miniboxing.org Collection Representation Collection Representation val c = List(1,2,3)
val d = c.map(_+1).filter(_%2==0) val c = List(1,2,3) val d = c.map(_+1).filter(_%2==0) -
115 scala-miniboxing.org Collection Representation Collection Representation val c = List(1,2,3)
val d = c.map(_+1).filter(_%2==0) Materialized list val c = List(1,2,3) val d = c.map(_+1).filter(_%2==0) -
116 scala-miniboxing.org Collection Representation Collection Representation val c = List(1,2,3)
val d = c.map(_+1).filter(_%2==0) Materialized list Materialized list val c = List(1,2,3) val d = c.map(_+1).filter(_%2==0) -
117 scala-miniboxing.org Collection Representation Collection Representation val c = List(1,2,3)
val d = c.map(_+1).filter(_%2==0) Materialized list Materialized list val c = List(1,2,3) val d = c.map(_+1).filter(_%2==0) -
118 scala-miniboxing.org Collection Representation Collection Representation val c = List(1,2,3)
val d = c.map(_+1).filter(_%2==0) Materialized list Materialized list val c: Stream[Int] = List(1,2,3).toStream val c = List(1,2,3) val d = c.map(_+1).filter(_%2==0) -
119 scala-miniboxing.org Collection Representation Collection Representation val c = List(1,2,3)
val d = c.map(_+1).filter(_%2==0) Materialized list Materialized list val c: Stream[Int] = List(1,2,3).toStream val d: Stream[Int] = c.map(_+1).filter(_%2==0) val c = List(1,2,3) val d = c.map(_+1).filter(_%2==0) -
120 scala-miniboxing.org Collection Representation Collection Representation val c = List(1,2,3)
val d = c.map(_+1).filter(_%2==0) Materialized list Materialized list val c: Stream[Int] = List(1,2,3).toStream val d: Stream[Int] = c.map(_+1).filter(_%2==0) val c = List(1,2,3) val d = c.map(_+1).filter(_%2==0) No materialization! -
123 scala-miniboxing.org <Your Use Case> <Your Use Case> <concept> repr.
1 … repr. n repr. 2 -
124 scala-miniboxing.org <Your Use Case> <Your Use Case> <concept> repr.
1 … repr. n repr. 2 Can LDL help you? -
125 scala-miniboxing.org <Your Use Case> <Your Use Case> <concept> repr.
1 … repr. n repr. 2 Can LDL help you? It may not be a perfect fit, but let's give it a shot! -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion -
scala-miniboxing.org How do transform a program? If you understand the
high-level picture, you will immediately see if your usecase matches. -
scala-miniboxing.org How do transform a program? If you understand the
high-level picture, you will immediately see if your usecase matches. We'll use autounboxing as the running example, to keep things simple -
131 scala-miniboxing.org Auto(un)boxing Auto(un)boxing scala.Int int • fast access •
no garbage collection • locality • indirect access • object allocation • and thus garbage collection • no locality guarantees • compatible with erased generics java.lang.Integer -
132 scala-miniboxing.org Auto(un)boxing Auto(un)boxing scala.Int int • fast access •
no garbage collection • locality • indirect access • object allocation • and thus garbage collection • no locality guarantees • compatible with erased generics java.lang.Integer incompatible → coercions -
134 scala-miniboxing.org Naive transformation Naive transformation val x: Int =
List[Int](1, 2, 3).head val y: List[Int] = List[Int](x) naive unboxing -
135 scala-miniboxing.org Naive transformation Naive transformation val x: Int =
List[Int](1, 2, 3).head val y: List[Int] = List[Int](x) val x: int = List[Int](1, 2, 3).head val y: List[Int] = List[Int](x) naive unboxing -
136 scala-miniboxing.org Naive transformation Naive transformation val x: Int =
List[Int](1, 2, 3).head val y: List[Int] = List[Int](x) val x: int = List[Int](1, 2, 3).head val y: List[Int] = List[Int](x) naive unboxing representation mismatch: expected: int found: Int -
137 scala-miniboxing.org Naive transformation Naive transformation val x: Int =
List[Int](1, 2, 3).head val y: List[Int] = List[Int](x) val x: int = List[Int](1, 2, 3).head val y: List[Int] = List[Int](x) naive unboxing representation mismatch: expected: int found: Int representation mismatch: expected: Int found: int -
138 scala-miniboxing.org Naive transformation Naive transformation • naively replacing representations
– leads to mismatches – which are hard to recover (impossible for value classes and miniboxing) • we need coercions between representations -
140 scala-miniboxing.org Syntax-based Syntax-based • when transforming a value –
coerce the definition right-hand side – coerce all references to it -
142 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head syntax-based unboxing -
143 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val x: int = syntax-based unboxing -
144 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val x: int = unbox(List[Int](1, 2, 3).head) syntax-based unboxing -
145 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val x: int = unbox(List[Int](1, 2, 3).head) syntax-based unboxing There are no references to x, so there's nothing else to do. -
146 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val x: int = unbox(List[Int](1, 2, 3).head) syntax-based unboxing There are no references to x, so there's nothing else to do. -
147 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val y: Int = x -
148 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val y: Int = x Transform one by one -
149 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val y: Int = x syntax-based unboxing Transform one by one -
150 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val y: Int = x val x: int = unbox(List[Int](1, 2, 3).head) syntax-based unboxing Transform one by one -
151 scala-miniboxing.org Syntax-based Syntax-based val x: Int = List[Int](1, 2,
3).head val y: Int = x val x: int = unbox(List[Int](1, 2, 3).head) val y: Int = box(x) syntax-based unboxing Transform one by one -
152 scala-miniboxing.org Syntax-based Syntax-based val x: int = unbox(List[Int](1, 2,
3).head) val y: Int = box(x) -
153 scala-miniboxing.org Syntax-based Syntax-based val x: int = unbox(List[Int](1, 2,
3).head) val y: Int = box(x) syntax-based unboxing -
154 scala-miniboxing.org Syntax-based Syntax-based val x: int = unbox(List[Int](1, 2,
3).head) val y: Int = box(x) val x: int = unbox(List[Int](1, 2, 3).head) val y: int = syntax-based unboxing -
155 scala-miniboxing.org Syntax-based Syntax-based val x: int = unbox(List[Int](1, 2,
3).head) val y: Int = box(x) val x: int = unbox(List[Int](1, 2, 3).head) val y: int = unbox(box(x)) syntax-based unboxing -
156 scala-miniboxing.org Syntax-based Syntax-based val x: int = unbox(List[Int](1, 2,
3).head) val y: Int = box(x) val x: int = unbox(List[Int](1, 2, 3).head) val y: int = unbox(box(x)) syntax-based unboxing suboptimal -
158 scala-miniboxing.org Peephole Optimization Peephole Optimization val y: int =
unbox(box(x)) peephole -
159 scala-miniboxing.org Peephole Optimization Peephole Optimization val y: int =
unbox(box(x)) val y: int = x peephole -
160 scala-miniboxing.org Peephole Optimization Peephole Optimization val y: int =
unbox(box(x)) val y: int = x peephole -
161 scala-miniboxing.org Peephole Optimization Peephole Optimization val y: int =
unbox(box(x)) val y: int = x peephole Okay, let's add the peephole transformation in the pipeline. -
162 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: Int, t2: Int): Int
= if (Random.nextBoolean()) t1 else t2 -
163 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: Int, t2: Int): Int
= if (Random.nextBoolean()) t1 else t2 Transform one by one -
164 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: Int): Int
= if (Random.nextBoolean()) box(t1) else t2 -
165 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): Int
= if (Random.nextBoolean()) box(t1) else box(t2) -
166 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): Int
= if (Random.nextBoolean()) box(t1) else box(t2) Anything missing? -
167 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= unbox(if (Random.nextBoolean()) box(t1) else box(t2)) -
168 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= unbox(if (Random.nextBoolean()) box(t1) else box(t2)) -
169 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= unbox(if (Random.nextBoolean()) box(t1) else box(t2)) new peephole rule -
170 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= unbox(if (Random.nextBoolean()) box(t1) else box(t2)) new peephole rule sink outside coercions into the if branches -
171 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= if (Random.nextBoolean()) unbox(box(t1)) else unbox(box(t2)) -
172 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= if (Random.nextBoolean()) unbox(box(t1)) else unbox(box(t2)) -
173 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= if (Random.nextBoolean()) t1 else t2 -
174 scala-miniboxing.org Syntax-based Syntax-based def choice(t1: int, t2: int): int
= if (Random.nextBoolean()) t1 else t2 complicated -
175 scala-miniboxing.org Syntax-based Syntax-based • peephole transformation does not scale
– needs multiple rules for each node – needs successive rewriting => slow – impossible to guarantee optimality -
177 scala-miniboxing.org Type-based transformation Type-based transformation • propagate representation information
– into the type system (based on annotated types) – let the type system propagate this information -
178 scala-miniboxing.org Type-based transformation Type-based transformation • re-typechecking the tree
– exposes inconsistencies in the representation – so we introduce coercions • only when representations don't match -
179 scala-miniboxing.org Type-based transformation Type-based transformation • three-stage mechanism –
inject annotate the values to be unboxed → – coerce introduce coercion markers → – commit commit to the alternative representations → -
180 scala-miniboxing.org Type-based transformation Type-based transformation Warning! Throughout the presentation
we'll be writing annotations written before types (e.g. “@unboxed Int”), although in the Scala syntax they are written after the type (e.g.“Int @unboxed”). This makes it easier to read the types aloud. -
182 scala-miniboxing.org Type-based Type-based def choice(t1: Int, t2: Int): Int
= if (Random.nextBoolean()) t1 else t2 inject coerce commit -
183 scala-miniboxing.org Type-based Type-based def choice(t1: Int, t2: Int): Int
= if (Random.nextBoolean()) t1 else t2 inject coerce commit -
184 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit -
185 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit configurable introduction of annotations based on external constraints -
186 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit -
187 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit -
188 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit -
189 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit the rhs expression must be of type @unboxed Int -
190 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int the rhs expression must be of type @unboxed Int -
191 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int expected type (part of local type inference) the rhs expression must be of type @unboxed Int -
192 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : Boolean -
193 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : Boolean matches: expected: Boolean found: Boolean -
194 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int -
195 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int matches: expected: @unboxed Int found: @unboxed Int -
196 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int -
197 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit matches: ... : @unboxed Int -
198 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit -
199 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit all okay, next phase -
200 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit -
201 scala-miniboxing.org Type-based Type-based def choice(t1: @unboxed Int, t2: @unboxed
Int): @unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit Replace: @unboxed Int → int (not showing Int → j.l.Integer) -
202 scala-miniboxing.org Type-based Type-based def choice(t1: int, t2: int): int
= if (Random.nextBoolean()) t1 else t2 inject coerce commit -
203 scala-miniboxing.org Type-based Type-based def choice(t1: int, t2: int): int
= if (Random.nextBoolean()) t1 else t2 inject coerce commit that's it! -
204 scala-miniboxing.org Type-based transformation Type-based transformation • three-stage mechanism –
inject: add annotations – coerce: add coercions (based on the annotations) – commit: final representation semantics -
205 scala-miniboxing.org Type-based transformation Type-based transformation • Scalac's erasure –
similar transformation – less flexible (no annotations) – entangled with other transformations • we took what's good – and allowed the transformation to work on other usecases as well -
206 scala-miniboxing.org Type-based transformation Type-based transformation • why do this?
– at the core of: • miniboxing (http://scala-miniboxing.org) • value classes plugin (https://github.com/miniboxing/value-plugin) • multi-stage plugin (https://github.com/miniboxing/staging-plugin) • <your transformation here> -
207 scala-miniboxing.org Type-based transformation Type-based transformation • why do this?
– at the core of: • miniboxing (http://scala-miniboxing.org) • value classes plugin (https://github.com/miniboxing/value-plugin) • multi-stage plugin (https://github.com/miniboxing/staging-plugin) • <your transformation here> most important one -
209 scala-miniboxing.org Consistency Consistency inject coerce commit • representations become
explicit in types – representation mismatches • become type mismatches • are exposed by the type system – mismatches lead to coercions • explicit bridges between representations • are introduced automatically – regardless of the representations • at a meta-level -
211 scala-miniboxing.org Selectivity Selectivity inject coerce commit • annotations allow
selectively picking the values to be transformed – value classes • cannot unbox multi-param values in return position (not supported by the JVM platform) • bridge methods – staging • annotations signal domain-specific knowledge – can occur inside generics (List[@staged Int]) -
212 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: Int): Int
= if (Random.nextBoolean()) t1 else t2 inject coerce commit -
213 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: Int): Int
= if (Random.nextBoolean()) t1 else t2 inject coerce commit what if we did not annotate t1? -
214 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit what if we did not annotate t1? -
215 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int -
216 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int -
217 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int mismatch: expected: @unboxed Int found: Int -
218 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) t1 else t2 inject coerce commit : @unboxed Int mismatch: expected: @unboxed Int found: Int coercion -
219 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) unbox(t1) else t2 inject coerce commit -
220 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) unbox(t1) else t2 inject coerce commit -
221 scala-miniboxing.org Selectivity Selectivity def choice(t1: Int, t2: int): int
= if (Random.nextBoolean()) t1.intValue else t2 inject coerce commit -
223 scala-miniboxing.org Optimality Optimality def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) unbox(t1) else t2 inject coerce commit -
224 scala-miniboxing.org Optimality Optimality def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) unbox(t1) else t2 inject coerce commit -
225 scala-miniboxing.org Optimality Optimality def choice(t1: Int, t2: @unboxed Int):
@unboxed Int = if (Random.nextBoolean()) unbox(t1) else t2 inject coerce commit Coercions are sunk in the tree → excute only if necessary -
scala-miniboxing.org Miniboxing Value Classes* Multi-stage Programming* Use cases Type-based LDL
transformation * early prototypes -
227 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... -
228 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing -
229 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing first: duplicate body -
230 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … first: duplicate body -
231 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … def tupled_ML[T1, T2](..., t1: T1, t2: T2) = … first: duplicate body -
232 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … def tupled_ML[T1, T2](..., t1: T1, t2: T2) = … def tupled_LM[T1, T2](..., t1: T1, t2: T2) = … first: duplicate body -
233 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … def tupled_ML[T1, T2](..., t1: T1, t2: T2) = … def tupled_LM[T1, T2](..., t1: T1, t2: T2) = … def tupled_MM[T1, T2](..., t1: T1, t2: T2) = … first: duplicate body -
234 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … def tupled_ML[T1, T2](..., t1: T1, t2: T2) = … def tupled_LM[T1, T2](..., t1: T1, t2: T2) = … def tupled_MM[T1, T2](..., t1: T1, t2: T2) = … first: duplicate body second: adapt it -
235 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … def tupled_ML[T1, T2](..., t1: @long T1, t2: T2) = … def tupled_LM[T1, T2](..., t1: T1, t2: @long T2) = … def tupled_MM[T1, T2](..., t1: @long T1, t2: @long T2) = * @long is used instead of @storage[Long] second: adapt it first: duplicate body -
236 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … def tupled_ML[T1, T2](..., t1: @long T1, t2: T2) = … def tupled_LM[T1, T2](..., t1: T1, t2: @long T2) = … def tupled_MM[T1, T2](..., t1: @long T1, t2: @long T2) = * @long is used instead of @storage[Long] second: adapt it using the transformation first: duplicate body -
237 scala-miniboxing.org LDL for miniboxing LDL for miniboxing def tupled[T1,
T2](t1: T1, t2: T2) = ... miniboxing def tupled[T1, T2](t1: T1, t2: T2) = … def tupled_ML[T1, T2](..., t1: @long T1, t2: T2) = … def tupled_LM[T1, T2](..., t1: T1, t2: @long T2) = … def tupled_MM[T1, T2](..., t1: @long T1, t2: @long T2) = * @long is used instead of @storage[Long] second: adapt it using the transformation first: duplicate body body gets adapted** -
scala-miniboxing.org Miniboxing Value Classes* Multi-stage Programming* Use cases Type-based LDL
transformation * early prototypes -
239 scala-miniboxing.org LDL for value classes LDL for value classes
def abs(c: @unboxed Complex): Double = ... -
240 scala-miniboxing.org LDL for value classes LDL for value classes
def abs(c: @unboxed Complex): Double = ... value class plugin (commit phase) -
241 scala-miniboxing.org LDL for value classes LDL for value classes
def abs(c: @unboxed Complex): Double = ... value class plugin (commit phase) def abs(c_re: Double, c_im: Double): Double = ... -
242 scala-miniboxing.org LDL for value classes LDL for value classes
def abs(c: @unboxed Complex): Double = ... value class plugin (commit phase) def abs(c_re: Double, c_im: Double): Double = ... -
243 scala-miniboxing.org LDL for value classes LDL for value classes
def abs(c: @unboxed Complex): Double = ... value class plugin (commit phase) def abs(c_re: Double, c_im: Double): Double = ... I'm hiding a lot of details here. But one could talk about this for an entire day -
244 scala-miniboxing.org LDL for value classes LDL for value classes
def abs(c: @unboxed Complex): Double = ... value class plugin (commit phase) def abs(c_re: Double, c_im: Double): Double = ... I'm hiding a lot of details here. But one could talk about this for an entire day The one is @xeno-by! He implemented this :) -
scala-miniboxing.org Miniboxing Value Classes* Multi-stage Programming* Use cases Type-based LDL
transformation * early prototypes -
scala-miniboxing.org Miniboxing Value Classes* Multi-stage Programming* Use cases Type-based LDL
transformation We won't go into it today, but see github.com/miniboxing/staging-plugin * early prototypes -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion -
249 scala-miniboxing.org Miniboxing Benchmarks Miniboxing Benchmarks on the Scala library
on the Scala library • benchmark: Least Squares Method – using a mockup of scala.collection.immutable.List -
250 scala-miniboxing.org Miniboxing Benchmarks Miniboxing Benchmarks on the Scala library
on the Scala library • work with Aymeric Genet (github: @MelodyLucid) • mock-up of Scala linked List – Tuples – Traversable/TraversableLike – Iterator/Iterable/IterableLike – LinearSeqOptimized – Builder/CanBuildFrom • FunctionX has a nice story -
251 scala-miniboxing.org Miniboxing Benchmarks Miniboxing Benchmarks on the Scala library
on the Scala library • FunctionX from the Scala library – specialized – no way to call from miniboxed code without boxing slow → • MiniboxedFunctionX benchmarked ← – miniboxed, call without coercing – added automatically with another LDL cycle • MyFunctionX benchmarked ← – miniboxed, call without coercing – added by hand to the library -
253 scala-miniboxing.org Miniboxing Benchmarks Miniboxing Benchmarks on the Scala library
on the Scala library 30%-45% faster -
254 scala-miniboxing.org Miniboxing Benchmarks Miniboxing Benchmarks on the Scala library
on the Scala library 30%-45% faster On a non-contiguous data structure -
255 scala-miniboxing.org Miniboxing Benchmarks Miniboxing Benchmarks on the Scala library
(with GC) on the Scala library (with GC) -
256 scala-miniboxing.org Miniboxing Benchmarks Miniboxing Benchmarks on the Scala library
(with GC) on the Scala library (with GC) 3x faster On a non-contiguous data structure -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion -
scala-miniboxing.org What do auto(un)boxing, specialization and value classes have in
common? Why is this important? The transformation Benchmark Conclusion ` -
259 scala-miniboxing.org Conclusion Conclusion LDL is a LDL is a
transformation transformation • that allows splitting a high-level concept – into multiple representations – in a consistent way (through coercions) – in a selective way (through annotations) – in an optimal way (coerce only if necessary) • use cases covered – miniboxing – value classes • what is your use case? <concept> repr. 1 … repr. n repr. 2 -
scala-miniboxing.org Credits and Thank you-s • 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 • Eugene Burmako, for trusting the idea enough to develop the value-plugin based on the LDL transformation • 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 Special thanks to the Scala Community for their support! (@StuHood, @vpatryshev and everyone else!) -
261 scala-miniboxing.org Conclusion Conclusion LDL is a LDL is a
transformation transformation • that allows splitting a high-level concept – into multiple representations – in a consistent way (through coercions) – in a selective way (through annotations) – in an optimal way (coerce only if necessary) • use cases covered – miniboxing – value classes • what is your use case? <concept> repr. 1 … repr. n repr. 2 -
scala-miniboxing.org ScalaTeam @ EPFL • Dependent Object Types calculus –
core type system of the dotty compiler – Nada Amin/Tiark Rompf https://github.com/TiarkRompf/minidot https://github.com/lampepfl/dotty -
scala-miniboxing.org ScalaTeam @ EPFL • YinYang multi-stage macro-based frontend –
replacement for scala-virtualized – Vojin Jovanovic/Sandro Stucki + others https://github.com/vjovanov/yin-yang -
scala-miniboxing.org ScalaTeam @ EPFL • Scala.js backend – compiles Scala
to JavaScript – Sébastien Doeraene/Tobias Schlatter + others http://www.scala-js.org/ www -
scala-miniboxing.org ScalaTeam @ EPFL • Staged Parser-combinators – fast parser
combinators through staging – Manohar Jonnalagedda + others https://github.com/manojo/experiments -
scala-miniboxing.org ScalaTeam @ EPFL • Pickling framework and Spores –
support for distributed programming – Heather Miller/Philipp Haller + others https://github.com/scala/pickling https://github.com/heathermiller/spores -
scala-miniboxing.org ScalaTeam @ EPFL • dotty – experimental compiler based
on DOT – Martin Odersky/Dmitry Petrashko/Samuel Grütter/Tobias Schlatter + others https://github.com/lampepfl/dotty -
scala-miniboxing.org ScalaTeam @ EPFL • scala.meta metaprogramming support – Improved
reflection, macros, and many more – Eugene Burmako/Denys Shabalin + others http://scalameta.org/ www -
scala-miniboxing.org ScalaTeam @ EPFL • miniboxing specialization – LDL transformation
– Vlad Ureche/Aymeric Genêt + others http://scala-miniboxing.org/ www -
scala-miniboxing.org ScalaTeam @ EPFL • scaladyno plugin – giving Scala
a dynamic language look and feel – Cédric Bastin/Vlad Ureche https://github.com/scaladyno/scaladyno-plugin -
scala-miniboxing.org ScalaTeam @ EPFL • ScalaBlitz optimization framework – macro-based
collection optimization – Dmitry Petrashko/Aleksandar Prokopec http://scala-blitz.github.io/ www -
scala-miniboxing.org ScalaTeam @ EPFL • Type debugger for Scala –
debugging aid for Scala type errors – Hubert Plociniczak http://lampwww.epfl.ch/~plocinic/ type-debugger-tutorial/ www -
scala-miniboxing.org ScalaTeam @ EPFL • ScalaMeter benchmarking framework – google
caliper for scala – Aleksandar Prokopec http://scalameter.github.io/ www -
scala-miniboxing.org ScalaTeam @ EPFL • the new scalac backend –
good performance gains – Miguel Garcia • on the job market right now http://magarciaepfl.github.io/scala/ www @ [email protected] -
scala-miniboxing.org 1st of August 2014 Scala Bay Area Meetup Linkedin
HQ, Mountain View Thank you!