Author: Maciej Fijalkowski <fij...@gmail.com>
Branch: extradoc
Changeset: r5540:ea1511561764
Date: 2015-07-15 12:51 +0200
http://bitbucket.org/pypy/extradoc/changeset/ea1511561764/

Log:    merge

diff --git a/talk/ep2015/pypy-abstract.rst b/talk/ep2015/pypy-abstract.rst
new file mode 100644
--- /dev/null
+++ b/talk/ep2015/pypy-abstract.rst
@@ -0,0 +1,22 @@
+=============================
+PyPy for mediocre programmers
+=============================
+
+This is a talk for mediocre Python programmers by a mediocre programmer.  PyPy
+is an alternative implementation of Python. It is notorious for being fast, but
+also for using clever algorithms pertaining to advanced concepts such as type
+inference, garbage collection, just-in-time compilation, etc. So, can we,
+mediocre programmers, realistically use PyPy?
+
+Yes, absolutely. In fact, PyPy developers did all that hard work so that we
+wouldn't have to. As we'll see, it runs most Python code exactly like CPython
+does, save that it magically makes it faster.
+
+Porting existing applications is always more involved than running a simple
+script, so we'll also examine likely difficulties such as code relying on
+CPython implementation details, and dependencies on C extensions, and explore
+simple principles to let PyPy run your code even faster.
+
+Finally, we'll have a glimpse of the future by looking at what's brewing in 
+the PyPy lair, such as software transactional memory, new speed optimisations,
+better support for Python 3 and NumPy, ...
diff --git a/talk/pycon-italy-2015/Makefile b/talk/pycon-italy-2015/Makefile
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/Makefile
@@ -0,0 +1,18 @@
+# you can find rst2beamer.py here:
+# http://codespeak.net/svn/user/antocuni/bin/rst2beamer.py
+
+# WARNING: to work, it needs this patch for docutils
+# 
https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414
+
+talk.pdf: talk.rst author.latex title.latex stylesheet.latex
+       python `which rst2beamer.py` --stylesheet=stylesheet.latex 
--documentoptions=14pt talk.rst talk.latex || exit
+       #/home/antocuni/.virtualenvs/rst2beamer/bin/python `which 
rst2beamer.py` --stylesheet=stylesheet.latex --documentoptions=14pt talk.rst 
talk.latex || exit
+       sed 's/\\date{}/\\input{author.latex}/' -i talk.latex || exit
+       #sed 's/\\maketitle/\\input{title.latex}/' -i talk.latex || exit
+       pdflatex talk.latex  || exit
+
+view: talk.pdf
+       evince talk.pdf &
+
+xpdf: talk.pdf
+       xpdf talk.pdf &
diff --git a/talk/pycon-italy-2015/author.latex 
b/talk/pycon-italy-2015/author.latex
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/author.latex
@@ -0,0 +1,8 @@
+\definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0}
+
+\title[PyPy JIT]{PyPy JIT (not) for dummies}
+\author[antocuni]
+{Antonio Cuni}
+
+\institute{PyCon Sei}
+\date{April 17, 2015}
diff --git a/talk/pycon-italy-2015/beamerdefs.txt 
b/talk/pycon-italy-2015/beamerdefs.txt
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/beamerdefs.txt
@@ -0,0 +1,108 @@
+.. colors
+.. ===========================
+
+.. role:: green
+.. role:: red
+
+
+.. general useful commands
+.. ===========================
+
+.. |pause| raw:: latex
+
+   \pause
+
+.. |small| raw:: latex
+
+   {\small
+
+.. |end_small| raw:: latex
+
+   }
+
+.. |scriptsize| raw:: latex
+
+   {\scriptsize
+
+.. |end_scriptsize| raw:: latex
+
+   }
+
+.. |strike<| raw:: latex
+
+   \sout{
+
+.. closed bracket
+.. ===========================
+
+.. |>| raw:: latex
+
+   }
+
+
+.. example block
+.. ===========================
+
+.. |example<| raw:: latex
+
+   \begin{exampleblock}{
+
+
+.. |end_example| raw:: latex
+
+   \end{exampleblock}
+
+
+
+.. alert block
+.. ===========================
+
+.. |alert<| raw:: latex
+
+   \begin{alertblock}{
+
+
+.. |end_alert| raw:: latex
+
+   \end{alertblock}
+
+
+
+.. columns
+.. ===========================
+
+.. |column1| raw:: latex
+
+   \begin{columns}
+      \begin{column}{0.45\textwidth}
+
+.. |column2| raw:: latex
+
+      \end{column}
+      \begin{column}{0.45\textwidth}
+
+
+.. |end_columns| raw:: latex
+
+      \end{column}
+   \end{columns}
+
+
+
+.. |snake| image:: ../../img/py-web-new.png
+           :scale: 15%
+           
+
+
+.. nested blocks
+.. ===========================
+
+.. |nested| raw:: latex
+
+   \begin{columns}
+      \begin{column}{0.85\textwidth}
+
+.. |end_nested| raw:: latex
+
+      \end{column}
+   \end{columns}
diff --git a/talk/pycon-italy-2015/jit-overview.odg 
b/talk/pycon-italy-2015/jit-overview.odg
new file mode 100644
index 
0000000000000000000000000000000000000000..43aec7c16da3c72bec87a6be52ce41969f4db8c7
GIT binary patch

[cut]

diff --git a/talk/pycon-italy-2015/jit-overview1.pdf 
b/talk/pycon-italy-2015/jit-overview1.pdf
new file mode 100644
index 
0000000000000000000000000000000000000000..6b511590edd06e9deb157eb02cecb7cf64c61926
GIT binary patch

[cut]

diff --git a/talk/pycon-italy-2015/jit-overview2.pdf 
b/talk/pycon-italy-2015/jit-overview2.pdf
new file mode 100644
index 
0000000000000000000000000000000000000000..c07d0e3948403a7c42951a65ba023311d4739ac8
GIT binary patch

[cut]

diff --git a/talk/pycon-italy-2015/jit-overview3.pdf 
b/talk/pycon-italy-2015/jit-overview3.pdf
new file mode 100644
index 
0000000000000000000000000000000000000000..277b2067bc2daf79f7696edaabd22614182e6bfa
GIT binary patch

[cut]

diff --git a/talk/pycon-italy-2015/speed.png b/talk/pycon-italy-2015/speed.png
new file mode 100644
index 
0000000000000000000000000000000000000000..e2372b9e0d5fc3fe7711b27d641d2d9706185fd3
GIT binary patch

[cut]

diff --git a/talk/pycon-italy-2015/src/decode0.py 
b/talk/pycon-italy-2015/src/decode0.py
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/src/decode0.py
@@ -0,0 +1,25 @@
+import sys
+import struct
+
+P1 = '\x0c\x00\x00\x00"\x00\x00\x00\x07\x00'
+P2 = '\x15\x00\x00\x00+\x00\x00\x00\x08\x00'
+
+PLIST = [P1, P2] * 2000
+
+def read_x(p):
+    return struct.unpack_from('l', p, 0)[0]
+
+def read_y(p):
+    return struct.unpack_from('l', p, 4)[0]
+
+def read_color(p):
+    return struct.unpack_from('i', p, 8)[0]
+
+def main():
+    res = 0
+    for p in PLIST:
+        x = read_x(p)
+        res += x
+    print res
+
+main()
diff --git a/talk/pycon-italy-2015/src/decode1.py 
b/talk/pycon-italy-2015/src/decode1.py
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/src/decode1.py
@@ -0,0 +1,41 @@
+import sys
+import struct
+
+P1 = '\x0c\x00\x00\x00"\x00\x00\x00\x07\x00'
+P2 = '\x15\x00\x00\x00+\x00\x00\x00\x08\x00'
+
+PLIST = [P1, P2] * 2000
+
+class Field(object):
+
+    def __init__(self, fmt, offset):
+        self.fmt = fmt
+        self.offset = offset
+
+
+class Message(object):
+
+    def __init__(self, name, fields):
+        self._name = name
+        self._fields = fields
+
+    def read(self, buf, name):
+        f = self._fields[name]
+        return struct.unpack_from(f.fmt, buf, f.offset)[0]
+
+
+Point = Message('Point', {
+    'x': Field('l', 0),
+    'y': Field('l', 4),
+    'color': Field('i', 8)
+    })
+
+
+def main():
+    res = 0
+    for p in PLIST:
+        x = Point.read(p, 'x')
+        res += x
+    print res
+
+main()
diff --git a/talk/pycon-italy-2015/src/decode2.py 
b/talk/pycon-italy-2015/src/decode2.py
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/src/decode2.py
@@ -0,0 +1,42 @@
+import sys
+import struct
+
+P1 = '\x0c\x00\x00\x00"\x00\x00\x00\x07\x00'
+P2 = '\x15\x00\x00\x00+\x00\x00\x00\x08\x00'
+
+PLIST = [P1, P2] * 2000
+
+class Field(object):
+
+    def __init__(self, fmt, offset):
+        self.fmt = fmt
+        self.offset = offset
+
+def Message(name, fields):
+    class M(object):
+        def read(self, buf, name):
+            f = getattr(self, name)
+            return struct.unpack_from(f.fmt, buf, f.offset)[0]            
+
+    for fname, f in fields.iteritems():
+        setattr(M, fname, f)
+
+    M.__name__ = name
+    return M()
+
+
+Point = Message('Point', {
+    'x': Field('l', 0),
+    'y': Field('l', 4),
+    'color': Field('i', 8)
+    })
+
+
+def main():
+    res = 0
+    for p in PLIST:
+        x = Point.read(p, 'x')
+        res += x
+    print res
+
+main()
diff --git a/talk/pycon-italy-2015/src/decode3.py 
b/talk/pycon-italy-2015/src/decode3.py
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/src/decode3.py
@@ -0,0 +1,32 @@
+import sys
+import struct
+
+P1 = '\x0c\x00\x00\x00"\x00\x00\x00\x07\x00'
+P2 = '\x15\x00\x00\x00+\x00\x00\x00\x08\x00'
+
+PLIST = [P1, P2] * 2000
+
+class Field(object):
+    def __init__(self, fmt, offset):
+        self.fmt = fmt
+        self.offset = offset
+
+    def __get__(self, obj, cls):
+        return struct.unpack_from(self.fmt, obj._buf, self.offset)[0]
+
+class Point(object):
+    def __init__(self, buf):
+        self._buf = buf
+
+    x = Field('l', 0)
+    y = Field('l', 4)
+    color = Field('h', 8)
+
+def main():
+    res = 0
+    for p in PLIST:
+        p = Point(p)
+        res += p.x
+    print res
+
+main()
diff --git a/talk/pycon-italy-2015/stylesheet.latex 
b/talk/pycon-italy-2015/stylesheet.latex
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/stylesheet.latex
@@ -0,0 +1,10 @@
+\usetheme{Boadilla}
+\setbeamercovered{transparent}
+\setbeamertemplate{navigation symbols}{}
+
+\definecolor{darkgreen}{rgb}{0, 0.5, 0.0}
+\newcommand{\docutilsrolegreen}[1]{\color{darkgreen}#1\normalcolor}
+\newcommand{\docutilsrolered}[1]{\color{red}#1\normalcolor}
+
+\newcommand{\green}[1]{\color{darkgreen}#1\normalcolor}
+\newcommand{\red}[1]{\color{red}#1\normalcolor}
diff --git a/talk/pycon-italy-2015/talk.pdf b/talk/pycon-italy-2015/talk.pdf
new file mode 100644
index 
0000000000000000000000000000000000000000..1492bcaa865783996c4f06a4afc7eabcea54249b
GIT binary patch

[cut]

diff --git a/talk/pycon-italy-2015/talk.pdf.info 
b/talk/pycon-italy-2015/talk.pdf.info
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/talk.pdf.info
@@ -0,0 +1,11 @@
+AvailableTransitions=[Crossfade]
+TransitionDuration = 100
+EstimatedDuration = 45*60       # in seconds
+MinutesOnly = True
+
+PageProps = {
+    1: {
+    'reset': FirstTimeOnly,
+    'progress': False,
+    },
+}
diff --git a/talk/pycon-italy-2015/talk.rst b/talk/pycon-italy-2015/talk.rst
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/talk.rst
@@ -0,0 +1,580 @@
+.. include:: beamerdefs.txt
+
+================================
+PyPy JIT (not) for dummies
+================================
+
+About me
+---------
+
+- PyPy core dev
+
+- ``pdb++``, ``fancycompleter``, ...
+
+- Consultant, trainer
+
+- http://antocuni.eu
+
+
+What is PyPy
+---------------
+
+- Alternative, fast Python implementation
+
+- Performance: JIT compiler, advanced GC
+
+- STM: goodbye GIL
+
+- PyPy 2.5.1 (2.7.8)
+
+- Py3k as usual in progress (3.2.5 out, 3.3 in development)
+
+- http://pypy.org
+
+
+STM
+---
+
+- pypy-stm-2.5.1 is out
+
+  * 64 bit Linux only
+
+- no GIL!
+
+- 25-40% slowdown for single core programs
+
+  * still ``7*0.75 = 5.25x`` faster than CPython :)
+
+- parallelism up to 4 threads
+
+- concurrency slow-but-correct by default
+
+  * compared to fast-but-buggy by using threads
+
+- conflict detection
+
+- TransactionQueue: parallelize your program without using threads!
+
+
+Extension modules
+------------------
+
+- CFFI: stable, mature and widely used
+
+  * psycopg2cffi, lxml-cffi, pysdl2-cffi, etc.
+
+  * should be used even for CPython-only projects!
+
+- numpy:
+
+  * support for linalg
+
+  * support for pure Python, JIT friendly ufuncs
+
+  * object dtype in-progress
+
+- scipy: see next slide :)
+
+
+Pymetabiosis
+--------------
+
+- embed CPython in PyPy
+
+- import and use CPython modules in PyPy
+
+- ALPHA status
+
+- slow when passing arbitrary objects
+
+- but fast for numpy arrays
+
+- matplotlib and scipy works
+
+- https://github.com/rguillebert/pymetabiosis
+
+
+
+Speed: 7x faster than CPython
+-------------------------------
+
+.. image:: speed.png
+   :scale: 47%
+
+
+The JIT
+--------
+
+.. image:: jit-overview1.pdf
+   :scale: 50%
+
+
+The JIT
+--------
+
+.. image:: jit-overview2.pdf
+   :scale: 50%
+
+
+The JIT
+--------
+
+.. image:: jit-overview3.pdf
+   :scale: 50%
+
+
+JIT overview
+-------------
+
+- Tracing JIT
+
+  * detect and compile "hot" loops
+
+  * (although not only loops)
+
+- **Specialization**
+
+- Precompute as much as possible
+
+- Constant propagation
+
+- Aggressive inlining
+
+
+Specialization (1)
+-------------------
+
+- ``obj.foo()``
+
+- which code is executed? (SIMPLIFIED)
+
+  * lookup ``foo`` in obj.__dict__
+
+  * lookup ``foo`` in obj.__class__
+
+  * lookup ``foo`` in obj.__bases__[0], etc.
+
+  * finally, execute ``foo``
+
+- without JIT, you need to do these steps again and again
+
+- Precompute the lookup?
+
+
+Specialization (2)
+--------------------
+
+- pretend and assume that ``obj.__class__`` IS constant
+
+  * "promotion"
+
+- guard
+
+  * check our assumption: if it's false, bail out
+
+- now we can directly jump to ``foo`` code
+
+  * ...unless ``foo`` is in ``obj.__dict__``: GUARD!
+
+  * ...unless ``foo.__class__.__dict__`` changed: GUARD!
+
+- Too many guard failures?
+
+  * Compile some more assembler!
+
+- guards are cheap
+
+  * out-of-line guards even more
+
+
+Specialization (3)
+---------------------
+
+- who decides what to promote/specialize for?
+
+  * we, the PyPy devs :)
+
+  * heuristics
+
+- instance attributes are never promoted
+
+- class attributes are promoted by default (with some exceptions)
+
+- module attributes (i.e., globals) as well
+
+- bytecode constants
+
+
+Specialization trade-offs
+--------------------------
+
+- Too much specialization
+
+  * guards fails often
+
+  * explosion of assembler
+
+- Not enough specialization
+
+  * inefficient code
+
+
+Virtuals
+--------
+
+- Remove unnecessary allocations
+
+- Remove unnecessary load/store
+
+|small|
+|example<| |small| virtuals.py |end_small| |>|
+
+.. sourcecode:: python
+
+    res = 0
+    while res < 10000:
+        obj = Foo(x, y, z)
+        res += obj.x
+
+|end_example|
+|end_small|
+
+
+Example
+--------
+
+- Real world example
+
+- Decoding binary messages
+
+- Messages: strings of bytes
+
+|small|
+|example<| |small| Point |end_small| |>|
+
+.. sourcecode:: C
+
+    struct Point {
+        int x;
+        int y;
+        short color;
+    }
+
+|end_example|
+|end_small|
+
+
+
+Example: low-level solution
+----------------------------
+
+|scriptsize|
+|example<| |small| decode0.py |end_small| |>|
+
+.. sourcecode:: python
+
+    P1 = '\x0c\x00\x00\x00"\x00\x00\x00\x07\x00\x00\x00'
+    P2 = '\x15\x00\x00\x00+\x00\x00\x00\x08\x00\x00\x00'
+    
+    PLIST = [P1, P2] * 2000
+    
+    def read_x(p):
+        return struct.unpack_from('l', p, 0)[0]
+    
+    def main():
+        res = 0
+        for p in PLIST:
+            x = read_x(p)
+            res += x
+        print res
+
+|end_example|
+|end_scriptsize|
+
+Example: low-level solution
+----------------------------
+
+|scriptsize|
+|example<| |small| decode0.py trace |end_small| |>|
+
+.. sourcecode:: python
+
+    debug_merge_point(1, 1, '<code object read_x> #0 LOAD_GLOBAL')
+    debug_merge_point(1, 1, '<code object read_x> #3 LOOKUP_METHOD')
+    debug_merge_point(1, 1, '<code object read_x> #6 LOAD_CONST')
+    debug_merge_point(1, 1, '<code object read_x> #9 LOAD_FAST')
+    debug_merge_point(1, 1, '<code object read_x> #12 LOAD_CONST')
+    debug_merge_point(1, 1, '<code object read_x> #15 CALL_METHOD')
+    +606: i91 = strlen(p88)
+    +609: i92 = int_lt(i91, 4)
+    guard_false(i92, descr=<Guard0xb3a14b20>)
+    +618: i93 = strgetitem(p88, 0)
+    +622: i94 = strgetitem(p88, 1)
+    +632: i95 = int_lshift(i94, 8)
+    +635: i96 = int_or(i93, i95)
+    +637: i97 = strgetitem(p88, 2)
+    +653: i98 = int_lshift(i97, 16)
+    +656: i99 = int_or(i96, i98)
+    +658: i100 = strgetitem(p88, 3)
+    +662: i101 = int_ge(i100, 128)
+    guard_false(i101, descr=<Guard0xb3a14ac0>)
+    +674: i102 = int_lshift(i100, 24)
+    +677: i103 = int_or(i99, i102)
+    
+|end_example|
+|end_scriptsize|
+
+Example: better API
+---------------------
+
+|scriptsize|
+|example<| |small| decode1.py |end_small| |>|
+
+.. sourcecode:: python
+
+    class Field(object):
+        def __init__(self, fmt, offset):
+            self.fmt = fmt; self.offset = offset
+
+    class Message(object):
+        def __init__(self, name, fields):
+            self._name = name; self._fields = fields
+    
+        def read(self, buf, name):
+            f = self._fields[name]
+            return struct.unpack_from(f.fmt, buf, f.offset)[0]
+
+    Point = Message('Point', {'x': Field('l', 0), 
+                              'y': Field('l', 8),
+                              'color': Field('i', 16)})
+
+    def main():
+        res = 0
+        for p in PLIST:
+            x = Point.read(p, 'x')
+            res += x
+        print res
+
+|end_example|
+|end_scriptsize|
+
+Example: better API
+----------------------------
+
+|scriptsize|
+|example<| |small| decode1.py trace (1) |end_small| |>|
+
+.. sourcecode:: python
+
+    debug_merge_point(1, 1, '<code object read> #34 CALL_METHOD')
+    p156 = getfield_gc_pure(p154, descr=<W_BytesObject.inst__value 8>)
+    i157 = getfield_gc_pure(p155, descr=<W_IntObject.inst_intval 8>)
+    p158 = new_with_vtable(-1228074336)
+    setfield_gc(p158, 0, descr=<CalcSizeFormatIterator.inst_totalsize 8>)
+    call(interpret_trampoline__v238___simple_call__function_i, p158, p156, ...)
+    guard_no_exception(descr=<Guard0xb3a8cd00>)
+    i159 = getfield_gc(p158, descr=<CalcSizeFormatIterator.inst_totalsize 8>)
+    i160 = int_lt(i157, 0)
+    guard_false(i160, descr=<Guard0xb3a8ccd0>)
+    i161 = strlen(p141)
+    i162 = int_sub(i161, i157)
+    i163 = int_lt(i162, i159)
+    guard_false(i163, descr=<Guard0xb3a8cca0>)
+    i164 = int_ge(i159, 0)
+    guard_true(i164, descr=<Guard0xb3a8cc70>)
+    p165 = force_token()
+    p166 = new_with_vtable(-1228077368)
+    p167 = new_with_vtable(-1228077280)
+    p168 = new_with_vtable(-1228267680)
+    setfield_gc(p167, 1, descr=<FieldU 
rpython.rlib.buffer.Buffer.inst_readonly 8>)
+|end_example|
+|end_scriptsize|
+
+Example: better API
+----------------------------
+
+|scriptsize|
+|example<| |small| decode1.py trace (2) |end_small| |>|
+
+.. sourcecode:: python
+
+    p169 = new(descr=<SizeDescr 12>)
+    p170 = new_array_clear(0, descr=<ArrayP 4>)
+    p171 = new_with_vtable(-1229823908)
+    setfield_gc(p171, p145, descr=<JitVirtualRef.virtual_token 8>)
+    setfield_gc(p171, p145, descr=<JitVirtualRef.virtual_token 8>)
+    setfield_gc(p171, ConstPtr(null), descr=<FieldP JitVirtualRef.forced 12>)
+    setfield_gc(p51, p171, descr=<ExecutionContext.inst_topframeref 40>)
+    setfield_gc(p0, p165, descr=<PyFrame.vable_token 8>)
+    setfield_gc(p168, 1, descr=<Buffer.inst_readonly 8>)
+    setfield_gc(p168, p141, descr=<StringBuffer.inst_value 12>)
+    setfield_gc(p167, p168, descr=<SubBuffer.inst_buffer 12>)
+    setfield_gc(p167, i157, descr=<SubBuffer.inst_offset 16>)
+    setfield_gc(p167, i159, descr=<SubBuffer.inst_size 20>)
+    setfield_gc(p166, p167, descr=<UnpackFormatIterator.inst_buf 8>)
+    setfield_gc(p166, i159, descr=<UnpackFormatIterator.inst_length 12>)
+    setfield_gc(p166, 0, descr=<UnpackFormatIterator.inst_pos 16>)
+    setfield_gc(p169, 0, descr=<list.length 4>)
+    setfield_gc(p169, p170, descr=<list.items 8>)
+    setfield_gc(p166, p169, descr=<UnpackFormatIterator.inst_result_w 20>)
+
+|end_example|
+|end_scriptsize|
+
+
+Example: better API
+----------------------------
+
+|scriptsize|
+|example<| |small| decode1.py trace (3) |end_small| |>|
+
+.. sourcecode:: python
+
+    call_may_force(interpret_trampoline__v628___simple_call__function_i), 
p166, p156, descr=<Callv 0 rr EF=6>)
+    guard_not_forced(descr=<Guard0xb3a8b9d0>)
+    guard_no_exception(descr=<Guard0xb3a8cc40>)
+    p172 = getfield_gc(p166, descr=<UnpackFormatIterator.inst_result_w 20>)
+    i173 = getfield_gc(p172, descr=<list.length 4>)
+    p174 = new_array_clear(i173, descr=<ArrayP 4>)
+    p175 = getfield_gc(p172, descr=<list.items 8>)
+    call(ll_arraycopy__arrayPtr_arrayPtr_Signed_Signed_Signed), p175, p174, 0, 
0, i173, descr=<Callv 0 rriii EF=2 OS=1>)
+    i176 = int_eq(i173, 2)
+    guard_false(i176, descr=<Guard0xb3a8cc10>)
+
+|end_example|
+|end_scriptsize|
+
+Example: faster API
+---------------------
+
+|scriptsize|
+|example<| |small| decode2.py |end_small| |>|
+
+.. sourcecode:: python
+
+    def Message(name, fields):
+        class M(object):
+            def read(self, buf, name):
+                f = getattr(self, name)
+                return struct.unpack_from(f.fmt, buf, f.offset)[0]            
+    
+        for fname, f in fields.iteritems():
+            setattr(M, fname, f)
+    
+        M.__name__ = name
+        return M()
+    
+    Point = Message('Point', {
+        'x': Field('l', 0),
+        'y': Field('l', 4),
+        'color': Field('i', 8)
+        })
+    
+     ...
+     x = Point.read(p, 'x')
+     ...
+
+|end_example|
+|end_scriptsize|
+
+Example: faster API
+----------------------------
+
+|scriptsize|
+|example<| |small| decode2.py trace (3) |end_small| |>|
+
+.. sourcecode:: python
+
+    debug_merge_point(1, 1, '<code object read> #36 CALL_METHOD')
+    +670: i104 = strlen(p101)
+    +673: i105 = int_lt(i104, 4)
+    guard_false(i105, descr=<Guard0xb3afac10>)
+    +682: i106 = strgetitem(p101, 0)
+    +686: i107 = strgetitem(p101, 1)
+    +696: i108 = int_lshift(i107, 8)
+    +699: i109 = int_or(i106, i108)
+    +701: i110 = strgetitem(p101, 2)
+    +717: i111 = int_lshift(i110, 16)
+    +720: i112 = int_or(i109, i111)
+    +722: i113 = strgetitem(p101, 3)
+    +726: i114 = int_ge(i113, 128)
+    guard_false(i114, descr=<Guard0xb3afabe0>)
+    +738: i115 = int_lshift(i113, 24)
+    +741: i116 = int_or(i112, i115)
+
+|end_example|
+|end_scriptsize|
+
+What happened?
+---------------
+
+- dict lookups inside classes are specialized
+
+- decode1.py
+
+  * ``fields`` is "normal data" and expected to change
+
+  * one JIT code for **all** possible messages
+
+- decode2.py
+
+  * ``fields`` is expected to be constant
+
+  * one JIT code for **each** message
+
+- Behaviour is the same, different performance
+
+
+Example: even better API :)
+-----------------------------
+
+|scriptsize|
+|example<| |small| decode3.py |end_small| |>|
+
+.. sourcecode:: python
+
+    class Field(object):
+        def __init__(self, fmt, offset):
+            self.fmt = fmt
+            self.offset = offset
+    
+        def __get__(self, obj, cls):
+            return struct.unpack_from(self.fmt, obj._buf, self.offset)[0]
+    
+    class Point(object):
+        def __init__(self, buf):
+            self._buf = buf
+    
+        x = Field('l', 0)
+        y = Field('l', 4)
+        color = Field('h', 8)
+    
+    def main():
+        res = 0
+        for p in PLIST:
+            p = Point(p)
+            res += p.x
+        print res
+
+|end_example|
+|end_scriptsize|
+
+
+
+Contacts, Q&A
+--------------
+
+- http://pypy.org
+
+- http://morepypy.blogspot.com/
+
+- twitter: @antocuni
+
+- Available for consultancy & training:
+
+  * http://antocuni.eu
+
+  * i...@antocuni.eu
+
+- Any question?
+
diff --git a/talk/pycon-italy-2015/title.latex 
b/talk/pycon-italy-2015/title.latex
new file mode 100644
--- /dev/null
+++ b/talk/pycon-italy-2015/title.latex
@@ -0,0 +1,5 @@
+\begin{titlepage}
+\begin{figure}[h]
+\includegraphics[width=80px]{../img/py-web.png}
+\end{figure}
+\end{titlepage}
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to