[pypy-svn] pypy default: merge heads

arigo commits-noreply at bitbucket.org
Tue May 3 16:16:40 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r43861:87afbf37afa2
Date: 2011-05-03 16:16 +0200
http://bitbucket.org/pypy/pypy/changeset/87afbf37afa2/

Log:	merge heads

diff --git a/pypy/doc/discussion/jit-profiler.rst b/pypy/doc/discussion/jit-profiler.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/discussion/jit-profiler.rst
@@ -0,0 +1,79 @@
+A JIT-aware profiler
+====================
+
+Goal: have a profiler which is aware of the PyPy JIT and which shows which
+percentage of the time have been spent in which loops.
+
+Long term goal: integrate the data collected by the profiler with the
+jitviewer.
+
+The idea is record an event in the PYPYLOG everytime we enter and exit a loop
+or a bridge.
+
+Expected output
+----------------
+
+[100] {jit-profile-enter
+loop1      # e.g. an entry bridge
+[101] jit-profile-enter}
+...
+[200] {jit-profile-enter
+loop0      # JUMP from loop1 to loop0
+[201] jit-profile-enter}
+...
+[500] {jit-profile-exit
+loop0      # e.g. because of a failing guard
+[501] jit-profile-exit}
+
+In this example, the exiting from loop1 is implicit because we are entering
+loop0.  So, we spent 200-100=100 ticks in the entry bridge, and 500-200=300
+ticks in the actual loop.
+
+What to do about "inner" bridges?
+----------------------------------
+
+"Inner bridges" are those bridges which jump back to the loop where they
+originate from.  There are two possible ways of dealing with them:
+
+  1. we ignore them: we record when we enter the loop, but not when we jump to
+     a compiled inner bridge.  The exit event will be recorded only in case of
+     a non-compiled guard failure or a JUMP to another loop
+
+  2. we record the enter/exit of each inner bridge
+
+The disadvantage of solution (2) is that there are certain loops which takes
+bridges at everty single iteration.  So, in this case we would record a huge
+number of events, possibly adding a lot of overhead and thus making the
+profiled data useless.
+
+
+Detecting the enter to/exit from a loop
+----------------------------------------
+
+Ways to enter:
+
+    - just after the tracing/compilation
+
+    - from the interpreter, if the loop has already been compiled
+
+    - from another loop, via a JUMP operation
+
+    - from a hot guard failure (which we ignore, in case we choose solution
+      (1) above)
+
+    - XXX: am I missing anything?
+
+Ways to exit:
+
+    - guard failure (entering blackhole)
+
+    - guard failure (jumping to a bridge) (ignored in case of solution (1))
+
+    - jump to another loop
+
+    - XXX: am I missing anything?
+
+
+About call_assembler: I think that at the beginning, we should just ignore
+call_assembler: the time spent inside the call will be accounted to the loop
+calling it.
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1662,3 +1662,20 @@
         assert log.result == 300
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match_by_id('shift', "")  # optimized away
+
+    def test_division_to_rshift(self):
+        def main(b):
+            res = 0
+            a = 0
+            while a < 300:
+                assert a >= 0
+                assert 0 <= b <= 10
+                res = a/b     # ID: div
+                a += 1
+            return res
+        #
+        log = self.run(main, [3], threshold=200)
+        #assert log.result == 149
+        loop, = log.loops_by_filename(self.filepath)
+        import pdb;pdb.set_trace()
+        assert loop.match_by_id('div', "")  # optimized away


More information about the Pypy-commit mailing list