Slide 1

Slide 1 text

ZipPy: A Simple Python 3 for the JVM Wei Zhang UC Irvine !1

Slide 2

Slide 2 text

Python? • Dynamic languages are here to stay • People use it too: NumPy, Django • Concise syntax, good readability • Py3k is the future !2

Slide 3

Slide 3 text

JVM, the Platform • 100+ languages • Robust Memory Management • Concurrency support • Development Productivity • Cross Platform !3

Slide 4

Slide 4 text

JVM, the Challenges • Value representation • Tagged union • Boxing for numerics • Runtime type specialization !4 small integer pointer 01 00 tagged union PyObject value all values in heap

Slide 5

Slide 5 text

Truffle Framework Python AST Interpreter with uninitialized nodes Python AST Interpreter with rewritten nodes Images from [2] [1]: S. Brunthaler, Inline Caching Meets Quickening, ECOOP 2010 [2]: T. Würthinger et al., Self-Optimizing AST Interpreters DLS 2012 !5

Slide 6

Slide 6 text

Example Python Function def  sumitup(n):      total  =  0      for  i  in  range(n):          total  =  total  +  i      return  total   !6

Slide 7

Slide 7 text

AST After Parsing FunctionRootNode      parameters  =  ParametersOfSizeOneNode          parameter  =  WriteLocalUninitializedNode              rightNode  =  ReadArgumentNode      body  =  BlockNode          statements[0]  =  WriteLocalUninitializedNode              rightNode  =  IntegerLiteralNode          statements[1]  =  ForWithLocalTargetUninitializedNode              body  =  BlockNode                  statements[0]  =  WriteLocalUninitializedNode                      rightNode  =  AddUninitializedNode                          leftNode  =  ReadLocalUninitializedNode                          rightNode  =  ReadLocalUninitializedNode              target  =  WriteLocalUninitializedNode              iterator  =  UninitializedCallFunctionNode                  callee  =  ReadGlobalScopeNode                      load  =  UninitializedLoadAttributeNode                          primary  =  ObjectLiteralNode                  arguments[0]  =  ReadLocalUninitializedNode          statements[2]  =  FrameReturnNode              right  =  WriteLocalUninitializedNode                  rightNode  =  ReadLocalUninitializedNode      returnValue  =  ReadLocalUninitializedNode !7

Slide 8

Slide 8 text

Specialized AST FunctionRootNode      parameters  =  ParametersOfSizeOneNode          parameter  =  WriteLocalIntNode              rightNode  =  ReadArgumentNode      body  =  BlockNode          statements[0]  =  WriteLocalIntNode              rightNode  =  IntegerLiteralNode          statements[1]  =  ForWithLocalTargetPRangeNode              body  =  BlockNode                  statements[0]  =  WriteLocalIntNode                      rightNode  =  AddIntNode                          leftNode  =  ReadLocalIntNode                          rightNode  =  ReadLocalIntNode              target  =  WriteLocalIntNode              iterator  =  CallBuiltInFunctionDefaultNode                  arguments[0]  =  ReadLocalIntNode          statements[2]  =  FrameReturnNode              right  =  WriteLocalIntNode                  rightNode  =  ReadLocalIntNode      returnValue  =  ReadLocalIntNode !8

Slide 9

Slide 9 text

AddNode @NodeChildren({      @NodeChild(value  =  "leftNode",  type  =  PNode.class),        @NodeChild(value  =  "rightNode",  type  =  PNode.class)})   public  abstract  static  class  AddNode  extends  PNode{   !    @Specialization(rewriteOn  =  ArithmeticException.class,  order  =  0)      int  doInteger(int  left,  int  right)  {          return  ExactMath.addExact(left,  right);      }   !    @Specialization(order  =  1)      BigInteger  doBigInteger(BigInteger  left,  BigInteger  right)  {          return  left.add(right);      }   [...]      @Generic      Object  doGeneric(Object  left,  Object  right)  {          throw  Py.TypeError("unsupported  operand  type(s)  for  +:");      }   } !9

Slide 10

Slide 10 text

Python AST Interpreter with rewritten nodes Partial Evaluation Images from [1] [1]: T. Würthinger et al., One VM to Rule Them All Onward! 2013 Compiled Python program !10

Slide 11

Slide 11 text

Example Python Function Specialized int  sumItUp(int  n)  {      int  total  =  0;   !    for  (int  i  =  0;  i  <  n;  i++)  {          total  =  total  +  i;      }   !    return  total;   }   !11

Slide 12

Slide 12 text

Machine Code for the Loop            jmp  L7   ! L6:      mov              ecx,  edx              add              ecx,  ebp              jo                L8              mov              edx,  ebp              incl            edx              mov              esi,  ebp              mov              ebp,  edx              mov              edx,  ecx   L7:      cmp              eax,  ebp              jle              L9              jmp              L6   L8:      call            deoptimize()   ! L9: !12

Slide 13

Slide 13 text

Performance of Our Example def  sumitup(n):      total  =  0      for  i  in  range(n):          total  =  total  +  i      return  total   CPython 2.7 110 sec. CPython 3.3 147 sec. PyPy 2.1 4.0 sec. ZipPy 3.8 sec. 50,000 invocations of sumitup(50,000) Peak performance after warmup runs, so that method is compiled !13

Slide 14

Slide 14 text

Call Graph Image from [1] !14 [1]: T. Würthinger et al., One VM to Rule Them All Onward! 2013 spam ham egg

Slide 15

Slide 15 text

Call Inlining Image from [1] !15 [1]: T. Würthinger et al., One VM to Rule Them All Onward! 2013 spam ham egg egg

Slide 16

Slide 16 text

Example with Call def  add(left,  right):      return  left  +  right   ! def  sumitup(n):      total  =  0      for  i  in  range(n):          total  =  add(total,  i)      return  total   !16

Slide 17

Slide 17 text

AST After Parsing FunctionRootNode      parameters  =  ParametersOfSizeOneNode          parameter  =  WriteLocalUninitializedNode              rightNode  =  ReadArgumentNode      body  =  BlockNode          statements[0]  =  WriteLocalUninitializedNode              rightNode  =  IntegerLiteralNode          statements[1]  =  ForWithLocalTargetUninitializedNode              body  =  BlockNode                  statements[0]  =  WriteLocalUninitializedNode                      rightNode  =  UninitializedCallFunctionNode                          callee  =  ReadGlobalScopeNode                              load  =  UninitializedLoadAttributeNode                                  primary  =  ObjectLiteralNode                          arguments[0]  =  ReadLocalUninitializedNode                          arguments[1]  =  ReadLocalUninitializedNode              target  =  WriteLocalUninitializedNode              iterator  =  UninitializedCallFunctionNode                  callee  =  ReadGlobalScopeNode                      load  =  UninitializedLoadAttributeNode                          primary  =  ObjectLiteralNode                  arguments[0]  =  ReadLocalUninitializedNode          statements[2]  =  FrameReturnNode              right  =  WriteLocalUninitializedNode                  rightNode  =  ReadLocalUninitializedNode      returnValue  =  ReadLocalUninitializedNode !17

Slide 18

Slide 18 text

Call Inlined FunctionRootNode      parameters  =  ParametersOfSizeOneNode          parameter  =  WriteLocalIntNode              rightNode  =  ReadArgumentNode      body  =  BlockNode          statements[0]  =  WriteLocalIntNode              rightNode  =  IntegerLiteralNode          statements[1]  =  ForWithLocalTargetPRangeNode              body  =  BlockNode                  statements[0]  =  WriteLocalIntNode                      rightNode  =  CallFunctionNoKeywordInlinedNode                          callee  =  ReadGlobalDirectNode                              load  =  LoadObjectAttributeNode                                  primary  =  ObjectLiteralNode                          functionRoot  =  InlinedFunctionRootNode                              parameters  =  ParametersOfSizeTwoNode                                  param0  =  WriteLocalIntNode                                      rightNode  =  ReadArgumentNode                                  param1  =  WriteLocalIntNode                                      rightNode  =  ReadArgumentNode                              body  =  BlockNode                                  statements[0]  =  FrameReturnNode                                      right  =  WriteLocalIntNode                                          rightNode  =  AddIntNode                                              leftNode  =  ReadLocalIntNode                                              rightNode  =  ReadLocalIntNode                              returnValue  =  ReadLocalIntNode                          arguments[0]  =  ReadLocalIntNode                          arguments[1]  =  ReadLocalIntNode              target  =  WriteLocalIntNode              iterator  =  CallBuiltInFunctionDefaultNode                  arguments[0]  =  ReadLocalIntNode          statements[2]  =  FrameReturnNode              right  =  WriteLocalIntNode                  rightNode  =  ReadLocalIntNode      returnValue  =  ReadLocalIntNode !18

Slide 19

Slide 19 text

Machine Code for the Loop            jmp  L7   ! L6:      mov              ecx,  edx              add              ecx,  ebp              jo                L8              mov              edx,  ebp              incl            edx              mov              esi,  ebp              mov              ebp,  edx              mov              edx,  ecx   L7:      cmp              eax,  ebp              jle              L9              jmp              L6   L8:      call            deoptimize()   ! L9: Same as the version without call !19

Slide 20

Slide 20 text

Performance of Our Example def  sumitup(n):      total  =  0      for  i  in  range(n):          total  =  total  +  i      return  total   without call with call CPython 2.7 110 sec. 305 sec. CPython 3.3 147 sec. 330 sec. PyPy 2.1 4.0 sec. 4.4 sec. ZipPy 3.8 sec. 3.8 sec. 50,000 invocations of sumitup(50,000) Peak performance after warmup runs, so that method is compiled def  add(left,  right):      return  left  +  right   ! def  sumitup(n):      total  =  0      for  i  in  range(n):          total  =  add(total,  i)      return  total   !20

Slide 21

Slide 21 text

Running Benchmarks 1 1 1 1.7 0.8 1.3 3.2 11 120 8.2 3.5 58 0 20 40 60 80 100 120 140 binarytrees nbody spectralnorm CPython 3.3 Jython 2.7 PyPy 2.1 Truffle (ZipPy) Speedup relative to CPython 3.3 !21

Slide 22

Slide 22 text

ZipPy > hg clone https://bitbucket.org/ssllab/zippy > cd zippy > ./mx.py build > ./mx.py python graal/edu.uci.python.benchmark/src/micro/for_range.py > ./mx.py ideinit !22

Slide 23

Slide 23 text

Thank You !23

Slide 24

Slide 24 text

ZipPy > hg clone https://bitbucket.org/ssllab/zippy > cd zippy > ./mx.py build > ./mx.py python graal/edu.uci.python.benchmark/src/micro/for_range.py > ./mx.py ideinit !24 Oracle Labs is looking for summer intern 2014 Christian Wimmer