1 Transient Typechecks are (almost) Free Richard Roberts, Stefan - - PowerPoint PPT Presentation

1 transient typechecks are almost free
SMART_READER_LITE
LIVE PREVIEW

1 Transient Typechecks are (almost) Free Richard Roberts, Stefan - - PowerPoint PPT Presentation

1 Transient Typechecks are (almost) Free Richard Roberts, Stefan Marr Michael Homer, James Noble 2 Transient Performance The transient approach checks types at uses, so the act of adding types to a program introduces more


slide-1
SLIDE 1 1
slide-2
SLIDE 2

Transient
 Typechecks
 are (almost) Free

Richard Roberts, Stefan Marr
 Michael Homer, James Noble

2
slide-3
SLIDE 3

Transient Performance

“The transient approach checks types at uses, so the act of adding types to a program introduces more casts and may slow the program down (even in fully typed code).” … “transient semantics...is a worst case scenario..., there is a cast at almost every call” Chung, Li, Nardelli and Vitek, ECOOP 2018 “imposes a run-time checking overhead that is directly proportional to the number of [type annotations] in the program” Greenman and Felleisen, ICFP 2018 “clear trend that adding type annotations adds performance
  • verhead. The increase is typically linear.”
Greenman and Migeed, PEPM 2018 3
slide-4
SLIDE 4

Microbenchmarks

method foo9(xa : A, xb : B, xc : C, xd : D, xe : E) { count := count + 1 foo8(a,b,c,d,e) } method foo8(xa : A, xb : B, xc : C, xd : D, xe : E) { count := count + 1 foo7(a,b,c,d,e) } method foo7(xa : A, xb : B, xc : C, xd : D, xe : E) { count := count + 1 foo6(a,b,c,d,e) } 4
slide-5
SLIDE 5

Microbenchmarks

method foo9(xa , xb , xc , xd , xe ) { count := count + 1 foo8(a,b,c,d,e) } method foo8(xa , xb , xc , xd , xe ) { count := count + 1 foo7(a,b,c,d,e) } method foo7(xa , xb , xc , xd , xe ) { count := count + 1 foo6(a,b,c,d,e) } 5
slide-6
SLIDE 6

Microbenchmarks

method foo9(xa : A, xb : B, xc : C, xd , xe ) { count := count + 1 foo8(a,b,c,d,e) } method foo8(xa : A, xb : B, xc : C, xd , xe ) { count := count + 1 foo7(a,b,c,d,e) } method foo7(xa : A, xb : B, xc : C, xd , xe ) { count := count + 1 foo6(a,b,c,d,e) } 6
slide-7
SLIDE 7

Microbenchmarks

method foo9(xa : A, xb : B, xc : C, xd : D, xe : E) { count := count + 1 foo8(a,b,c,d,e) } method foo8(xa : A, xb : B, xc : C, xd : D, xe : E) { count := count + 1 foo7(a,b,c,d,e) } method foo7(xa , xb , xc , xd , xe ) { count := count + 1 foo6(a,b,c,d,e) } 7
slide-8
SLIDE 8

Are We Fast Yet?

8 Iteration 1 Check Nest 1 2 3 4 5 1 2 3 4 5 2000 2400 2800 3200 Number of Typed Method Arguments Run time (ms) (lower is better)
slide-9
SLIDE 9

Are We Fast Yet?

9 Iteration 1 Check Nest 1 2 3 4 5 1 2 3 4 5 2000 2400 2800 3200 Number of Typed Method Arguments Run time (ms) (lower is better) Check Nest 1 2 3 4 5 1 2 3 4 5 200 400 600 800 Number of Typed Method Arguments Run time (ms) (lower is better) Moth (both) Moth (neither) Moth (untyped) Iteration 100
slide-10
SLIDE 10

Transient
 Typechecks
 are (almost) Free

Richard Roberts, Stefan Marr
 Michael Homer, James Noble

10
slide-11
SLIDE 11 11
slide-12
SLIDE 12 12

Grace

slide-13
SLIDE 13

Goals

Not require type annotations Dynamic types must be checked Checking must be cheap Run statically incorrect code Lightweight Implementation

13
slide-14
SLIDE 14 14
slide-15
SLIDE 15 Every object has a class Methods, fields, constants Multipart names Blocks for control Non-local returns Optionally typed Modules as classes Classes inside classes
 Everything is an object Methods, fields, constants Multi-part & arity names Blocks for control Non-local returns Optionally & gradually typed Modules as objects Classes inside classes Objects inside methods 15

Grace

slide-16
SLIDE 16 16

NS

slide-17
SLIDE 17

Are We Fast Yet?

17 Higgs Moth Node.js (V8) Java 0.75 1.00 2.00 3.00 4.00 10.00 50.00 Run-time factor, normalized to Java
slide-18
SLIDE 18

def o = object { 
 method three {3}
 }

18
slide-19
SLIDE 19

def o = object { 
 method three {3}
 }


  • .three

19
slide-20
SLIDE 20

def o = object { 
 method three {3}
 }
 type Three = interface { three }

20
slide-21
SLIDE 21

def o = object { 
 method three {3}
 }
 type Three = interface { three } def p : Three = o p.three

21
slide-22
SLIDE 22

def o = object { 
 method three {3}
 }
 type Three = interface { three } method wantsThree( trois : Three ) { } wantsThree( o )

22
slide-23
SLIDE 23

def o = object { 
 method four {3}
 }
 type Three = interface { three } method wantsThree( trois : Three ) { } wantsThree( o ) // should crash!

23
slide-24
SLIDE 24

Transient Typechecks

method wantsThree( trois : Three ) { } method wantsThree( trois ) {
 assert { Three.match(trois) }
 } 24
slide-25
SLIDE 25 Towers Storage SpectralNorm Snake Sieve Richards Queens PyStone Permute NBody Mandelbrot List Json Havlak GraphSearch Go Float Fannkuch DeltaBlue CD Bounce 0.8 0.9 1.0 1.1 1.5 2.0 Run-time factor, normalized to Moth (untyped)

Transient Overhead

25
slide-26
SLIDE 26 26

Warmup

SpectralNorm Storage Towers Richards Sieve Snake Permute PyStone Queens List Mandelbrot NBody GraphSearch Havlak Json Fannkuch Float Go Bounce CD DeltaBlue 25 50 75 100 25 50 75 100 25 50 75 100 0.0 0.5 1.0 1.5 2.0 0.0 0.5 1.0 1.5 2.0 0.0 0.5 1.0 1.5 2.0 0.0 0.5 1.0 1.5 2.0 0.0 0.5 1.0 1.5 2.0 0.0 0.5 1.0 1.5 2.0 0.0 0.5 1.0 1.5 2.0 Iterations in same VM Run-time factor, normalized to untyped (lower is better)
slide-27
SLIDE 27 27

Subtype Cache

Three A B …
  • 1
T xa T xb T … Defined Type Observed Shape (names indicate origin)

method wantsThree( trois : Three ) { } wantsThree( o )

slide-28
SLIDE 28 28

Subtype Cache

1 global record: Matrix 2 3 class TypeCheckNode(Node): 4 5 expected: Type 6 7 @Spec(static_guard=expected.check(obj)) 20 21 @Fallback 22 def check(obj: Any): 23 T = obj.get_type() 24 25 if record[T, expected] is unknown: 26 record[T, expected] = T.is_subtype_of(expected) 27 28 if not record[T, expected]: 29 raise TypeError(f"{obj} doesnt implement {expected}")
slide-29
SLIDE 29

Specialization

29 call wantsThree read
  • check
arg trois expect type(o)

method wantsThree( trois : Three ) { } wantsThree( o )

... exception After Würthinger et al, One VM to Rule them all Onward! 2013

slide-30
SLIDE 30

Specialization

30 call wantsThree read
  • check

cache type Three

method wantsThree( trois : Three ) { } wantsThree( o )

... shape call wantsThree After Würthinger et al, One VM to Rule them all Onward! 2013

slide-31
SLIDE 31

Specialization

31 call wantsThree read
  • check

cache type Three

method wantsThree( trois : Three ) { } wantsThree( o )

... shape call wantsThree After Würthinger et al, One VM to Rule them all Onward! 2013

slide-32
SLIDE 32 32

Specialization

6 7 @Spec(static_guard=expected.check(obj)) 8 def check(obj: Number): 9 pass 10 11 @Spec(static_guard=expected.check(obj)) 12 def check(obj: String): 13 pass 14 15 ... 16 17 @Spec(guard=obj.shape==cached_shape, static_guard=expected.check(obj)) 18 def check(obj: Object, @Cached(obj.shape) cached_shape: Shape): 19 pass 20 21 @Fallback 22 def check(obj: Any): 23 T = obj.get_type() 24 25 if record[T, expected] is unknown:
slide-33
SLIDE 33

Optimizations

33 Moth (neither) Moth (subtype cache) Moth (optimized node) Moth (both) Moth (untyped) 0.85 1.00 2.00 8.00 30.00 50.00 100.00 150.00 Run-time factor, normalized to Moth (untyped)
slide-34
SLIDE 34

Optimizations

34 Type Test Enabled Optimization mean #invocations min max check_generic Neither 137,525,845 11,628,068 896,604,537 Subtype Cache 137,525,845 11,628,068 896,604,537 Optimized Node 292 68 1,012 Both 292 68 1,012 is_subtype_of Neither 134,125,215 11,628,067 896,604,534 Subtype Cache 16 10 29 Optimized Node 292 68 1,012 Both 16 10 29
slide-35
SLIDE 35

Pathology

79%

35 1 var elem: ListElement := headOfList 2 while (...) do { 3 elem := elem.next 4 }
slide-36
SLIDE 36

Local Semantics

def o = object { 
 method three -> Unknown {3}
 } type ThreeString = interface { three -> String } def t : ThreeString = o printString (t.three)

36
slide-37
SLIDE 37

Lexical Semantics

def o = object { 
 method three -> Unknown {3}
 } type ThreeString = interface { three -> String } def t : ThreeString = o printString (t.three)

37
slide-38
SLIDE 38

Shallow Semantics

def o = object { 
 method three -> Number {3}
 } type ThreeString = interface { three -> String } method wantsThree( trois : ThreeString ) {}
 wantsThree( o )

38
slide-39
SLIDE 39

Deep Semantics

def o = object { 
 method three -> Number {3}
 } type ThreeString = interface { three -> String } method wantsThree( trois : ThreeString ) {}
 wantsThree( o )

39
slide-40
SLIDE 40

Deep emulates Shallow

def o = object { 
 method three -> Number {3}
 } type Three = interface { three -> Unknown } method wantsThree( trois : Three ) {}
 wantsThree( o )

40
slide-41
SLIDE 41

Concrete Semantics

def o = object { 
 method three -> Unknown {3}
 } type ThreeString = interface { three -> String } method wantsThree( trois : ThreeString ) {}
 wantsThree( o )

41
slide-42
SLIDE 42

Graceful Semantics?

def o = object { 
 method three -> Unknown {3}
 } type ThreeString = interface { three -> String } method wantsThree( trois : ThreeString ) {}
 wantsThree( o )

42
slide-43
SLIDE 43

Pathology

43

for (1.. innerIterations) do { i: Number ->
 system.advance(0.01)
 } 1.asInteger.to(innerIterations) do { i: Number ->
 system.advance(0.01)
 }

slide-44
SLIDE 44

Dialects

44 SomeDialect ModuleC dialect "SomeDialect" ... diaMeth ... DialectDialect SomeDialect dialect "DialectDialect" method diaMeth { ... }
slide-45
SLIDE 45

Into the Gracer-verse?

method wantsThree( trois : ThreeString ) { method wantsThree( trois ) {
 assert { ThreeString.match(trois) }
 }
 method wantsThree( trois’’ ) {
 def trois’ = ThreeString.match(trois’’) assert { trois’ } def trois = trois’.result } 45
slide-46
SLIDE 46

Even more semantics

Optional vs Mandatory Structural vs Nominal Erasure vs Shallow vs Deep Symmetric vs Asymmetric Local vs Lexical vs Reference vs Global Identity vs Chaperones vs Coercions Pure vs Impure Crash vs Exceptions vs Warnings 46
slide-47
SLIDE 47

Related Work

47
slide-48
SLIDE 48

Conclusions?

Transient checks (almost) for free Use a “real” VM Steal one if you can Dynamic vs Static optimisation Many more gradual semantics…

48
slide-49
SLIDE 49 49

github.com/ gracelang/ moth-SOMns

slide-50
SLIDE 50 50

?

slide-51
SLIDE 51 51