Hi Juan,

On Tue, Mar 3, 2009 at 5:28 AM, Juan Vuletich <juan@jvuletich.org> wrote:
Hi Andreas,

Andreas Raab wrote:
...

This is tricky with MessageTally. There are several issues to keep in mind, some of which you can fix, some of which you can't. Here we go:

1) Observing all Processes
--------------------------
First, MessageTally only observes the block you are running, not the entire system. For example, if you were to profile this:

done := Semaphore new.
worker:= [
   10 timesRepeat:[World changed; displayWorld].
   done signal.
] fork.
MessageTally spyOn:[done wait].

This is what you'd get:

**Tree**
100.0% {2367ms} primitives

**Leaves**
100.0% {2367ms} UndefinedObject>>DoIt

Obviously it's not actually measuring what is going on during the period of time which is a real problem if you are trying to measure server load in general. But it's fixable.
...
I found all this stuff very interesting and useful. Thanks!

WRT issue 1), what I'd really like is the tally tree to have several roots, one for each forked process. Otherwise, the process that forks other processes would also have their tallies added to him (which is wrong, as it would appear to be using more time than it really did). Fixing this, MessageTally could give a better insight on cpu usage than #tallyCPUUsageFor:.

To do this, I'd need to find out for a certain context in the sender chain, on which process it was running. (Then, when building the tally tree, I could know that I need to add a new root.) Do you know how to find out? I spent a couple of hours on this, and it seems it is not possible...

When MessageTally runs to collect each tally the process that has been interrupted is the highest priority runnable process in the runnable process lists in ProcessorScheduler.  You could implement it like this:

!ProcessorScheduler methodsFor: 'accessing' stamp: 'eem 3/3/2009 10:41'!
highestPriorityRunnableProcess
[quiescentProcessLists reverseDo:
[:each| each isEmpty ifFalse: [^each first]]] valueUnpreemptively.
^nil

"| thisProcess interruptedProcess done |
thisProcess := Processor activeProcess.
done := false.
[(Delay forSeconds: 1) wait.
interruptedProcess := Processor highestPriorityRunnableProcess.
done := true] forkAt: Processor userInterruptPriority.
[done] whileFalse.
self assert: thisProcess == interruptedProcess"! !

So modify MessageTally (or better still create a subclass called MultiProcessMessageTally) that uses the above to manage a set of tallies for each process found while spying.

HTH




Thanks,
Juan Vuletich

Ps. I found that the problem with long primitives first appears in your 3.9.1 VM, and that BitBlt seems to slow down a bit in 3.7.1 and even more in 3.9.1. Are you planning to address this issues in the Windows VM?