[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