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

Let's Talk about PyPy

Let's Talk about PyPy

Invited Keynote at PyCon 2012. Santa Clara. Conference video at https://www.youtube.com/watch?v=l_HBRhcgeuQ

David Beazley

October 03, 2012
Tweet

More Decks by David Beazley

Other Decks in Programming

Transcript

  1. PyPy Project • Perhaps you've heard about PyPy • Python

    implemented in Python • It is apparently quite a bit faster • How is that possible? Magic???
  2. It's Not Slow Draw the Mandelbrot set Credit: Jeff Preshing

    CPython 2.7: 502s _ = ( 255, lambda V ,B,c :c and Y(V*V+B,B, c -1)if(abs(V)<6)else ( 2+c-4*abs(V)**-0.4)/i ) ;v, x=1500,1000;C=range(v*x );import struct;P=struct.pack;M,\ j ='<QIIHHHH',open('M.bmp','wb').write for X in j('BM'+P(M,v*x*3+26,26,12,v,x,1,24))or C: i ,Y=_;j(P('BBB',*(lambda T:(T*80+T**9 *i-950*T **99,T*70-880*T**18+701* T **9 ,T*i**(1-T**45*2)))(sum( [ Y(0,(A%3/3.+X%v+(X/v+ A/3/3.-x/2)/1j)*2.5 /x -2.7,i)**2 for \ A in C [:9]]) /9) ) )
  3. It's Not Slow Draw the Mandelbrot set Credit: Jeff Preshing

    CPython 2.7: 502s _ = ( 255, lambda V ,B,c :c and Y(V*V+B,B, c -1)if(abs(V)<6)else ( 2+c-4*abs(V)**-0.4)/i ) ;v, x=1500,1000;C=range(v*x );import struct;P=struct.pack;M,\ j ='<QIIHHHH',open('M.bmp','wb').write for X in j('BM'+P(M,v*x*3+26,26,12,v,x,1,24))or C: i ,Y=_;j(P('BBB',*(lambda T:(T*80+T**9 *i-950*T **99,T*70-880*T**18+701* T **9 ,T*i**(1-T**45*2)))(sum( [ Y(0,(A%3/3.+X%v+(X/v+ A/3/3.-x/2)/1j)*2.5 /x -2.7,i)**2 for \ A in C [:9]]) /9) ) ) PyPy-1.8: 203s Speedup of ~2.5x
  4. It's Not Slow Draw the Mandelbrot set (non-obfuscated) Python 2.7.2

    : 14.5s Python 2.7.2+ctypes : 0.95s PyPy-1.8 : 0.42s Yow! That's 34x faster!
  5. CPython PyPy Just in time compilation Translation to C Optimization

    ... but performance is not what this talk is about. One is clearly faster than the other...
  6. CPython PyPy • Which one can you adjust with a

    pocketknife? ... in the dark ... under a pressing deadline
  7. CPython PyPy • Which one can you adjust with a

    pocketknife? ... in the dark ... under a pressing deadline I speak from some experience...
  8. Exploring New Ideas ported to An "afternoon hack," with a

    big impact parallel Python ... we didn't choose Python for performance.
  9. CPython PyPy An honest question • Is PyPy something that

    YOU can tinker with? • As in YOU... sitting in this room. • Or is it for "evil genuises only?"
  10. A Confession • PyPy scares me • It's fast. I

    get that. • A lot of moving parts • A lot of advanced computer science inside
  11. CPython PyPy An honest question • Is PyPy something that

    YOU can tinker with? Honest answer: I don't know
  12. • See if I could teach myself to tinker with

    PyPy • From scratch (I'm not a PyPy developer) • Use nothing but the source, online docs, etc. An Experiment:
  13. Tinkering with PyPy != Using PyPy • If you want

    to use it, just run it • It's Python. • Not so interesting (not as much as tinkering) bash % pypy gofaster.py
  14. Tinkering with PyPy != Creating PyPy • submit a useful

    bug report (or patch) • Make extensions • Study parts of the implementation (GIL, etc.) • Post messages on [email protected]
  15. Where To Start? • Tinkerers use source • You build

    it yourself! • You read instructions http://pypy.org Go Download it. Now!
  16. Running py.py • PyPy is written in "Python"... you can

    run it bash % python pypy-1.8/pypy/bin/py.py [platform:execute] gcc-4.0 -c -arch x86_64 -O frame-pointer - \ ... PyPy 1.8.0 in StdObjSpace on top of Python 2. (startuptime: 23.23 secs) >>>> • Performance is terrible! • You wouldn't do it except for debugging
  17. Translating PyPy • To get the "real" version, you translate

    it • Huh? No makefile? No setup.py? • Already, I'm getting nervous. bash % cd pypy/translator/goal bash % python translate.py -Ojit
  18. Building PyPy Some Facts: • Movie is @ 64x speed

    • Takes a few hours Contrast: Configure and build CPython-3.2.2 • ./configure; make -j8 • Takes about 90 seconds Immediate Problem: • Finding enough RAM • It takes >4GB 4 cores, 8 GB RAM EC2, m2.xlarge (17GB) What's Actually Happening • Translation of PyPy to C • Creates ~800 C files • ~10.4 million lines! • 350 Mbytes It might kill the C compiler (or your machine) • Example: gcc-4.2 This is Amazing! • Dare I say "diabolical" • If not intimidating One of the most daunting parts of PyPy • Must redo the process if you make any tweak • An obvious barrier to casual tinkering
  19. RPython • PyPy is actually implemented in "RPython" • RPython

    is not an "interpreter", but a restricted subset of the Python language Python rpython • It can run as valid Python code, but that's about the only similarity
  20. RPython • Formal specification (in their own words): "RPython is

    everything that our translation toolchain can accept"
  21. RPython • Formal specification (in their own words): "RPython is

    everything that our translation toolchain can accept" • An analogy "Python is everything that runs without generating a traceback."
  22. RPython • Formal specification (in their own words): "RPython is

    everything that our translation toolchain can accept" • An analogy "Python is everything that runs without generating a traceback." • Okay, let's go reading...
  23. Detailed Tech Reports To be fair, it was a funded

    academic project in PL. (They had to write like this)
  24. Source Code • 454 directories • 5534 files (4513 .py

    source files) • ~1.25 million non-blank source lines (.py) By The Numbers: It's not so easy to just jump in and make sense of it
  25. Reading Blogs • Recommend start: Andrew Brown • Laurence Tratt

    "Fast Enough VMs in Fast Enough Time" "Tutorial: Writing an Interpreter with PyPy" http://bit.ly/fmV2wx http://bit.ly/y8GLqf
  26. RPython in a Nutshell • RPython is a completely different

    language • Python syntax, yes. • Must be compiled (like C, C++, etc.) • Static typing via type inference • Limited set of libraries • If you love Python, you will hate RPython
  27. Type Inference Illustrated def fib(n): if n < 2: return

    n else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0
  28. Type Inference Illustrated def fib(n): if n < 2: return

    n else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 int
  29. Type Inference Illustrated def fib(n): if n < 2: return

    n else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 int int
  30. Type Inference Illustrated def fib(n): if n < 2: return

    n else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 int int int
  31. Type Inference Illustrated def fib(n): if n < 2: return

    n else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 int int int int
  32. Type Inference Illustrated def fib(n): if n < 2: return

    n else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 int int int int int Key Point: Think static typing (like C)
  33. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement Now think about the whole program Type inference + restrictions
  34. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement There is a single spark... Entry point
  35. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement Entry point Exploration Begins
  36. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement Exploration Begins Entry point
  37. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement Entry point Exploration Begins Whole program type annotation!
  38. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement All reachable control- flow paths are followed Entry point Whole program type annotation!
  39. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement Entry point Imagine this diagram, but with tens of thousands of functions Whole program type annotation!
  40. # file1.py def name2(args): statement statement def name3(args): statement statement

    statement statement def name1(args): statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement Key Insight: Entry point All of the reachable code is RPython
  41. RPython def name1(args): statement statement statement # file1.py def name2(args):

    statement statement def name3(args): statement statement statement statement def name1(args): statement statement statement def name3(args): statement statement statement statement # file2.py def name1(args): statement statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement PyPy Source def name1(args): statement statement # file3.py def name2(args): statement statement def name3(args): statement statement def name4(args): statement statement class B(object): def method1(self,args): statement statement statement def method2(self,args): statement statement def name1(args): statement statement def name2(args): statement statement def name4(args): statement statement Translation C Compile pypy-c Entry point
  42. Understanding Translation • The translation process will blow your mind

    • Full understanding by mortals is probably futile • Snakes + Souls of Ph.D. students inside? • Let's look at a small taste...
  43. A Function def fib(n): if n < 2: return n

    else: return fib(n-1) + fib(n-2) Obvious question: How does it translate to C?
  44. Traditional Compiler def fib(n): if n < 2: return n

    else: return fib(n-1) + fib(n-2) Lexer Parser IR C You might think it's like a traditional compiler.
  45. Traditional Compiler def fib(n): if n < 2: return n

    else: return fib(n-1) + fib(n-2) Lexer Parser IR C You might think it's like a traditional compiler. (and you would be wrong)
  46. Traditional Compiler IR def fib(n): if n < 2: return

    n else: return fib(n-1) + fib(n-2) Lexer Parser C Insight: Python already parsed the code! ... so don't do it again. ?????
  47. RPython Translation IR C Translation occurs directly from Python code

    objects >>> fib.__code__.co_code '|\x00\x00d\x01\x00k\x00\x00r\x10\x00 d\x02\x00St\x00\x00|\x00\x00d\x02\x00 \x18\x83\x01\x00t\x00\x00|\x00\x00d \x01\x00\x18\x83\x01\x00\x17Sd\x00\x00S'
  48. Bytecode Interpretation CPython • Python has a bytecode interpreter •

    Core of the eval loop (written in C). bytecode interpreter runtime
  49. Bytecode Interpretation CPython • It executes the bytecode bytecode interpreter

    runtime >>> fib.__code__.co_code '|\x00\x00d\x01\x00k\x00\x00r\x1 d\x02\x00St\x00\x00|\x00\x00d\x \x18\x83\x01\x00t\x00\x00|\x00\ \x01\x00\x18\x83\x01\x00\x17Sd\
  50. Bytecode Interpretation PyPy • PyPy has a bytecode interpreter too

    • Written in pure Python (that's the whole idea) bytecode interpreter runtime >>> fib.__code__.co_code '|\x00\x00d\x01\x00k\x00\x00r\x1 d\x02\x00St\x00\x00|\x00\x00d\x \x18\x83\x01\x00t\x00\x00|\x00\ \x01\x00\x18\x83\x01\x00\x17Sd\
  51. Bytecode Interpretation PyPy runtime bytecode interpreter • Bytecode interpreter is

    modular • Also used by the translate.py program translate.py bytecode interpreter abstract runtime
  52. Abstract Interpretation translate.py bytecode interpreter abstract runtime 2 0 LOAD_FAST

    0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE Translator runs the code "in the abstract"
  53. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE 2 0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE Translator runs the code "in the abstract" translate.py bytecode interpreter abstract runtime
  54. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE translate.py bytecode interpreter abstract runtime
  55. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE translate.py bytecode interpreter abstract runtime
  56. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE translate.py bytecode interpreter abstract runtime
  57. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE translate.py bytecode interpreter abstract runtime
  58. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE translate.py bytecode interpreter abstract runtime
  59. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE translate.py bytecode interpreter abstract runtime
  60. Abstract Interpretation Translator runs the code "in the abstract" 2

    0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_CONST 2 (1) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (fib) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 2 (1) 25 BINARY_SUBTRACT 26 CALL_FUNCTION 1 29 LOAD_GLOBAL 0 (fib) 32 LOAD_FAST 0 (n) 35 LOAD_CONST 1 (2) 38 BINARY_SUBTRACT 39 CALL_FUNCTION 1 42 BINARY_ADD 43 RETURN_VALUE 44 LOAD_CONST 0 (None) 47 RETURN_VALUE translate.py bytecode interpreter abstract runtime
  61. "You are in a maze of twisty little passages, all

    alike." (and a huge green fierce snake bars the way)
  62. Understanding the Source • Two different languages co-exist (same syntax)

    # file1.py def name2(args): statement statement def name3(args): statement statement statement statement def name1(args): statement statement statement Full Python???? RPython???? Which is it?
  63. Understanding the Source • Two different languages co-exist (same syntax)

    # file1.py def name2(args): statement statement def name3(args): statement statement statement statement def name1(args): statement statement statement Full Python???? RPython???? Which is it? (You can't look in isolation)
  64. Understanding the Source def cast_object_to_ptr(PTR, object): """NOT_RPYTHON: hack. The object

    may Limited to casting a given object to """ if isinstance(PTR, lltype.Ptr): TO = PTR.TO else: TO = PTR ... • PyPy uses doc strings to help you sort it out • It is enforced by the translator (an assertion)
  65. Understanding the Source • Deeper question: Why would you have

    mixed code? # file1.py def name2(args): statement statement def name3(args): statement statement statement statement def name1(args): statement statement statement RPython Python • Head throbbing...
  66. Execution Contexts # file1.py def name2(args): statement statement def name3(args):

    statement statement statement statement def name1(args): statement statement statement Translation (Python) Executable (C)
  67. Execution Contexts # file1.py def name2(args): statement statement def name3(args):

    statement statement statement statement def name1(args): statement statement statement Translation (Python) Executable (C) • At translation, the code separates Metaprogramming Implementation • decorators • metaclasses • exec()
  68. Example def decorator(func): statements ... def wrapper(*args,**kwargs): statements ... return

    func(*args,**kwargs) return wrapper @decorator def func(args): statements ...
  69. Example def decorator(func): statements ... def wrapper(*args,**kwargs): statements ... return

    func(*args,**kwargs) return wrapper @decorator def func(args): statements ... Python RPython Python RPython
  70. Rules of Thumb • Code that executes at import time

    can make use of all Python features • Code reachable through the entry point (target) is RPython • Keeping it straight is hard (for me anyways)
  71. Foreign Code • PyPy is written in "Python", but can

    access external C code and libraries • os, math, time, threads, etc. • There is a highly developed FFI mechanism • Plus a configuration system (think autoconf)
  72. A Quandary • How do I end this talk? •

    I've only talked about RPython • When do we get to the PyPy?
  73. A Clarification I do know how to use the tools

    that make CPython • ANSI C • Makefiles • Algorithms • Data Structures
  74. The Challenge PyPy has a different set of tools •

    RPython • translate.py • Metaprogramming • Foreign Functions
  75. Breaking GILs • As you know, I like breaking GILs

    • You know, global interpreter locks • As in threads and stuff... • I love it!
  76. A Benchmark • Message-passing with a CPU-bound thread C :

    1.11s Python 2.7 : 1.60s Ruby 1.9 : 5839.4s • Don't concern yourself with the details • Ruby 3600x slower than Python? • What's that all about? Let's go tinker!
  77. Tinkering with Ruby • It was pretty straightforward • Finding

    the GIL didn't take long • An afternoon of fiddling around (Search for my talk at RuPy 2011) • Caused by a more extreme case of the thread priority inversion that's in Python 3.3
  78. Just to be clear... I couldn't write a real Ruby

    program to save my life right now.
  79. A PyPy Benchmark • A similar message-passing benchmark Python 2.7

    : 15.6s PyPy-1.6 : 6689.2s (428x slower) • Huh? What's that all about? • No idea! Or even how to look. • That is the whole reason for this talk
  80. Parting Words • Can you tinker with PyPy? • Honest

    answer: I still don't know • Should you try to go tinker with it anyways? • YES! • You will find interesting things inside
  81. Thanks! • Hope you learned at least one new thing

    • Special thanks: • Alex Gaynor • Maciej Fijalkowski • Chipy • Twitter: @dabeaz