1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 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.
|