[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