[Newbies] Re: Explorer and MessageTally [was: remembering variables]

nicolas cellier 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:
	YourNotification signal.
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 
with EndOfStream):

"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.

tallyEnd := false.
[(Delay forSeconds: 300) wait. tallyEnd := true] fork.

[[World doOneCycle. Processor yield. tallyEnd] whileFalse]
         on: YourNotification
         do: [:exc | tally tally: exc signalerContext by: 1.
             exc resume].

(StringHolder new contents:
         (String streamContents: [:s | tally report: s]))
     openLabel: 'YourNotification Spy Results'.
tally close.

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 
want to.

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=1035 or 
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 mailing list