[Newbies] Re: Explorer and MessageTally [was: remembering variables]
ncellier at ifrance.com
Thu Jun 5 22:19:12 UTC 2008
Herbert König a écrit :
> Hello Klaus,
> KDW> Yes, MessageTally does that for you: a tree of message sends. From the Spy
> KDW> results, you can select a class and browse it for more details, or a
> KDW> method and browse its senders or implementors for more details.
> interesting idea to use it this way! But MessageTally IMHO only shows
> what it finds on the stack when it peeks. So it can miss some methods
> running seldom and quick.
> So you can do MessageTally>>tallySends: [your tallied block] which
> uses the simulator (sloow!!) but gets you everything.
> And to be real useful with long class names and deeply nested sends
> one might have to patch some of the class side methods of MessageTally
> in the defaults category.
> After looking I see it has become better with 3.9 so the latter
> applies only for 3.8 and older.
Another possibility well beyond beginners list is the opposite, when you
want to trace senders call stack rather than sent call tree.
The idea is like putting a halt in a method and debugging, but instead
of putting a halt, you raise (signal) a Notification in the method(s)
you want to trace, and instead of a debugger at each send occurence, you
open a MessageTally for tracing the call stacks of the overall sends.
Create a subclass of Notification for that purpose, say
YourNotification, and put the sentence:
in every method or block you want to trace.
You can of course raise YourNotification conditionally like say:
yourConditionsAreFulfilled ifTrue: [YourNotification signal].
Then trap and tally YourNotification with this little code snippet
(As demonstrated at http://bugs.squeak.org/view.php?id=6755 I used it
"INITIALIZE THE TALLY (that is hackish)"
tally := MessageTally new.
tally spyEvery: 100 on: ['em ezilaitini ot si siht' reverse].
tally class: World class method: World class>>#doOneCycle.
"ARM A TIMER TO END THE TALLY"
tallyEnd := false.
[(Delay forSeconds: 300) wait. tallyEnd := true] fork.
"EMULATE REGULAR SQUEAK USER ACTIVITY LOOP"
[[World doOneCycle. Processor yield. tallyEnd] whileFalse]
"TALLY THE CALL STACK AT EACH SENT OF YOUR METHODS"
do: [:exc | tally tally: exc signalerContext by: 1.
"OPEN A WINDOW WITH TALLY CALL STACK RESULTS"
(StringHolder new contents:
(String streamContents: [:s | tally report: s]))
openLabel: 'YourNotification Spy Results'.
You put the code snippet in a workspace and execute it (DoIt).
Thanks to [World doOneCycle] emulation this enables you to run any
activity you like during the 300 seconds duration including interactive
and graphical activity but also running some SUnit tests cases if you
Thanks to YourNotification Exception handling, the tally will catch each
and every send to the method(s) of interest (where you raised
YourNotification), rather than randomly analyze callStack every few
Some core or UI activity are really impossible to debug with a halt and
step by step processing in debugger, in which case this hack is usefull.
(like tracing a Font or a Morphic bug / see
http://bugs.squeak.org/view.php?id=2084 for example).
Of course, you do not catch each and every possible send of the
method(s), but only actual send you triggered by your selected activity.
It's complementary to browsing activity when polymorphism makes it
complex to track...
You can change the 300 seconds timer at will, or end the tally manually
by executing tallyEnd := true with a doIt in the same workspace rather
than forking a timer...
If you omit the final tally close, you can also cumulate tallies by
rearming the timer and tally block (simply doIt!).
Though i tried to be didactic, I know this hack might be just too much
for this list, but isn't it amazingly clear and powerful what you can do
with Smalltalk in a few lines?
Just invent your own variations...
More information about the Beginners