The Inbox: Chronology-Core-nice.41.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Inbox: Chronology-Core-nice.41.mcz

commits-2
Nicolas Cellier uploaded a new version of Chronology-Core to project The Inbox:
http://source.squeak.org/inbox/Chronology-Core-nice.41.mcz

==================== Summary ====================

Name: Chronology-Core-nice.41
Author: nice
Time: 23 April 2019, 11:52:55.257088 pm
UUID: e4abf0f8-228d-4456-b296-92764394926c
Ancestors: Chronology-Core-dtl.40

Provide access to high resolution clock (if any).

This is especially useful for micro-benchmarks, so provide a #durationToRun: based on high-res clock if available.
As the name tells, it will answer a Duration rather than a number of milliseconds, microseconds or whatever...
A duration is way more universal and self-explaining than currently obscure Integer encoding returned by:

        [100 factorial] timeToRun.

The aim is either to provide a new #durationToRun selector, or replace #timeToRun semantics...

Provide a microsecondsToRun: fallback in case the host does not provide a high resolution clock.

Notes: the number of ticks per millisecond for the high-res clock is roughly estimated by a busy loop like found in the AndreasSystemProfiler.
It is reset at startup, and initialized once at first use with the assumption that it will be constant.

=============== Diff against Chronology-Core-dtl.40 ===============

Item was changed:
  Magnitude subclass: #Time
  instanceVariableNames: 'seconds nanos'
+ classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick'
- classVariableNames: 'ClockPolicy LastClockTick'
  poolDictionaries: 'ChronologyConstants'
  category: 'Chronology-Core'!
 
  !Time commentStamp: 'dew 10/23/2004 17:58' prior: 0!
  This represents a particular point in time during any given day.  For example, '5:19:45 pm'.
 
  If you need a point in time on a particular day, use DateAndTime.  If you need a duration of time, use Duration.
  !

Item was added:
+ ----- Method: Time class>>durationToRun: (in category 'general inquiries') -----
+ durationToRun: timedBlock
+ "Answer a duration timedBlock takes to return its value.
+ Use high resolution clock if available."
+
+ | ticks |
+ self highResClock = 0 ifTrue: [^Duration nanoSeconds: 1000 * (self microsecondsToRun: timedBlock)].
+ ticks := self highResClock.
+ timedBlock value.
+ ticks := self highResClock - ticks.
+ ^Duration nanoSeconds: 1000000* ticks // self highResClockTicksPerMillisecond!

Item was added:
+ ----- Method: Time class>>estimateHighResClockTicksPerMillisecond (in category 'clock') -----
+ estimateHighResClockTicksPerMillisecond
+
+ | t0 t1 t2 t3 |
+
+ "Count the ticks ellapsed during a 10ms busy loop"
+ t0 := Time utcMicrosecondClock + 200.
+ [Time utcMicrosecondClock >= t0] whileFalse.
+ t1 := Smalltalk highResClock.
+ [Time utcMicrosecondClock >= (t0 + 10000)] whileFalse.
+ t1 := Smalltalk highResClock - t1 * 1000 // (Time utcMicrosecondClock - t0).
+
+ "Count the ticks ellapsed during a 20ms busy loop"
+ t0 := Time utcMicrosecondClock + 200.
+ [Time utcMicrosecondClock >= t0] whileFalse.
+ t2 := Smalltalk highResClock.
+ [Time utcMicrosecondClock >= (t0 + 20000)] whileFalse.
+ t2 := Smalltalk highResClock - t2 * 1000 // (Time utcMicrosecondClock - t0).
+
+ "Count the ticks ellapsed during a 30ms busy loop"
+ t0 := Time utcMicrosecondClock + 200.
+ [Time utcMicrosecondClock >= t0] whileFalse.
+ t3 := Smalltalk highResClock.
+ [Time utcMicrosecondClock >= (t0 + 30000)] whileFalse.
+ t3 := Smalltalk highResClock - t3 * 1000 // (Time utcMicrosecondClock - t0).
+
+ "Take the median of the 3 estimates as the best"
+ ^ t1 <= t2
+ ifTrue: [t2 <= t3
+ ifTrue: [t2]
+ ifFalse: [t1 <= t3
+ ifTrue: [t3]
+ ifFalse: [t1]]]
+ ifFalse: [t1 <= t3
+ ifTrue: [t1]
+ ifFalse: [t2 <= t3
+ ifTrue: [t3]
+ ifFalse: [t2]]]!

Item was added:
+ ----- Method: Time class>>highResClock (in category 'clock') -----
+ highResClock
+ "Time highResClock"
+ "Primitive. Answer the value of the high resolution clock if this computer has one.
+ Usually, this should be the highest resolution value available, for example on Intel
+ it will be the value of the time stamp counter register."
+ <primitive: 'primitiveHighResClock'>
+ ^0!

Item was added:
+ ----- Method: Time class>>highResClockTicksPerMillisecond (in category 'clock') -----
+ highResClockTicksPerMillisecond
+ HighResClockTicksPerMillisecond = 0
+ ifTrue:
+ [HighResClockTicksPerMillisecond := self estimateHighResClockTicksPerMillisecond].
+ ^HighResClockTicksPerMillisecond!

Item was changed:
  ----- Method: Time class>>initialize (in category 'class initialization') -----
  initialize
  "Time initialize"
 
  "Initialize at startup time to protect for the case of an image saved with bad LastClockTick"
  LastClockTick := 0.
+
+ HighResClockTicksPerMillisecond := 0.
 
  "self clockPolicy: #acceptPlatformTime."
  self clockPolicy: #monotonicAllowDuplicates.
  "self clockPolicy: #monotonicForceMicrosecondIncrement."
  "self clockPolicy: #monotonicForceNanosecondIncrement."
  !

Item was added:
+ ----- Method: Time class>>microsecondsToRun: (in category 'general inquiries') -----
+ microsecondsToRun: timedBlock
+ "Answer the number of microseconds timedBlock takes to return its value."
+
+ | startUsecs |
+ startUsecs := self utcMicrosecondClock.
+ timedBlock value.
+ ^self utcMicrosecondClock - startUsecs!

Item was changed:
  ----- Method: Time class>>millisecondsToRun: (in category 'general inquiries') -----
  millisecondsToRun: timedBlock
  "Answer the number of milliseconds timedBlock takes to return its value."
 
+ ^(self microsecondsToRun: timedBlock) + 500 // 1000!
- | startUsecs |
- startUsecs := self utcMicrosecondClock.
- timedBlock value.
- ^self utcMicrosecondClock - startUsecs + 500 // 1000!