<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>