<body><div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000">
Yay! Finally. ^__^<div><br></div><div>+1 for after the 5.3 release</div><div><br></div><div>Best,</div><div>Marcel</div><div class="mb_sig"></div><blockquote class="history_container" type="cite" style="border-left-style:solid;border-width:1px; margin-top:20px; margin-left:0px;padding-left:10px;">
<p style="color: #AAAAAA; margin-top: 10px;">Am 18.12.2019 01:25:07 schrieb commits@source.squeak.org <commits@source.squeak.org>:</p><div style="font-family:Arial,Helvetica,sans-serif">Chris Muller uploaded a new version of Chronology-Core to project The Inbox:<br>http://source.squeak.org/inbox/Chronology-Core-cmm.52.mcz<br><br>==================== Summary ====================<br><br>Name: Chronology-Core-cmm.52<br>Author: cmm<br>Time: 17 December 2019, 6:24:58.728545 pm<br>UUID: 2fcaa724-74e7-46e1-b77e-d976e58e21cf<br>Ancestors: Chronology-Core-mt.51<br><br>Ability to run and compare multiple benchmarks at once via:<br><br> { baselineExpression.<br> altExpression1.<br> altExpression2.<br> "...etc..." } benchCompare<br><br>The standard bench string is reported for each, along with a percentage rate relative to the baseline, the first one.<br><br>=============== Diff against Chronology-Core-mt.51 ===============<br><br>Item was changed:<br> ----- Method: BlockClosure>>benchFor: (in category '*chronology-core') -----<br>+ benchFor: aDuration <br>+ "See how many times I can value within the given duration. I'll answer a meaningful description."<br>+ ^ self<br>+ benchFor: aDuration<br>+ do:<br>+ [ : metrics |<br>+ self<br>+ benchMessageForTime: (metrics at: #time)<br>+ count: (metrics at: #count)<br>+ gc: (metrics at: #gcTime) ]!<br>- benchFor: aDuration<br>- "See how many times I can value within the given duration. I'll answer a meaningful description."<br>- <br>- | startTime shouldRun count elapsedTime roundTo3Digits delay gcStart gcTime |<br>- roundTo3Digits := [:num |<br>- | rounded lowDigit |<br>- rounded := (num * 1000) rounded. "round to 1/1000"<br>- lowDigit := (rounded numberOfDigitsInBase: 10) - 3. "keep only first 3 digits"<br>- rounded := rounded roundTo:(10 raisedTo: lowDigit).<br>- (lowDigit >= 3 or: [rounded \\ 1000 = 0]) "display fractional part only when needed"<br>- ifTrue: [(rounded // 1000) asStringWithCommas]<br>- ifFalse: [(rounded / 1000.0) printString]].<br>- delay := aDuration asDelay.<br>- count := 0.<br>- shouldRun := true.<br>- Smalltalk garbageCollect.<br>- [ delay wait. shouldRun := false ] forkAt: Processor timingPriority - 1.<br>- startTime := Time millisecondClockValue.<br>- gcStart := (Smalltalk vmParameterAt: 8) + (Smalltalk vmParameterAt: 10).<br>- [ shouldRun ] whileTrue: [ <br>- self value.<br>- count := count + 1 ].<br>- elapsedTime := Time millisecondsSince: startTime.<br>- gcTime := (Smalltalk vmParameterAt: 8) + (Smalltalk vmParameterAt: 10) - gcStart.<br>- ^(roundTo3Digits value: count * 1000 / elapsedTime) , ' per second.', ((<br>- #(<br>- (1e-3 'seconds')<br>- (1 'milliseconds')<br>- (1e3 'microseconds')<br>- (1e6 'nanoseconds')<br>- )<br>- detect: [ :pair | elapsedTime * pair first >= count ]<br>- ifNone: [ #(1e9 'picoseconds') ])<br>- in: [ :pair |<br>- ' {1} {2} per run.' format: {<br>- (roundTo3Digits value: elapsedTime * pair first / count).<br>- pair second } ]), (' {1} % GC time.' format: {gcTime / elapsedTime * 100 printShowingMaxDecimalPlaces: 5})!<br><br>Item was added:<br>+ ----- Method: BlockClosure>>benchFor:do: (in category '*chronology-core') -----<br>+ benchFor: aDuration do: oneArgBlock<br>+ "See how many times I can value within the given duration. I'll answer a meaningful description."<br>+ | startTime shouldRun count elapsedTime delay gcStart gcTime |<br>+ delay := aDuration asDelay.<br>+ count := 0.<br>+ shouldRun := true.<br>+ Smalltalk garbageCollect.<br>+ [ delay wait. shouldRun := false ] forkAt: Processor timingPriority - 1.<br>+ startTime := Time millisecondClockValue.<br>+ gcStart := (Smalltalk vmParameterAt: 8) + (Smalltalk vmParameterAt: 10).<br>+ [ shouldRun ] whileTrue: [ <br>+ self value.<br>+ count := count + 1 ].<br>+ elapsedTime := Time millisecondsSince: startTime.<br>+ gcTime := (Smalltalk vmParameterAt: 8) + (Smalltalk vmParameterAt: 10) - gcStart.<br>+ ^ oneArgBlock value:<br>+ ({ #time -> elapsedTime.<br>+ #count -> count.<br>+ #rate -> (count * 1000 / elapsedTime).<br>+ #gcTime -> gcTime} as: OrderedDictionary)!<br><br>Item was added:<br>+ ----- Method: BlockClosure>>benchMessageForTime:count:gc: (in category '*chronology-core') -----<br>+ benchMessageForTime: elapsedTime count: count gc: gcTime<br>+ | roundTo3Digits |<br>+ roundTo3Digits := [:num |<br>+ | rounded lowDigit |<br>+ rounded := (num * 1000) rounded. "round to 1/1000"<br>+ lowDigit := (rounded numberOfDigitsInBase: 10) - 3. "keep only first 3 digits"<br>+ rounded := rounded roundTo:(10 raisedTo: lowDigit).<br>+ (lowDigit >= 3 or: [rounded \\ 1000 = 0]) "display fractional part only when needed"<br>+ ifTrue: [(rounded // 1000) asStringWithCommas]<br>+ ifFalse: [(rounded / 1000.0) printString]].<br>+ ^(roundTo3Digits value: count * 1000 / elapsedTime) , ' per second.', ((<br>+ #(<br>+ (1e-3 'seconds')<br>+ (1 'milliseconds')<br>+ (1e3 'microseconds')<br>+ (1e6 'nanoseconds')<br>+ )<br>+ detect: [ :pair | elapsedTime * pair first >= count ]<br>+ ifNone: [ #(1e9 'picoseconds') ])<br>+ in: [ :pair |<br>+ ' {1} {2} per run.' format: {<br>+ (roundTo3Digits value: elapsedTime * pair first / count).<br>+ pair second } ]), (' {1} % GC time.' format: {gcTime / elapsedTime * 100 printShowingMaxDecimalPlaces: 5})!<br><br>Item was added:<br>+ ----- Method: Collection>>benchCompare (in category '*chronology-core') -----<br>+ benchCompare<br>+ "Each of my elements is a block to be benched. Bench each and answer a new collection which reports on each element of the receiver relative to the first."<br>+ ^ self benchCompareFor: 5 seconds!<br><br>Item was added:<br>+ ----- Method: Collection>>benchCompareFor: (in category '*chronology-core') -----<br>+ benchCompareFor: aDuration <br>+ "Each of my elements is a block to be benched. Bench each and answer a new collection which reports on each element of the receiver relative to the first."<br>+ ^ self<br>+ benchCompareFor: aDuration<br>+ do: [ : metrics | self benchMessageFor: metrics ]!<br><br>Item was added:<br>+ ----- Method: Collection>>benchCompareFor:do: (in category '*chronology-core-private') -----<br>+ benchCompareFor: aDuration do: aBlock<br>+ "Each of my elements is a block to be benched. Bench each and answer a new collection which reports on each element of the receiver as a fraction of the 'baseline' oscillation performance, an empty block."<br>+ | baselineMetrics |<br>+ ^ self asArray withIndexCollect: <br>+ [ : each : index | each sourceString -><br>+ (each<br>+ benchFor: aDuration<br>+ do:<br>+ [ : metrics |<br>+ index = 1 ifTrue: [ baselineMetrics := metrics ].<br>+ { #rate -> #relativeRate.<br>+ "any others?" } do:<br>+ [ : eachMetric |<br>+ metrics<br>+ at: eachMetric value<br>+ put: (metrics at: eachMetric key) / (baselineMetrics at: eachMetric key) ].<br>+ aBlock value: metrics ]) ]!<br><br>Item was added:<br>+ ----- Method: Collection>>benchMessageFor: (in category '*chronology-core-private') -----<br>+ benchMessageFor: metricsDictionary <br>+ "Answer a human-consumable String describing the performance<br>+ metrics within metricsDictionary."<br>+ ^ String<br>+ streamContents: <br>+ [ : stream | stream <br>+ nextPutAll: <br>+ ((metricsDictionary at: #relativeRate)<br>+ * 100 printShowingDecimalPlaces: 0)<br>+ , '% of baseline rate, ' ;<br>+ nextPutAll:<br>+ (["responsibility hack, Block knows how to print"]<br>+ benchMessageForTime: (metricsDictionary at: #time)<br>+ count: (metricsDictionary at: #count)<br>+ gc: (metricsDictionary at: #gcTime))]!<br><br><br></div></blockquote>
</div></body>