[squeak-dev] The Trunk: System-ar.242.mcz
Eliot Miranda
eliot.miranda at gmail.com
Thu Feb 4 05:46:03 UTC 2010
Andreas,
one rationale for
...
do: [| blockScope | ... blockScope := ...]
...
over
| methodScope |
...
do: [... methodScope := ...]
is that if ever one adds parallel do to the language the former continues to
work whereas the latter breaks. Personally I find declaring things at
method scope that are truly block scope bad style and not forward looking.
Yes, the auto declare facility is poor in this regard but it's fixable.
2¢
On Wed, Feb 3, 2010 at 9:35 PM, <commits at source.squeak.org> wrote:
> Andreas Raab uploaded a new version of System to project The Trunk:
> http://source.squeak.org/trunk/System-ar.242.mcz
>
> ==================== Summary ====================
>
> Name: System-ar.242
> Author: ar
> Time: 3 February 2010, 9:34:48.402 pm
> UUID: f0907bbe-46a2-a840-bcd8-afb5a10f16b0
> Ancestors: System-dtl.241
>
> Merge latest MessageTally changes from Cuis.
>
> =============== Diff against System-dtl.241 ===============
>
> Item was added:
> + ----- Method: MessageTally>>leavesPrintExactOn: (in category 'printing')
> -----
> + leavesPrintExactOn: aStream
> + | dict |
> + dict := IdentityDictionary new: 100.
> + self leavesInto: dict fromSender: nil.
> + dict asSortedCollection
> + do: [ :node |
> + node printOn: aStream total: tally totalTime: nil
> tallyExact: true.
> + node printSenderCountsOn: aStream ]!
>
> Item was changed:
> ----- Method: MessageTally>>spyEvery:onProcess:forMilliseconds: (in
> category 'initialize-release') -----
> spyEvery: millisecs onProcess: aProcess forMilliseconds: msecDuration
> "Create a spy and spy on the given process at the specified rate."
> + | myDelay startTime time0 endTime observedProcess sem |
> - | myDelay time0 endTime sem observedProcess |
> (aProcess isKindOf: Process)
> ifFalse: [self error: 'spy needs a Process here'].
> self class: aProcess suspendedContext receiver class method:
> aProcess suspendedContext method.
> "set up the probe"
> observedProcess := aProcess.
> myDelay := Delay forMilliseconds: millisecs.
> time0 := Time millisecondClockValue.
> endTime := time0 + msecDuration.
> sem := Semaphore new.
> gcStats := SmalltalkImage current getVMParameters.
> + Timer ifNotNil: [ Timer terminate ].
> + Timer := [
> - Timer := [ | startTime |
> [
> startTime := Time millisecondClockValue.
> myDelay wait.
> + self
> + tally: Processor preemptedProcess
> suspendedContext
> + in: (observedProcess == Processor
> preemptedProcess ifTrue: [observedProcess] ifFalse: [nil])
> - self tally: Processor preemptedProcess
> suspendedContext
> - in: (ShowProcesses ifTrue: [
> - observedProcess ==
> Processor preemptedProcess ifTrue: [observedProcess] ifFalse: [nil]])
> "tally can be > 1 if ran a long
> primitive"
> by: (Time millisecondClockValue -
> startTime) // millisecs.
> startTime < endTime
> ] whileTrue.
> sem signal.
> ] newProcess.
> Timer priority: Processor timingPriority-1.
> "activate the probe and evaluate the block"
> Timer resume.
> "activate the probe and wait for it to finish"
> sem wait.
> "Collect gc statistics"
> SmalltalkImage current getVMParameters keysAndValuesDo: [ :idx
> :gcVal |
> gcStats at: idx put: (gcVal - gcStats at: idx)].
> time := Time millisecondClockValue - time0!
>
> Item was changed:
> ----- Method: MessageTally>>tally:by: (in category 'tallying') -----
> tally: context by: count
> "Explicitly tally the specified context and its stack."
> | sender |
>
> "Add to this node if appropriate"
> context method == method ifTrue: [^self bumpBy: count].
>
> "No sender? Add new branch to the tree."
> + (sender := context home sender)ifNil: [
> - (sender := context home sender)ifNil: [
> ^ (self bumpBy: count) tallyPath: context by: count].
>
> "Find the node for the sending context (or add it if necessary)"
> ^ (self tally: sender by: count) tallyPath: context by: count!
>
> Item was changed:
> ----- Method: MessageTally class>>tallySendsTo:inBlock:showTree: (in
> category 'spying') -----
> tallySendsTo: receiver inBlock: aBlock showTree: treeOption
> + "
> + MessageTally tallySends: [3.14159 printString]
> + "
> - "MessageTally tallySends: [3.14159 printString]"
> "This method uses the simulator to count the number of calls on each
> method
> invoked in evaluating aBlock. If receiver is not nil, then only
> sends
> to that receiver are tallied.
> Results are presented as leaves, sorted by frequency,
> preceded, optionally, by the whole tree."
> | prev tallies startTime totalTime |
> startTime := Time millisecondClockValue.
> + tallies := MessageTally new class: aBlock receiver class method:
> aBlock method.
> + tallies reportOtherProcesses: true. "Do NOT filter nodes with
> nil process"
> - tallies := MessageTally new class: aBlock receiver class
> - method: aBlock
> method.
> prev := aBlock.
> thisContext sender
> runSimulated: aBlock
> contextAtEachStep:
> [:current |
> current == prev ifFalse:
> ["call or return"
> prev sender == nil ifFalse:
> ["call only"
> (receiver == nil or: [current
> receiver == receiver])
> ifTrue: [tallies tally:
> current by: 1]].
> prev := current]].
>
> totalTime := Time millisecondClockValue - startTime // 1000.0
> roundTo: 0.01.
> (StringHolder new contents:
> (String streamContents:
> [:s |
> s nextPutAll: 'This simulation took ' , totalTime
> printString
> , ' seconds.'; cr.
> treeOption
> + ifTrue: [ tallies fullPrintExactOn: s ]
> + ifFalse: [ tallies leavesPrintExactOn: s ].
> + tallies close ]))
> - ifTrue: [tallies fullPrintOn: s tallyExact:
> true orThreshold: 0]
> - ifFalse: [tallies leavesPrintOn: s
> tallyExact: true orThreshold: 0].
> - tallies close]))
> openLabel: 'Spy Results'!
>
> Item was added:
> + ----- Method: MessageTally>>rootPrintOn:total:totalTime:threshold: (in
> category 'printing') -----
> + rootPrintOn: aStream total: total totalTime: totalTime threshold:
> threshold
> +
> + | sons groups p |
> + sons := self sonsOver: threshold.
> + groups := sons groupBy: [ :aTally | aTally process] having: [ :g |
> true].
> + groups do:[:g|
> + sons := g asSortedCollection.
> + p := g anyOne process.
> + (reportOtherProcesses or: [ p notNil ]) ifTrue: [
> + aStream nextPutAll:
> '--------------------------------'; cr.
> + aStream nextPutAll: 'Process: ', (p ifNil: [
> 'other processes'] ifNotNil: [ p browserPrintString]); cr.
> + aStream nextPutAll:
> '--------------------------------'; cr.
> + (1 to: sons size) do:[:i |
> + (sons at: i)
> + treePrintOn: aStream
> + tabs: OrderedCollection new
> + thisTab: ''
> + total: total
> + totalTime: totalTime
> + tallyExact: false
> + orThreshold: threshold]].
> + ]!
>
> Item was added:
> + ----- Method: MessageTally class>>spyOn:toFileNamed:reportOtherProcesses:
> (in category 'spying') -----
> + spyOn: aBlock toFileNamed: fileName reportOtherProcesses: aBoolean
> + "Spy on the evaluation of aBlock. Write the data collected on a
> file
> + named fileName."
> +
> + | file value node |
> + node := self new.
> + node reportOtherProcesses: aBoolean.
> + value := node spyEvery: self defaultPollPeriod on: aBlock.
> + file := FileStream newFileNamed: fileName.
> + node report: file; close.
> + file close.
> + ^value!
>
> Item was changed:
> ----- Method: MessageTally>>spyAllEvery:on: (in category
> 'initialize-release') -----
> spyAllEvery: millisecs on: aBlock
> "Create a spy and spy on the given block at the specified rate."
> "Spy all the system processes"
>
> + | myDelay startTime time0 observedProcess |
> + (aBlock isMemberOf: BlockClosure)
> - | myDelay time0 |
> - (aBlock isBlock)
> ifFalse: [self error: 'spy needs a block here'].
> self class: aBlock receiver class method: aBlock method.
> "set up the probe"
> myDelay := Delay forMilliseconds: millisecs.
> time0 := Time millisecondClockValue.
> gcStats := SmalltalkImage current getVMParameters.
> + Timer ifNotNil: [ Timer terminate ].
> + Timer := [
> - Timer := [ | startTime observedProcess |
> [true] whileTrue: [
> startTime := Time millisecondClockValue.
> myDelay wait.
> observedProcess := Processor preemptedProcess.
> + self
> + tally: observedProcess suspendedContext
> + in: observedProcess
> - self tally: observedProcess suspendedContext
> - in: (ShowProcesses ifTrue:
> [observedProcess])
> "tally can be > 1 if ran a long primitive"
> by: (Time millisecondClockValue - startTime)
> // millisecs].
> nil] newProcess.
> Timer priority: Processor timingPriority-1.
> "activate the probe and evaluate the block"
> Timer resume.
> ^ aBlock ensure: [
> "Collect gc statistics"
> SmalltalkImage current getVMParameters keysAndValuesDo: [
> :idx :gcVal |
> gcStats at: idx put: (gcVal - (gcStats at: idx))].
> "cancel the probe and return the value"
> Timer terminate.
> + Timer := nil.
> time := Time millisecondClockValue - time0]!
>
> Item was changed:
> ----- Method: MessageTally>>leavesInto:fromSender: (in category
> 'collecting leaves') -----
> leavesInto: leafDict fromSender: senderTally
> +
> | rcvrs |
> + rcvrs := self sonsOver: 0.
> - rcvrs _ self sonsOver: 0.
> rcvrs size = 0
> + ifTrue: [ self into: leafDict fromSender: senderTally ]
> - ifTrue: [self into: leafDict fromSender: senderTally]
> ifFalse: [
>
> + (reportOtherProcesses not and: [ rcvrs anyOne
> process isNil ]) ifTrue: [
> + ^self].
> - "Do not show 'other processes' "
> - "Please keep consistency with
> #rootPrintOn:total:totalTime:tallyExact:orThreshold:
> - on showing them or not!!"
> - rcvrs anyOne process ifNil: [^self].
>
> + rcvrs do: [ :node |
> - rcvrs do:
> - [:node |
> node isPrimitives
> + ifTrue: [ node leavesInto: leafDict
> fromSender: senderTally ]
> + ifFalse: [ node leavesInto:
> leafDict fromSender: self ]]]!
> - ifTrue: [node leavesInto: leafDict
> fromSender: senderTally]
> - ifFalse: [node leavesInto: leafDict
> fromSender: self]]]!
>
> Item was changed:
> ----- Method: MessageTally>>printSenderCountsOn: (in category 'printing')
> -----
> printSenderCountsOn: aStream
> + | mergedSenders mergedNode |
> - | mergedSenders |
> mergedSenders := IdentityDictionary new.
> senders do:
> + [:node |
> - [:node | | mergedNode |
> mergedNode := mergedSenders at: node method ifAbsent: [nil].
> mergedNode == nil
> ifTrue: [mergedSenders at: node method put: node]
> ifFalse: [mergedNode bump: node tally]].
> mergedSenders asSortedCollection do:
> [:node |
> 10 to: node tally printString size by: -1 do: [:i | aStream
> space].
> node printOn: aStream total: tally totalTime: nil
> tallyExact: true]!
>
> Item was changed:
> ----- Method: MessageTally>>spyEvery:on: (in category
> 'initialize-release') -----
> + spyEvery: millisecs on: aBlock
> - spyEvery: millisecs on: aBlock
> "Create a spy and spy on the given block at the specified rate."
> "Spy only on the active process (in which aBlock is run)"
>
> + | myDelay startTime time0 observedProcess |
> + (aBlock isMemberOf: BlockClosure)
> - | myDelay time0 observedProcess |
> - aBlock isBlock
> ifFalse: [self error: 'spy needs a block here'].
> self class: aBlock receiver class method: aBlock method.
> "set up the probe"
> + observedProcess := Processor activeProcess.
> - observedProcess _ Processor activeProcess.
> myDelay := Delay forMilliseconds: millisecs.
> time0 := Time millisecondClockValue.
> gcStats := SmalltalkImage current getVMParameters.
> + Timer ifNotNil: [ Timer terminate ].
> + Timer := [
> - Timer := [ | startTime |
> [true] whileTrue: [
> startTime := Time millisecondClockValue.
> myDelay wait.
> + self
> + tally: Processor preemptedProcess
> suspendedContext
> + in: (observedProcess == Processor
> preemptedProcess ifTrue: [observedProcess] ifFalse: [nil])
> - self tally: Processor preemptedProcess
> suspendedContext
> - in: (ShowProcesses ifTrue: [
> - observedProcess == Processor
> preemptedProcess ifTrue: [observedProcess] ifFalse: [nil]])
> "tally can be > 1 if ran a long primitive"
> by: (Time millisecondClockValue - startTime)
> // millisecs].
> nil] newProcess.
> Timer priority: Processor timingPriority-1.
> "activate the probe and evaluate the block"
> Timer resume.
> ^ aBlock ensure: [
> "Collect gc statistics"
> SmalltalkImage current getVMParameters keysAndValuesDo: [
> :idx :gcVal |
> gcStats at: idx put: (gcVal - (gcStats at: idx))].
> "cancel the probe and return the value"
> + Timer terminate.
> + Timer := nil.
> - Timer ifNotNil: [ Timer terminate ].
> time := Time millisecondClockValue - time0]!
>
> Item was changed:
> ----- Method:
> MessageTally>>treePrintOn:tabs:thisTab:total:totalTime:tallyExact:orThreshold:
> (in category 'printing') -----
> treePrintOn: aStream tabs: tabs thisTab: myTab total: total totalTime:
> totalTime tallyExact: isExact orThreshold: threshold
> + | sons sonTab |
> - | sons |
> tabs do: [:tab | aStream nextPutAll: tab].
> tabs size > 0
> ifTrue:
> [self
> printOn: aStream
> total: total
> totalTime: totalTime
> tallyExact: isExact].
> sons := isExact ifTrue: [receivers] ifFalse: [self sonsOver:
> threshold].
> sons isEmpty
> ifFalse:
> [tabs addLast: myTab.
> sons := sons asSortedCollection.
> (1 to: sons size) do:
> + [:i |
> - [:i | | sonTab |
> sonTab := i < sons size ifTrue: ['
> |'] ifFalse: [' '].
> (sons at: i)
> treePrintOn: aStream
> tabs: (tabs size < self
> maxTabs
> ifTrue:
> [tabs]
> ifFalse:
> [(tabs select: [:x | x = '[']) copyWith: '['])
> thisTab: sonTab
> total: total
> totalTime: totalTime
> tallyExact: isExact
> orThreshold: threshold].
> tabs removeLast]!
>
> Item was changed:
> ----- Method: MessageTally class>>spyOnProcess:forMilliseconds: (in
> category 'spying') -----
> spyOnProcess: aProcess forMilliseconds: msecDuration
> + "Spy on aProcess for a certain amount of time
> - "
> | p1 p2 |
> + p1 := [100000 timesRepeat: [3.14159 printString. Processor yield]]
> newProcess.
> + p2 := [100000 timesRepeat: [3.14159 printString. Processor yield]]
> newProcess.
> + p1 resume.
> + p2 resume.
> - p1 _ [100000 timesRepeat: [3.14159 printString. Processor yield]]
> fork.
> - p2 _ [100000 timesRepeat: [3.14159 printString. Processor yield]]
> fork.
> (Delay forMilliseconds: 100) wait.
> MessageTally spyOnProcess: p1 forMilliseconds: 1000
> "
> + ^self spyOnProcess: aProcess forMilliseconds: msecDuration
> reportOtherProcesses: ShowProcesses
> + !
> - | node |
> - node := self new.
> - node
> - spyEvery: self defaultPollPeriod
> - onProcess: aProcess
> - forMilliseconds: msecDuration.
> - (StringHolder new
> - contents: (String
> - streamContents: [:s | node report: s;
> - close]))
> - openLabel: 'Spy Results'!
>
> Item was changed:
> ----- Method: MessageTally class>>spyAllOn: (in category 'spying') -----
> spyAllOn: aBlock
> "Spy on all the processes in the system
>
> [1000 timesRepeat: [3.14159 printString. Processor yield]] fork.
> [1000 timesRepeat: [20 factorial. Processor yield]] fork.
> [1000 timesRepeat: [20 factorial. Processor yield]] fork.
> MessageTally spyAllOn: [ (Delay forMilliseconds: 100) wait]
>
> "
> | node result |
> node := self new.
> + node reportOtherProcesses: true.
> result := node spyAllEvery: self defaultPollPeriod on: aBlock.
> + self showReport: node.
> - (StringHolder new contents: (String streamContents: [:s | node
> report: s; close]))
> - openLabel: 'Spy Results'.
> ^ result!
>
> Item was changed:
> Magnitude subclass: #MessageTally
> + instanceVariableNames: 'class method process tally receivers
> senders time gcStats maxClassNameSize maxClassPlusSelectorSize maxTabs
> reportOtherProcesses'
> - instanceVariableNames: 'class method process tally receivers
> senders time gcStats maxClassNameSize maxClassPlusSelectorSize maxTabs'
> classVariableNames: 'DefaultPollPeriod ShowProcesses Timer'
> poolDictionaries: ''
> category: 'System-Tools'!
>
> + !MessageTally commentStamp: 'StephaneDucasse 9/27/2009 10:42' prior: 0!
> - !MessageTally commentStamp: 'nk 3/8/2004 12:43' prior: 0!
> My instances observe and report the amount of time spent in methods.
>
> + NOTE: a higher-level user interface (combining the MessageTally result
> tree with a method browser) is available from TimeProfileBrowser. Note that
> TimeProfileBrowser was not fancy with the different setting possibilities.
> - NOTE: a higher-level user interface (combining the MessageTally result
> tree with a method browser) is available from TimeProfileBrowser.
>
> + TimeProfileBrowser spyOn: [20 timesRepeat:
> + [Transcript show: 100 factorial printString]]
> +
> +
> + Strategies
> + -----------
> MessageTally provides two different strategies available for profiling:
>
> + * spyOn: and friends use a high-priority Process to interrupt the block
> or process being spied on at periodic intervals. The interrupted call stack
> is then examined for caller information. See below for an example showing
> different settings
> - * spyOn: and friends use a high-priority Process to interrupt the block
> or process being spied on at periodic intervals. The interrupted call stack
> is then examined for caller information.
>
> * tallySends: and friends use the interpreter simulator to run the block,
> recording every method call.
>
> The two give you different results:
>
> + * spyOn: gives you a view of where the time is being spent in your
> program, at least on a rough statistical level (assuming you've run the
> block for long enough and have a high enough poll rate). If you're trying
> to optimize your code, start here and optimize the methods where most
> of the time is being spent first.
> - * spyOn: gives you a view of where the time is being spent in your
> program, at least on a rough statistical level (assuming you've run the
> block for long enough and have a high enough poll rate). If you're trying to
> optimize your code, start here and optimize the methods where most of the
> time is being spent first.
>
> + * tallySends: gives you accurate counts of how many times methods
> get called, and by exactly which route. If you're debugging, or trying to
> figure out if a given method is getting called too many times, this is
> your tool.
> - * tallySends: gives you accurate counts of how many times methods get
> called, and by exactly which route. If you're debugging, or trying to figure
> out if a given method is getting called too many times, this is your tool.
>
> + Q: How do you interpret MessageTally>>tallySends
> + A: The methods #tallySends and #spyOn: measure two very different
> quantities, but broken down in the same who-called-who format. #spyOn: is
> approximate, but more indicative of real time spent, whereas #tallySends is
> exact and a precise record of how many times each method got executed.
> +
> + Examples
> + ----------
> +
> + Here you can see all the processes computation time
> +
> + [1000 timesRepeat: [3.14159 printString. Processor yield]]
> fork.
> + [1000 timesRepeat: [30 factorial. Processor yield]] fork.
> + [1000 timesRepeat: [30 factorial. Processor yield]] fork.
> + MessageTally spyAllOn: [ (Delay forMilliseconds: 100) wait]
> +
> +
> + Settings
> + ---------
> You can change the printing format (that is, the whitespace and string
> compression) by using these instance methods:
> maxClassNameSize:
> maxClassPlusSelectorSize:
> maxTabs:
>
> You can change the default polling period (initially set to 1) by calling
> MessageTally defaultPollPeriod: numberOfMilliseconds
>
> +
> + To understand the difference
> + ----------------------------------
> + Here we see all the processes
> + [1000 timesRepeat: [
> + 100 timesRepeat: [120 factorial].
> + (Delay forMilliseconds: 10) wait
> + ]] forkAt: 45 named: '45'.
> + MessageTally spyAllOn: [10000 timesRepeat: [1.23 printString]]
> +
> +
> + Here we only see the execution of the expression [10000 timesRepeat:
> [1.23 printString]
> + [1000 timesRepeat: [
> + 100 timesRepeat: [120 factorial].
> + (Delay forMilliseconds: 10) wait
> + ]] forkAt: 45 named: '45'.
> + MessageTally spyOn: [10000 timesRepeat: [1.23 printString]]
> +
> + Here we only check the exact message sends: this is not a pc-sampling
> approach
> + [1000 timesRepeat: [
> + 100 timesRepeat: [120 factorial].
> + (Delay forMilliseconds: 10) wait
> + ]] forkAt: 45 named: '45'.
> + MessageTally tallySends: [10000 timesRepeat: [1.23 printString]]
> +
> +
> +
> + !
> - Q: How do you interpret MessageTally>>tallySends
> - A: The methods #tallySends and #spyOn: measure two very different
> quantities, but broken down in the same who-called-who format. #spyOn: is
> approximate, but more indicative of real time spent, whereas #tallySends is
> exact and a precise record of how many times each method got executed.!
>
> Item was changed:
> ----- Method: MessageTally>>tally:in:by: (in category 'tallying') -----
> tally: context in: aProcess by: count
> "Explicitly tally the specified context and its stack."
> | sender |
>
> "Add to this node if appropriate"
> context method == method ifTrue: [^self bumpBy: count].
>
> "No sender? Add new branch to the tree."
> + (sender := context home sender) ifNil: [
> - (sender := context home sender) ifNil: [
> ^ (self bumpBy: count) tallyPath: context in: aProcess by:
> count].
>
> "Find the node for the sending context (or add it if necessary)"
> ^ (self tally: sender in: aProcess by: count) tallyPath: context in:
> aProcess by: count!
>
> Item was added:
> + ----- Method: MessageTally>>reportOtherProcesses (in category
> 'accessing') -----
> + reportOtherProcesses
> + "If true, reports all processes in the system"
> + ^reportOtherProcesses!
>
> Item was changed:
> ----- Method: MessageTally>>into:fromSender: (in category 'collecting
> leaves') -----
> into: leafDict fromSender: senderTally
> | leafNode |
> + leafNode := leafDict at: method
> - leafNode _ leafDict at: method
> ifAbsent: [leafDict at: method
> put: ((MessageTally new class: class method: method)
> + process: process;
> + reportOtherProcesses:
> reportOtherProcesses)].
> - process: process)].
> leafNode bump: tally fromSender: senderTally!
>
> Item was changed:
> ----- Method: MessageTally>>tallyPath:in:by: (in category 'tallying')
> -----
> tallyPath: context in: aProcess by: count
> | aMethod path |
> aMethod := context method.
>
> "Find the correct child (if there)"
> receivers do: [ :oldTally |
> (oldTally method == aMethod and: [oldTally process ==
> aProcess])
> ifTrue: [path := oldTally]].
>
> "Add new child if needed"
> path ifNil:[
> path := MessageTally new class: context receiver class
> method: aMethod;
> process: aProcess;
> + reportOtherProcesses: reportOtherProcesses;
> maxClassNameSize: maxClassNameSize;
> maxClassPlusSelectorSize: maxClassPlusSelectorSize;
> maxTabs: maxTabs.
> receivers := receivers copyWith: path].
>
> ^ path bumpBy: count!
>
> Item was changed:
> + ----- Method: MessageTally>>initialize (in category 'initialization')
> -----
> - ----- Method: MessageTally>>initialize (in category 'initialize-release')
> -----
> initialize
> + "Initialize the receiver"
> + super initialize.
> maxClassNameSize := self class defaultMaxClassNameSize.
> maxClassPlusSelectorSize := self class
> defaultMaxClassPlusSelectorSize.
> + maxTabs := self class defaultMaxTabs.
> + reportOtherProcesses := false.
> + !
> - maxTabs := self class defaultMaxTabs.!
>
> Item was changed:
> ----- Method: MessageTally>>copyWithTally: (in category 'private') -----
> copyWithTally: hitCount
> + ^ (MessageTally new class: class method: method)
> + reportOtherProcesses: reportOtherProcesses;
> - ^ (MessageTally new class: class method: method)
> process: process;
> bump: hitCount!
>
> Item was added:
> + ----- Method: MessageTally>>fullPrintOn:threshold: (in category
> 'printing') -----
> + fullPrintOn: aStream threshold: perCent
> + | threshold |
> + threshold := (perCent asFloat / 100 * tally) rounded.
> + aStream nextPutAll: '**Tree**'; cr.
> + self
> + rootPrintOn: aStream
> + total: tally
> + totalTime: time
> + threshold: threshold.
> + aStream nextPut: Character newPage; cr.
> + aStream nextPutAll: '**Leaves**'; cr.
> + self
> + leavesPrintOn: aStream
> + threshold: threshold!
>
> Item was added:
> + ----- Method: MessageTally>>fullPrintExactOn: (in category 'printing')
> -----
> + fullPrintExactOn: aStream
> + aStream nextPutAll: '**Tree**'; cr.
> + self
> + treePrintOn: aStream
> + tabs: OrderedCollection new
> + thisTab: ''
> + total: tally
> + totalTime: time
> + tallyExact: true
> + orThreshold: nil.
> + aStream nextPut: Character newPage; cr.
> + aStream nextPutAll: '**Leaves**'; cr.
> + self leavesPrintExactOn: aStream!
>
> Item was added:
> + ----- Method: MessageTally
> class>>spyOnProcess:forMilliseconds:toFileNamed:reportOtherProcesses: (in
> category 'spying') -----
> + spyOnProcess: aProcess forMilliseconds: msecDuration toFileNamed:
> fileName reportOtherProcesses: aBoolean
> + "Spy on the evaluation of aProcess. Write the data collected on a
> file
> + named fileName. Will overwrite fileName"
> + | file node |
> + node := self new.
> + node reportOtherProcesses: aBoolean.
> + node
> + spyEvery: self defaultPollPeriod
> + onProcess: aProcess
> + forMilliseconds: msecDuration.
> + file := FileStream fileNamed: fileName.
> + node report: file;
> + close.
> + file close!
>
> Item was changed:
> ----- Method: MessageTally class>>tallySends: (in category 'spying') -----
> + tallySends: aBlock
> + "
> + MessageTally tallySends: [3.14159 printString]
> + "
> +
> - tallySends: aBlock "MessageTally tallySends: [3.14159 printString]"
> ^ self tallySendsTo: nil inBlock: aBlock showTree: true!
>
> Item was changed:
> ----- Method: MessageTally>>report:cutoff: (in category 'reporting') -----
> report: strm cutoff: threshold
> tally = 0
> ifTrue: [strm nextPutAll: ' - no tallies obtained']
> ifFalse:
> [strm nextPutAll: ' - '; print: tally; nextPutAll: '
> tallies, ', time printString, ' msec.'; cr; cr.
> + self fullPrintOn: strm threshold: threshold].
> - self fullPrintOn: strm tallyExact: false
> orThreshold: threshold].
>
> time isZero ifFalse:
> [self reportGCStatsOn: strm].!
>
> Item was added:
> + ----- Method: MessageTally class>>showReport: (in category 'spying')
> -----
> + showReport: node
> + "Open a string holder with the reports from the given node"
> + (StringHolder new contents:
> + (String streamContents: [:s | node report: s; close]))
> + openLabel: 'Spy Results'!
>
> Item was added:
> + ----- Method: MessageTally>>reportOtherProcesses: (in category
> 'accessing') -----
> + reportOtherProcesses: aBoolean
> + "If true, reports all processes in the system"
> + reportOtherProcesses := aBoolean!
>
> Item was added:
> + ----- Method: MessageTally
> class>>spyOnProcess:forMilliseconds:reportOtherProcesses: (in category
> 'spying') -----
> + spyOnProcess: aProcess forMilliseconds: msecDuration
> reportOtherProcesses: aBoolean
> + "Spy on aProcess for a certain amount of time
> + | p1 p2 |
> + p1 := [100000 timesRepeat: [3.14159 printString. Processor yield]]
> newProcess.
> + p2 := [100000 timesRepeat: [3.14159 printString. Processor yield]]
> newProcess.
> + p1 resume.
> + p2 resume.
> + (Delay forMilliseconds: 100) wait.
> + MessageTally spyOnProcess: p1 forMilliseconds: 1000
> reportOtherProcesses: true
> + "
> + | node |
> + node := self new.
> + node reportOtherProcesses: aBoolean.
> + node
> + spyEvery: self defaultPollPeriod
> + onProcess: aProcess
> + forMilliseconds: msecDuration.
> + self showReport: node.!
>
> Item was added:
> + ----- Method: MessageTally class>>spyOn:reportOtherProcesses: (in
> category 'spying') -----
> + spyOn: aBlock reportOtherProcesses: aBoolean
> + "Spy on aBlock, in the current process. Can include or not
> statistics on other processes in the report.
> + [1000 timesRepeat: [
> + 100 timesRepeat: [120 factorial].
> + (Delay forMilliseconds: 10) wait
> + ]] forkAt: 45 named: '45'.
> + MessageTally spyOn: [10000 timesRepeat: [1.23 printString]]
> reportOtherProcesses: true
> + "
> + | node result |
> + node := self new.
> + node reportOtherProcesses: aBoolean.
> + result := node spyEvery: self defaultPollPeriod on: aBlock.
> + self showReport: node.
> + ^ result!
>
> Item was changed:
> ----- Method: MessageTally>>sonsOver: (in category 'comparing') -----
> sonsOver: threshold
>
> | hereTally last sons |
> (receivers == nil or: [receivers size = 0]) ifTrue: [^#()].
> + hereTally := tally.
> + sons := receivers select: "subtract subNode tallies for primitive
> hits here"
> - hereTally _ tally.
> - sons _ receivers select: "subtract subNode tallies for primitive
> hits here"
> [:son |
> + hereTally := hereTally - son tally.
> - hereTally _ hereTally - son tally.
> son tally > threshold].
> hereTally > threshold
> + ifTrue: [
> + last := MessageTally new class: class method:
> method.
> - ifTrue:
> - [last _ MessageTally new class: class method:
> method.
> last process: process.
> + last reportOtherProcesses: reportOtherProcesses.
> ^sons copyWith: (last primitives: hereTally)].
> ^sons!
>
> Item was changed:
> ----- Method: MessageTally class>>spyOn: (in category 'spying') -----
> spyOn: aBlock
> + "Spy on aBlock, in the current process. Can include or not
> statistics on other processes in the report.
> - "
> [1000 timesRepeat: [
> 100 timesRepeat: [120 factorial].
> (Delay forMilliseconds: 10) wait
> ]] forkAt: 45 named: '45'.
> MessageTally spyOn: [10000 timesRepeat: [1.23 printString]]
> "
> + ^self spyOn: aBlock reportOtherProcesses: ShowProcesses!
> - | node result |
> - node _ self new.
> - result _ node spyEvery: self defaultPollPeriod on: aBlock.
> - (StringHolder new contents: (String streamContents: [:s | node
> report: s; close]))
> - openLabel: 'Spy Results'.
> - ^ result!
>
> Item was changed:
> ----- Method: MessageTally>>close (in category 'initialize-release') -----
> close
>
> + Timer ifNotNil: [ Timer terminate ].
> - (Timer isMemberOf: Process) ifTrue: [Timer terminate].
> Timer := nil.
> class := method := tally := receivers := nil!
>
> Item was changed:
> ----- Method: MessageTally>>tallyPath:by: (in category 'tallying') -----
> tallyPath: context by: count
> | aMethod path |
> + aMethod := context method.
> - aMethod :=context method.
>
> "Find the correct child (if there)"
> receivers do: [ :oldTally |
> oldTally method == aMethod ifTrue: [path := oldTally]].
>
> "Add new child if needed"
> path ifNil: [
> path := MessageTally new class: context receiver class
> method: aMethod.
> + path reportOtherProcesses: reportOtherProcesses.
> receivers := receivers copyWith: path].
>
> ^ path bumpBy: count!
>
> Item was added:
> + ----- Method: MessageTally>>leavesPrintOn:threshold: (in category
> 'printing') -----
> + leavesPrintOn: aStream threshold: threshold
> + | dict |
> + dict := IdentityDictionary new: 100.
> + self leavesInto: dict fromSender: nil.
> + (dict asOrderedCollection
> + select: [:node | node tally > threshold])
> + asSortedCollection do: [:node |
> + node printOn: aStream total: tally totalTime: time
> tallyExact: false ]!
>
> Item was removed:
> - ----- Method: MessageTally>>fullPrintOn:tallyExact:orThreshold: (in
> category 'printing') -----
> - fullPrintOn: aStream tallyExact: isExact orThreshold: perCent
> - | threshold |
> - isExact ifFalse: [threshold _ (perCent asFloat / 100 * tally)
> rounded].
> - aStream nextPutAll: '**Tree**'; cr.
> - self rootPrintOn: aStream
> - total: tally
> - totalTime: time
> - tallyExact: isExact
> - orThreshold: threshold.
> - aStream nextPut: Character newPage; cr.
> - aStream nextPutAll: '**Leaves**'; cr.
> - self leavesPrintOn: aStream
> - tallyExact: isExact
> - orThreshold: threshold!
>
> Item was removed:
> - ----- Method:
> MessageTally>>rootPrintOn:total:totalTime:tallyExact:orThreshold: (in
> category 'printing') -----
> - rootPrintOn: aStream total: total totalTime: totalTime tallyExact:
> isExact orThreshold: threshold
> - | groups sons |
> - ShowProcesses ifFalse:[
> - ^self treePrintOn: aStream
> - tabs: OrderedCollection new
> - thisTab: ''
> - total: total
> - totalTime: totalTime
> - tallyExact: isExact
> - orThreshold: threshold.
> - ].
> - sons := isExact ifTrue: [receivers] ifFalse: [self sonsOver:
> threshold].
> - groups := sons groupBy:[:aTally| aTally process] having:[:g| true].
> - groups do:[:g| | p |
> - sons := g asSortedCollection.
> - p := g anyOne process.
> - "Do not show 'other processes' "
> - "Please keep consistency with #leavesInto:fromSender:
> - on showing them or not!!"
> - p ifNotNil: [
> - aStream nextPutAll:
> '--------------------------------'; cr.
> - aStream nextPutAll: 'Process: ', (p ifNil: [
> 'other processes'] ifNotNil: [ p browserPrintString]); cr.
> - aStream nextPutAll:
> '--------------------------------'; cr.
> - (1 to: sons size) do:[:i |
> - (sons at: i)
> - treePrintOn: aStream
> - tabs: OrderedCollection new
> - thisTab: ''
> - total: total
> - totalTime: totalTime
> - tallyExact: isExact
> - orThreshold: threshold]].
> - ].!
>
> Item was removed:
> - ----- Method: MessageTally>>leavesPrintOn:tallyExact:orThreshold: (in
> category 'printing') -----
> - leavesPrintOn: aStream tallyExact: isExact orThreshold: threshold
> - | dict |
> - dict := IdentityDictionary new: 100.
> - self leavesInto: dict fromSender: nil.
> - isExact ifTrue:
> - [dict asSortedCollection
> - do: [:node |
> - node printOn: aStream total: tally
> totalTime: nil tallyExact: isExact.
> - node printSenderCountsOn: aStream]]
> - ifFalse:
> - [(dict asOrderedCollection
> - select: [:node | node tally > threshold])
> - asSortedCollection
> - do: [:node |
> - node printOn: aStream total: tally
> totalTime: time tallyExact: isExact]]!
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20100203/58086392/attachment.htm
More information about the Squeak-dev
mailing list
|