[Stackless] tracing Stackless events
Andrew Dalke
dalke at dalkescientific.com
Tue Dec 18 02:17:16 CET 2007
Here's a module which does a more complete job of detecting trace
events in Stackless. The module includes the hooks to send events to
a single handler function, two example handler functions, and example
code which uses the "verbose" handler.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sltrace.py
Type: text/x-python-script
Size: 11583 bytes
Desc: not available
Url : http://www.stackless.com/pipermail/stackless/attachments/20071218/35bf689f/attachment.bin
-------------- next part --------------
Here is the example code so you can see the trace is generates
set_stackless_trace(verbose_dump)
def call_wrapper(f, args, kwargs, result_ch):
result_ch.send(f(*args, **kwargs), )
def call(f, *args, **kwargs):
arglist = []
for arg in args:
arglist.append(repr(arg))
for k,v in kwargs.items():
arglist.append(repr(k) + "=" + repr(v))
tasklet_name = "%s(%s)" % (f.__name__, ", ".join(arglist))
result_ch = stackless.channel()
set_channel_name(result_ch, "<%s result>" % tasklet_name)
# Use the default or -1 and the tasklet stays around
# until the end of the run.
result_ch.preference = 1
named_tasklet(tasklet_name, call_wrapper)(f, args, kwargs,
result_ch)
return result_ch.receive()
def factorial(n):
if n <= 1:
return 1
return n * call(factorial, n-1)
#print factorial(1000)
fact = factorial(4)
print "fact =", fact
stackless.schedule()
=====================
Here is the output, showing things like all the tasklets waiting for
a channel and the status of all of the tasklets for each schedule event.
Trace started
Create tasklet: 'factorial(3)' (6510448)
by: 'main' (6422768) at sltrace.py:241
Receive (will block) 'main' (6422768) at sltrace.py:241
(empty queue)
Schedule from: 'main' (6422768) at (inaccesible frame)
to: 'factorial(3)' (6510448) at sltrace.py:241
(no other tasklets)
Create tasklet: 'factorial(2)' (6510512)
by: 'factorial(3)' (6510448) at sltrace.py:241
Receive (will block) 'factorial(3)' (6510448) at sltrace.py:241
(empty queue)
Schedule from: 'factorial(3)' (6510448) at (inaccesible frame)
to: 'factorial(2)' (6510512) at sltrace.py:241
'main' (6422768) at sltrace.py:340 blocked on send
Create tasklet: 'factorial(1)' (6510576)
by: 'factorial(2)' (6510512) at sltrace.py:241
Receive (will block) 'factorial(2)' (6510512) at sltrace.py:241
(empty queue)
Schedule from: 'factorial(2)' (6510512) at (inaccesible frame)
to: 'factorial(1)' (6510576) at sltrace.py:241
'main' (6422768) at sltrace.py:340 blocked on send
'factorial(3)' (6510448) at sltrace.py:340 blocked on send
Send: 1 'factorial(1)' (6510576) at sltrace.py:241
in queue: 'factorial(2)' (6510512) at sltrace.py:340
Schedule from: 'factorial(1)' (6510576) at (unknown; dead?)
to: 'factorial(2)' (6510512) at sltrace.py:241
'main' (6422768) at sltrace.py:340 blocked on send
'factorial(3)' (6510448) at sltrace.py:340 blocked on send
Tasklet exit: 'factorial(1)' (6510576)
Send: 2 'factorial(2)' (6510512) at sltrace.py:241
in queue: 'factorial(3)' (6510448) at sltrace.py:340
Schedule from: 'factorial(2)' (6510512) at (unknown; dead?)
to: 'factorial(3)' (6510448) at sltrace.py:241
'main' (6422768) at sltrace.py:340 blocked on send
Tasklet exit: 'factorial(2)' (6510512)
Send: 6 'factorial(3)' (6510448) at sltrace.py:241
in queue: 'main' (6422768) at sltrace.py:340
Schedule from: 'factorial(3)' (6510448) at (unknown; dead?)
to: 'main' (6422768) at sltrace.py:241
(no other tasklets)
fact = 24
Tasklet exit: 'factorial(3)' (6510448)
Trace ended
======
Some problems I found:
- There's direct way to assign a "name" (or a "group") to a
tasklet or channel.
(I already reported this; used a weakref.WeakKeyDict as a
workaround.)
Possible solution: Let tasklets and channels take two optional
instance parameters, name and group. These are (readonly) attributes.
- I had to synthesize a "tasklet exit" event based on weak references
Possible solution: the set_schedule_callback should get this with
prev is not None and next is None, according to the documentation.
Figure out why this isn't the case.
- I had to work around a strange problem with Python function calls
taking place during weakref dealloc notification (see the code
with "if 0:")
Possible solution: No clue.
- the schedule callback doesn't have a 'frame' for the 'prev' tasklet
(I already reported this)
Possible solution: change the C code so the frame (and other
attributes?) are set before the call, (and unset on error?)
- I can't figure out how to get all tasklets in the system, so I
only get
all the ones which are "named" in my WeakKeyDict
Possible solution: tell me how to do that. Failing that, implement a
function which iterates over all tasklets.
- I'm using my workaround for what I assume is a gc problem
related to
my weakref of the main tasklet (I already reported this)
Possible solution: No clue. Will need to stare at C code for a while.
I also synthesize start/end events for the whole trace, but that's
perhaps YAGNI.
Try it out. let me know if it proves useful. The output's somewhat
ugly so feel free to come up with a better one. It might be useful
generate some HTML display with the tasklet information visualized as
a UML-style sequence diagram, including perhaps coloring a tasklet
uniquely based on the full stack trace of the creating tasklet and
with mouseovers for viewing more detail information at each point.
Andrew
dalke at dalkescientific.com
More information about the Stackless
mailing list