Slide 1

Slide 1 text

Faster than C#: efficient implementation of dynamic languages on .NET Antonio Cuni Davide Ancona Armin Rigo ICOOOLPS@ECOOP 2009 - Genova, Italy July 6, 2009 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 1 / 22

Slide 2

Slide 2 text

Introduction Dynamic languages are nice e.g., Python so are .NET and the JVM Problem: slow! Solution: make them faster :-) We concentrate our efforts on .NET A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 2 / 22

Slide 3

Slide 3 text

State of the art IronPython Jython JRuby, Groovy, ... Self Javascript: TraceMonkey, V8 ... A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 3 / 22

Slide 4

Slide 4 text

State of the art IronPython Jython JRuby, Groovy, ... Self Javascript: TraceMonkey, V8 ... A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 3 / 22

Slide 5

Slide 5 text

Why so slow? Hard to compile efficiently Lack of type information at compile-time VMs not optimized to run them .NET is a multi-language VM? Sure, as long as the language is C# JVM is in a better shape, but still heavily optimized for Java A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 4 / 22

Slide 6

Slide 6 text

Why so slow? Hard to compile efficiently Lack of type information at compile-time VMs not optimized to run them .NET is a multi-language VM? Sure, as long as the language is C# JVM is in a better shape, but still heavily optimized for Java A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 4 / 22

Slide 7

Slide 7 text

Why so slow? Hard to compile efficiently Lack of type information at compile-time VMs not optimized to run them .NET is a multi-language VM? Sure, as long as the language is C# JVM is in a better shape, but still heavily optimized for Java A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 4 / 22

Slide 8

Slide 8 text

JIT compiler Wait until you know what you need Interweave compile-time and runtime Exploit runtime information JIT on top of .NET JIT layering How to extend existing code? Fight the VM A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 5 / 22

Slide 9

Slide 9 text

JIT compiler Wait until you know what you need Interweave compile-time and runtime Exploit runtime information JIT on top of .NET JIT layering How to extend existing code? Fight the VM A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 5 / 22

Slide 10

Slide 10 text

PyPy Python in Python (lots of features and goals) JIT compiler generator Python semantics for free JIT frontend Not limited to Python JIT backends x86 backend CLI/.NET backend Note: this talk is about JIT v2 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 6 / 22

Slide 11

Slide 11 text

PyPy Python in Python (lots of features and goals) JIT compiler generator Python semantics for free JIT frontend Not limited to Python JIT backends x86 backend CLI/.NET backend Note: this talk is about JIT v2 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 6 / 22

Slide 12

Slide 12 text

Partial evaluation (PE) Assume the Python bytecode to be constant Constant-propagate it into the Python interpreter. Colors Green: compile-time value Red: runtime value A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 7 / 22

Slide 13

Slide 13 text

Partial Evaluation with Colors Green operations: unchanged, executed at compile-time Red operations: converted into corresponding code emitting code Example def f(x, y): x2 = x * x y2 = y * y return x2 + y2 case x=10 def f_10(y): y2 = y * y return 100 + y2 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 8 / 22

Slide 14

Slide 14 text

Partial Evaluation with Colors Green operations: unchanged, executed at compile-time Red operations: converted into corresponding code emitting code Example def f(x, y): x2 = x * x y2 = y * y return x2 + y2 case x=10 def f_10(y): y2 = y * y return 100 + y2 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 8 / 22

Slide 15

Slide 15 text

Partial Evaluation with Colors Green operations: unchanged, executed at compile-time Red operations: converted into corresponding code emitting code Example def f(x, y): x2 = x * x y2 = y * y return x2 + y2 case x=10 def f_10(y): y2 = y * y return 100 + y2 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 8 / 22

Slide 16

Slide 16 text

Challenges A shortcoming of PE is that in many cases not much can be really assumed constant at compile-time: poor results Effective dynamic compilation requires feedback of runtime information into compile-time For a dynamic language: types are a primary example A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 9 / 22

Slide 17

Slide 17 text

Solution: Promotion “Promote”run-time values to compile-time Promotion guided by few hints in the interpreter Stop the compilation at promotions Execute until promotion points Compile more A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 10 / 22

Slide 18

Slide 18 text

Promotion (example) Example def f(x, y): x1 = hint(x, promote=True) return x1*x1 + y*y original def f_(x, y): switch x: pass default: compile_more(x) augmented def f_(x, y): switch x: case 3: return 9 + y*y default: compile_more(x) A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 11 / 22

Slide 19

Slide 19 text

Promotion (example) Example def f(x, y): x1 = hint(x, promote=True) return x1*x1 + y*y original def f_(x, y): switch x: pass default: compile_more(x) augmented def f_(x, y): switch x: case 3: return 9 + y*y default: compile_more(x) A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 11 / 22

Slide 20

Slide 20 text

Promotion (example) Example def f(x, y): x1 = hint(x, promote=True) return x1*x1 + y*y original def f_(x, y): switch x: pass default: compile_more(x) augmented def f_(x, y): switch x: case 3: return 9 + y*y default: compile_more(x) A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 11 / 22

Slide 21

Slide 21 text

Promotion on .NET Flexswitch Growable switch Can add new cases at runtime Ideally as efficient as a jump No support from the VM Very costly Still effective as long as it’s not in the hot path A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 12 / 22

Slide 22

Slide 22 text

Flexswitch example A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 13 / 22

Slide 23

Slide 23 text

Flexswitch example A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 14 / 22

Slide 24

Slide 24 text

Flexswitch for CLI Unit of compilation: method Flowgraphs split into multiple methods Primary method Contains a trampoline Array of delegates Secondary methods Stored into that array Jumps between secondary methods go through the trampoline Hard (and slow!) to pass arguments around A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 15 / 22

Slide 25

Slide 25 text

TLC Python not (yet) supported :-( Dynamic toy language Designed to be“as slow as Python” Stack manipulation Boxed integers Dynamic lookup of methods A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 16 / 22

Slide 26

Slide 26 text

Benchmarks (1) Factorial n 10 107 108 109 Interp 0.031 30.984 N/A N/A JIT 0.422 0.453 0.859 4.844 JIT 2 0.000 0.047 0.453 4.641 C# 0.000 0.031 0.359 3.438 Interp/JIT 2 N/A 661.000 N/A N/A JIT 2/C# N/A 1.500 1.261 1.350 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 17 / 22

Slide 27

Slide 27 text

Benchmarks (2) Fibonacci n 10 107 108 109 Interp 0.031 29.359 N/A N/A JIT 0.453 0.469 0.688 2.953 JIT 2 0.000 0.016 0.250 2.500 C# 0.000 0.016 0.234 2.453 Interp/JIT 2 N/A 1879.962 N/A N/A JIT 2/C# N/A 0.999 1.067 1.019 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 18 / 22

Slide 28

Slide 28 text

Benchmars (3) def main(n): if n < 0: n = -n obj = new(value, accumulate=count) else: obj = new(value, accumulate=add) obj.value = 0 while n > 0: n = n - 1 obj.accumulate(n) return obj.value def count(x): this.value = this.value + 1 def add(x): this.value = this.value + x A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 19 / 22

Slide 29

Slide 29 text

Benchmars (4) Accumulator n 10 107 108 109 Interp 0.031 43.063 N/A N/A JIT 0.453 0.516 0.875 4.188 JIT 2 0.000 0.047 0.453 3.672 C# 0.000 0.063 0.563 5.953 Interp/JIT 2 N/A 918.765 N/A N/A JIT 2/C# N/A 0.750 0.806 0.617 A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 20 / 22

Slide 30

Slide 30 text

Future work Non local jumps are terribly slow Good results only if they are not in the inner loop Recompile hot non-local jumps? Tracing JIT? You have just seen it in the previous talk :-) A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 21 / 22

Slide 31

Slide 31 text

Contributions JIT layering works Optimize different levels of overhead .NET’s own JIT could be improved Current VMs are limited How to make them more friendly to dynamic languges? A. Cuni, D. Ancona, A. Rigo (icooolps 09) Efficient dynamic languages on .NET July 6, 2009 22 / 22