[Vm-dev] VM Maker: CogTools-eem.71.mcz
commits at source.squeak.org
commits at source.squeak.org
Thu Jul 10 20:00:07 UTC 2014
Eliot Miranda uploaded a new version of CogTools to project VM Maker:
http://source.squeak.org/VMMaker/CogTools-eem.71.mcz
==================== Summary ====================
Name: CogTools-eem.71
Author: eem
Time: 10 July 2014, 12:59:56.965 pm
UUID: a0bb84f4-7ba8-4573-9c99-ac72820d7f38
Ancestors: CogTools-eem.70
Be robust in the face of old PluggableTextMorphs that don't
allow their contents to be set.
Make sure the tabs arrays are large on initialization.
Do a slightly better job at choosing labels to display.
=============== Diff against CogTools-eem.70 ===============
Item was changed:
----- Method: VMProfileGraphLabelMorph>>drawClippedOn: (in category 'drawing') -----
drawClippedOn: clippedCanvas
"Display the labels at their relative positions sloping down at 45 degrees.
Draw a label every font height pixels along to avoid a mess when there are lots of labels."
| labelForm lfc rotatedLabelForm rlfc warp degSin degCos side rect pts minDelta lastX margin range rotationOffset xs |
labelForm := Form extent: self height * 2 @ font height depth: 4.
rotatedLabelForm := Form extent: self height asPoint depth: 4.
lfc := labelForm getCanvas.
rlfc := rotatedLabelForm getCanvas.
warp := (WarpBlt current toForm: rotatedLabelForm)
sourceForm: labelForm;
colorMap: (labelForm colormapIfNeededFor: rotatedLabelForm);
cellSize: 2 "smooothing"; "installs a new colormap if cellSize > 1"
combinationRule: Form paint.
degSin := 45 degreeSin.
degCos := 45 degreeCos.
"See Form>>rotateBy:magnify:smoothing:"
side := labelForm extent r.
rect := (0 at 0 extent: side at side) align: (side / 2) asPoint with: labelForm extent / 2.
pts := rect innerCorners collect:
[:pt | | p |
p := pt - rect center.
((labelForm width / 2.0) + (p x asFloat*degCos) + (p y asFloat*degSin)) @
((labelForm height / 2.0) - (p x asFloat*degSin) + (p y asFloat*degCos))].
+ minDelta := font height / 1.5.
- minDelta := font height / 1.75. "1.6 a little greater than 2 sqrt"
lastX := font height negated.
margin := model graphMargin.
range := self width - margin - margin.
rotationOffset := (labelForm height / 2 * 2 sqrt) ceiling.
(xs := positionedLabels keys asSortedCollection) withIndexDo:
[:fractionalX :index| | x |
x := (fractionalX * range) rounded.
(lastX + minDelta <= x
or: [index < xs size
and: [lastX + minDelta + minDelta <= ((xs at: index + 1) * range)]]) ifTrue:
[lfc
fillColor: Color black;
drawString: (positionedLabels at: fractionalX) at: 0 at 0 font: font color: Color white.
rlfc
fillColor: Color black.
warp copyQuad: pts toRect: rotatedLabelForm boundingBox.
clippedCanvas
image: rotatedLabelForm
at: self bounds origin + ((fractionalX * range max: lastX + minDelta) floor + margin - rotationOffset at 0)
sourceRect: rotatedLabelForm boundingBox
rule: Form erase.
true ifTrue:
[| box |
box := (self bounds origin + ((fractionalX * range) floor + margin at 0)) extent: 1 at 6.
Display fill: box rule: Form over fillColor: Color gray].
lastX := x]]!
Item was added:
+ ----- Method: VMProfiler class>>fixTabs (in category 'class initialization') -----
+ fixTabs
+ "Make sure the DefaultTabsArray and DefaultMarginTabsArray are adequately sized for modern displays."
+ | defaultTab tempArray width |
+ (Smalltalk bindingOf: #TextConstants) ifNil: [^self].
+ width := 2000.
+ (TextConstants at: #DefaultTabsArray) last < width ifTrue:
+ [defaultTab := TextConstants at: #DefaultTab.
+ tempArray := Array new: 2000 // defaultTab.
+ 1 to: tempArray size do:
+ [:i | tempArray at: i put: defaultTab * i].
+ TextConstants at: #defaultTabsArray put: tempArray.
+ tempArray := Array new: (width // defaultTab) // 2.
+ 1 to: tempArray size do:
+ [:i | tempArray at: i put: (Array with: (defaultTab*i) with: (defaultTab*i))].
+ TextConstants at: #DefaultMarginTabsArray put: tempArray]!
Item was changed:
----- Method: VMProfiler class>>initialize (in category 'class initialization') -----
initialize
CannedBenchmarkStrings := OrderedCollection new.
(TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue:
[TheWorldMenu registerOpenCommand: {'VM Profiler'. {self. #open}. 'A VM profiler'}].
Preferences
addBooleanPreference: #vmProfilerFillInIntegral
category: #vmProfiler
default: false
+ balloonHelp: 'If enabled, the profiler will fill in the area under the integral.'.
+ self fixTabs!
- balloonHelp: 'If enabled, the profiler will fill in the area under the integral.'!
Item was added:
+ ----- Method: VMProfiler>>highResSamplesFor: (in category 'accessing') -----
+ highResSamplesFor: sym
+ | samples |
+ samples := 0.
+ sym address to: sym limit - 1 do:
+ [:a| samples := samples + (highResSamples at: a)].
+ ^samples!
Item was changed:
----- Method: VMProfiler>>positionedLabels (in category 'accessing') -----
positionedLabels
"Compute the set of labels to be displayed for the given address range.
+ Try and display no more than maxLabels labels. The result is a dictionary
+ of fractional position in the range to string. If there are lots of labels, try
+ and favour those that have samples."
+ | maxLabels counts types symbolsInRange positionedLabels index count range significantSymbolsInRange |
+ maxLabels := 50.
- Try and display no more than 25 labels. The result is a dictionary of
- fractional position in the range to string."
- | counts types symbolsInRange positionedLabels index count range |
minSelectionIndex isZero ifTrue:
[^Dictionary new].
"count how many labels of each type there are in the range."
counts := Dictionary new.
(types := #(module objectFile publicFunction privateFunction label)) do:
[:type| counts at: type put: 0].
types := types select: [:type| symbolTypes includes: type].
symbolsInRange := symbolManager symbolsSelect: [:sym| sym address <= highAddress and: [sym limit >= lowAddress and: [(symbolTypes includes: sym type)]]].
+ "If there are kots if klabels then choose to display only those with samples"
+ symbolsInRange size > (maxLabels / 2) ifTrue:
+ [significantSymbolsInRange := symbolsInRange select: [:s| (self symHasLowResSamples: s) and: [(self highResSamplesFor: s) > 0]]].
+ (symbolsInRange size > maxLabels
+ and: [significantSymbolsInRange size >= (maxLabels / 2)]) ifTrue:
+ [symbolsInRange := significantSymbolsInRange].
symbolsInRange do:
[:s| counts at: s type put: (counts at: s type) + 1].
"Find out what types give us at least one label but no more
+ than maxLabels unless necessary to have at least one."
- than 25 unless necessary to have at least one."
index := 1.
count := counts at: (types at: index).
[index <= types size
+ and: [count + (counts at: (types at: index)) < maxLabels]] whileTrue:
- and: [count + (counts at: (types at: index)) < 25]] whileTrue:
[count := count + (counts at: (types at: index)).
index := index + 1].
"add labels to positionedLabels indexed by their fractional position in the range, filtering by type."
types := types copyFrom: 1 to: (index min: types size).
positionedLabels := Dictionary new: count.
range := (highAddress - lowAddress) asFloat.
symbolsInRange do:
[:s |
(types includes: s type) ifTrue:
[positionedLabels
at: ([s address - lowAddress / range]
on: ZeroDivide
do: [:ex| 0])
put: s displayText]].
^positionedLabels!
Item was changed:
----- Method: VMProfiler>>spyOn: (in category 'spying') -----
spyOn: aBlock
| blockToProfile r |
blockToProfile := forkProfile
ifTrue:
[| sem fr |
sem := Semaphore new.
[[fr := aBlock value. sem signal] fork.
sem wait.
fr]]
ifFalse: [aBlock].
+ [self selectBenchmark: aBlock sourceString]
+ on: Error
+ do: [:ex|].
- self selectBenchmark: aBlock sourceString.
self startProfiling.
r := blockToProfile ensure: [self stopProfiling].
WorldState addDeferredUIMessage:
[self plotGraph].
^r!
Item was added:
+ ----- Method: VMProfiler>>symHasLowResSamples: (in category 'accessing') -----
+ symHasLowResSamples: sym
+ ^(sym address // lowResolution to: sym limit // lowResolution)
+ anySatisfy:
+ [:pc| (lowResSamples at: pc + 1) > 0]!
Item was changed:
----- Method: VMProfiler>>totalsDo: (in category 'reports') -----
totalsDo: septuaryBlock
"Evaluate aBlock with
a Dictionary of symbol -> total for the functions in the VM (excluding generated code)
a Dictionary of symbol -> total for the generated code in the VM
a Dictionary of symbol -> total for the functions in other code
total number of samples in functions in the VM (excluding generated code)
total number of samples in generated code in the VM
total number of samples in generated code in the VM
total number of samples in functions in other code
total number of samples not in VM or VM-generated code (incudes code not in any function)"
| vmTotals cogTotals nonVMTotals
samplesInVM samplesInCog samplesInNonVMModules samplesInNonVM |
vmTotals := Dictionary new.
cogTotals := Dictionary new.
nonVMTotals := Dictionary new.
samplesInVM := samplesInCog := samplesInNonVMModules := 0.
(symbolManager symbolsInModule: symbolManager vmModule) do:
[:sym| | samples |
+ ((#(publicFunction privateFunction) includes: sym type)
+ and: [(samples := self highResSamplesFor: sym) > 0]) ifTrue:
+ [vmTotals at: sym put: samples.
+ samplesInVM := samplesInVM + samples]].
- (#(publicFunction privateFunction) includes: sym type) ifTrue:
- [samples := 0.
- sym address to: sym limit - 1 do:
- [:a| samples := samples + (highResSamples at: a)].
- samples > 0 ifTrue:
- [vmTotals at: sym put: samples.
- samplesInVM := samplesInVM + samples]]].
(symbolManager symbolsInModule: symbolManager cogModule) do:
[:sym| | samples |
+ ((#(publicFunction privateFunction) includes: sym type)
+ and: [(samples := self highResSamplesFor: sym) > 0]) ifTrue:
+ [cogTotals at: sym put: samples.
+ samplesInCog := samplesInCog + samples]].
- (#(publicFunction privateFunction) includes: sym type) ifTrue:
- [samples := 0.
- sym address to: sym limit - 1 do:
- [:a| samples := samples + (highResSamples at: a)].
- samples > 0 ifTrue:
- [cogTotals at: sym put: samples.
- samplesInCog := samplesInCog + samples]]].
((symbolManager modules
copyWithout: symbolManager vmModule)
copyWithout: symbolManager cogModule) do:
[:module|
(symbolManager symbolsInModule: module) do:
[:sym| | samples |
((#(publicFunction privateFunction) includes: sym type)
+ and: [(self symHasLowResSamples: sym)
+ and: [(samples := self highResSamplesFor: sym) > 0]]) ifTrue:
+ [nonVMTotals at: sym put: samples.
+ samplesInNonVMModules := samplesInNonVMModules + samples]]].
- and: [(sym address // lowResolution to: sym limit // lowResolution) anySatisfy:
- [:pc| (lowResSamples at: pc + 1) > 0]]) ifTrue:
- [samples := 0.
- sym address to: sym limit - 1 do:
- [:a| samples := samples + (highResSamples at: a)].
- samples > 0 ifTrue:
- [nonVMTotals at: sym put: samples.
- samplesInNonVMModules := samplesInNonVMModules + samples]]]].
samplesInNonVM := total - samplesInVM - samplesInCog.
nonVMTotals
at: 'Samples Not In Any Function'
put: samplesInNonVM - samplesInNonVMModules.
septuaryBlock valueWithArguments:
{vmTotals.
cogTotals.
nonVMTotals.
samplesInVM.
samplesInCog.
samplesInNonVMModules.
samplesInNonVM}!
More information about the Vm-dev
mailing list