The Inbox: Chronology-Core-cmm.53.mcz

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

The Inbox: Chronology-Core-cmm.53.mcz

commits-2
Chris Muller uploaded a new version of Chronology-Core to project The Inbox:
http://source.squeak.org/inbox/Chronology-Core-cmm.53.mcz

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

Name: Chronology-Core-cmm.53
Author: cmm
Time: 29 April 2020, 6:51:53.53317 pm
UUID: b930b208-c85e-4c6b-8254-2837493384bd
Ancestors: Chronology-Core-nice.52

- Extend the API to allow an integral representation of DateAndTime's, by introducing

        DateAndTime class>>#fromMicroseconds:
        DateAndTime>>#asMicroseconds

which go along with the existing API:

        DateAndTime class>>#fromSeconds:
        DateAndTime>>#asSeconds

- Every Squeak with the substring "utcMicrosecond" in the selector name refers to the number of microseconds since the POSIX epoch (1/1/1971@00:00:00.000), __except for one__:  Time utcMicroseconds.  Therefore, to avoid astonishment when using it with the "utc" API of DateAndTime, rename it without the "utc" prefix.

=============== Diff against Chronology-Core-nice.52 ===============

Item was added:
+ ----- Method: DateAndTime class>>fromMicroseconds: (in category 'smalltalk-80') -----
+ fromMicroseconds: anInteger
+ "Answer a DateAndTime anInteger microseconds since the Squeak epoch: 1 January 1901."
+ ^ self
+ utcMicroseconds: anInteger - (self epochOffset * 1000000)
+ offset: self localOffsetSeconds!

Item was added:
+ ----- Method: DateAndTime>>asMicroseconds (in category 'smalltalk-80') -----
+ asMicroseconds
+ "Return the number of microseconds since the Squeak epoch, 1/1/1901 @ 00:00:00."
+ ^ utcMicroseconds + self class epochOffsetMicros!

Item was changed:
  ----- Method: Time class>>estimateHighResClockTicksPerMillisecond (in category 'clock') -----
  estimateHighResClockTicksPerMillisecond
 
  | t0 t1 t2 t3 |
 
  "Count the ticks ellapsed during a 10ms busy loop"
+ t0 := Time microsecondClock + 200.
+ [Time microsecondClock >= t0] whileFalse.
- t0 := Time utcMicrosecondClock + 200.
- [Time utcMicrosecondClock >= t0] whileFalse.
  t1 := self highResClock.
+ [Time microsecondClock >= (t0 + 10000)] whileFalse.
+ t1 := self highResClock - t1 * 1000 // (Time microsecondClock - t0).
- [Time utcMicrosecondClock >= (t0 + 10000)] whileFalse.
- t1 := self highResClock - t1 * 1000 // (Time utcMicrosecondClock - t0).
 
  "Count the ticks ellapsed during a 20ms busy loop"
+ t0 := Time microsecondClock + 200.
+ [Time microsecondClock >= t0] whileFalse.
- t0 := Time utcMicrosecondClock + 200.
- [Time utcMicrosecondClock >= t0] whileFalse.
  t2 := self highResClock.
+ [Time microsecondClock >= (t0 + 20000)] whileFalse.
+ t2 := self highResClock - t2 * 1000 // (Time microsecondClock - t0).
- [Time utcMicrosecondClock >= (t0 + 20000)] whileFalse.
- t2 := self highResClock - t2 * 1000 // (Time utcMicrosecondClock - t0).
 
  "Count the ticks ellapsed during a 30ms busy loop"
+ t0 := Time microsecondClock + 200.
+ [Time microsecondClock >= t0] whileFalse.
- t0 := Time utcMicrosecondClock + 200.
- [Time utcMicrosecondClock >= t0] whileFalse.
  t3 := self highResClock.
+ [Time microsecondClock >= (t0 + 30000)] whileFalse.
+ t3 := self highResClock - t3 * 1000 // (Time microsecondClock - t0).
- [Time utcMicrosecondClock >= (t0 + 30000)] whileFalse.
- t3 := self 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 changed:
  ----- Method: Time class>>localMicrosecondClock (in category 'clock') -----
  localMicrosecondClock
  "Answer the local microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
  The value is derived from the current UTC wallclock time and the image's current notion of time zone."
+ ^self microsecondClock + (DateAndTime localOffset asSeconds * 1000000)!
- ^self utcMicrosecondClock + (DateAndTime localOffset asSeconds * 1000000)!

Item was added:
+ ----- Method: Time class>>microsecondClock (in category 'clock') -----
+ microsecondClock
+ "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
+ The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
+ between the two epochs according to RFC 868."
+ <primitive: 240>
+ ^0!

Item was changed:
  ----- Method: Time class>>microsecondsToRun: (in category 'general inquiries') -----
  microsecondsToRun: timedBlock
  "Answer the number of microseconds timedBlock takes to return its value."
 
  | startUsecs |
  (self useHighResClockForTiming and: [self highResClock ~= 0])
  ifTrue: [ ^(self nanosecondsToRunHighRes: timedBlock) + 500 // 1000].
+ startUsecs := self microsecondClock.
- startUsecs := self utcMicrosecondClock.
  timedBlock value.
+ ^self microsecondClock - startUsecs!
- ^self utcMicrosecondClock - startUsecs!

Item was changed:
  ----- Method: Time class>>millisecondClockValue (in category 'general inquiries') -----
  millisecondClockValue
  "Answer the value of the millisecond clock."
 
+ ^self microsecondClock // 1000!
- ^self utcMicrosecondClock // 1000!

Item was changed:
  ----- Method: Time class>>nanosecondsToRun: (in category 'general inquiries') -----
  nanosecondsToRun: timedBlock
  "Answer the number of nanoseconds timedBlock takes to return its value.
  Use high resolution clock if available and preferred."
 
  | startUsecs |
  (self useHighResClockForTiming and: [self highResClock ~= 0])
  ifTrue: [ ^(self nanosecondsToRunHighRes: timedBlock)].
  "Fallback to microseconds clock"
+ startUsecs := self microsecondClock.
- startUsecs := self utcMicrosecondClock.
  timedBlock value.
+ ^self microsecondClock - startUsecs * 1000!
- ^self utcMicrosecondClock - startUsecs * 1000!

Item was added:
+ ----- Method: Time class>>totalMicroSeconds (in category 'smalltalk-80') -----
+ totalMicroSeconds
+ "Answer the total seconds since the Squeak epoch: 1 January 1901, in local time."
+
+ ^self localMicrosecondClock // 1000000!

Item was changed:
  ----- Method: Time class>>utcMicrosecondClock (in category 'clock') -----
  utcMicrosecondClock
  "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
  The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
  between the two epochs according to RFC 868."
  <primitive: 240>
+ self deprecated: 'Use #microsecondClock'.
  ^0!


Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Chronology-Core-cmm.53.mcz

Chris Muller-3
One of the main benefits of converting former Chronology's internal 3-element Array to an Integer should be to be able to easily translate back-and-forth between Integer and object (DateAndTime) representations.  With this, when creating log entries, you can simply access Time class>>#microsecondClock, which creates no garbage.  Then, to display the log, DateAndTime class>>#fromMicroseconds: will instantiate the proper instance of that time.

The "utc" prefix seems to be related to the name that Dave gave his alternative version of Chronology, and retained some of it when it was integrated into trunk.  I don't recall whether Time>>#utcMicrosecond was part of that, but if we can be willing to drop the prefix for that one selector, the API won't have this ambiguity that confused me for an evening.

Best,
  Chris


On Wed, Apr 29, 2020 at 6:51 PM <[hidden email]> wrote:
Chris Muller uploaded a new version of Chronology-Core to project The Inbox:
http://source.squeak.org/inbox/Chronology-Core-cmm.53.mcz

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

Name: Chronology-Core-cmm.53
Author: cmm
Time: 29 April 2020, 6:51:53.53317 pm
UUID: b930b208-c85e-4c6b-8254-2837493384bd
Ancestors: Chronology-Core-nice.52

- Extend the API to allow an integral representation of DateAndTime's, by introducing

        DateAndTime class>>#fromMicroseconds:
        DateAndTime>>#asMicroseconds

which go along with the existing API:

        DateAndTime class>>#fromSeconds:
        DateAndTime>>#asSeconds

- Every Squeak with the substring "utcMicrosecond" in the selector name refers to the number of microseconds since the POSIX epoch (1/1/1971@00:00:00.000), __except for one__:  Time utcMicroseconds.  Therefore, to avoid astonishment when using it with the "utc" API of DateAndTime, rename it without the "utc" prefix.

=============== Diff against Chronology-Core-nice.52 ===============

Item was added:
+ ----- Method: DateAndTime class>>fromMicroseconds: (in category 'smalltalk-80') -----
+ fromMicroseconds: anInteger
+       "Answer a DateAndTime anInteger microseconds since the Squeak epoch: 1 January 1901."
+       ^ self
+               utcMicroseconds: anInteger - (self epochOffset * 1000000)
+               offset: self localOffsetSeconds!

Item was added:
+ ----- Method: DateAndTime>>asMicroseconds (in category 'smalltalk-80') -----
+ asMicroseconds
+       "Return the number of microseconds since the Squeak epoch, 1/1/1901 @ 00:00:00."
+       ^ utcMicroseconds + self class epochOffsetMicros!

Item was changed:
  ----- Method: Time class>>estimateHighResClockTicksPerMillisecond (in category 'clock') -----
  estimateHighResClockTicksPerMillisecond

        | t0 t1 t2 t3 |

        "Count the ticks ellapsed during a 10ms busy loop"
+       t0 := Time microsecondClock + 200.
+       [Time microsecondClock >= t0] whileFalse.
-       t0 := Time utcMicrosecondClock + 200.
-       [Time utcMicrosecondClock >= t0] whileFalse.
        t1 := self highResClock.
+       [Time microsecondClock >= (t0 + 10000)] whileFalse.
+       t1 := self highResClock - t1 * 1000 // (Time microsecondClock - t0).
-       [Time utcMicrosecondClock >= (t0 + 10000)] whileFalse.
-       t1 := self highResClock - t1 * 1000 // (Time utcMicrosecondClock - t0).

        "Count the ticks ellapsed during a 20ms busy loop"
+       t0 := Time microsecondClock + 200.
+       [Time microsecondClock >= t0] whileFalse.
-       t0 := Time utcMicrosecondClock + 200.
-       [Time utcMicrosecondClock >= t0] whileFalse.
        t2 := self highResClock.
+       [Time microsecondClock >= (t0 + 20000)] whileFalse.
+       t2 := self highResClock - t2 * 1000 // (Time microsecondClock - t0).
-       [Time utcMicrosecondClock >= (t0 + 20000)] whileFalse.
-       t2 := self highResClock - t2 * 1000 // (Time utcMicrosecondClock - t0).

        "Count the ticks ellapsed during a 30ms busy loop"
+       t0 := Time microsecondClock + 200.
+       [Time microsecondClock >= t0] whileFalse.
-       t0 := Time utcMicrosecondClock + 200.
-       [Time utcMicrosecondClock >= t0] whileFalse.
        t3 := self highResClock.
+       [Time microsecondClock >= (t0 + 30000)] whileFalse.
+       t3 := self highResClock - t3 * 1000 // (Time microsecondClock - t0).
-       [Time utcMicrosecondClock >= (t0 + 30000)] whileFalse.
-       t3 := self 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 changed:
  ----- Method: Time class>>localMicrosecondClock (in category 'clock') -----
  localMicrosecondClock
        "Answer the local microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
         The value is derived from the current UTC wallclock time and the image's current notion of time zone."
+       ^self microsecondClock + (DateAndTime localOffset asSeconds * 1000000)!
-       ^self utcMicrosecondClock + (DateAndTime localOffset asSeconds * 1000000)!

Item was added:
+ ----- Method: Time class>>microsecondClock (in category 'clock') -----
+ microsecondClock
+       "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
+        The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
+        between the two epochs according to RFC 868."
+       <primitive: 240>
+       ^0!

Item was changed:
  ----- Method: Time class>>microsecondsToRun: (in category 'general inquiries') -----
  microsecondsToRun: timedBlock
        "Answer the number of microseconds timedBlock takes to return its value."

        | startUsecs |
        (self useHighResClockForTiming and: [self highResClock ~= 0])
                ifTrue: [       ^(self nanosecondsToRunHighRes: timedBlock) + 500 // 1000].
+       startUsecs := self microsecondClock.
-       startUsecs := self utcMicrosecondClock.
        timedBlock value.
+       ^self microsecondClock - startUsecs!
-       ^self utcMicrosecondClock - startUsecs!

Item was changed:
  ----- Method: Time class>>millisecondClockValue (in category 'general inquiries') -----
  millisecondClockValue
        "Answer the value of the millisecond clock."

+       ^self microsecondClock // 1000!
-       ^self utcMicrosecondClock // 1000!

Item was changed:
  ----- Method: Time class>>nanosecondsToRun: (in category 'general inquiries') -----
  nanosecondsToRun: timedBlock
        "Answer the number of nanoseconds timedBlock takes to return its value.
        Use high resolution clock if available and preferred."

        | startUsecs |
        (self useHighResClockForTiming and: [self highResClock ~= 0])
                ifTrue: [       ^(self nanosecondsToRunHighRes: timedBlock)].
        "Fallback to microseconds clock"
+       startUsecs := self microsecondClock.
-       startUsecs := self utcMicrosecondClock.
        timedBlock value.
+       ^self microsecondClock - startUsecs * 1000!
-       ^self utcMicrosecondClock - startUsecs * 1000!

Item was added:
+ ----- Method: Time class>>totalMicroSeconds (in category 'smalltalk-80') -----
+ totalMicroSeconds
+       "Answer the total seconds since the Squeak epoch: 1 January 1901, in local time."
+
+       ^self localMicrosecondClock // 1000000!

Item was changed:
  ----- Method: Time class>>utcMicrosecondClock (in category 'clock') -----
  utcMicrosecondClock
        "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
         The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
         between the two epochs according to RFC 868."
        <primitive: 240>
+ self deprecated: 'Use #microsecondClock'.
        ^0!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Chronology-Core-cmm.53.mcz

Chris Muller-3
In reply to this post by commits-2
Oh, about this part:

+ ----- Method: Time class>>totalMicroSeconds (in category 'smalltalk-80') -----
+ totalMicroSeconds
+       "Answer the total seconds since the Squeak epoch: 1 January 1901, in local time."
+
+       ^self localMicrosecondClock // 1000000!

I'm not sure whether #totalSeconds (or anyone) should be using #localMicrosecondClock anymore, but I included the above method too, just in case.

On Wed, Apr 29, 2020 at 6:51 PM <[hidden email]> wrote:
Chris Muller uploaded a new version of Chronology-Core to project The Inbox:
http://source.squeak.org/inbox/Chronology-Core-cmm.53.mcz

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

Name: Chronology-Core-cmm.53
Author: cmm
Time: 29 April 2020, 6:51:53.53317 pm
UUID: b930b208-c85e-4c6b-8254-2837493384bd
Ancestors: Chronology-Core-nice.52

- Extend the API to allow an integral representation of DateAndTime's, by introducing

        DateAndTime class>>#fromMicroseconds:
        DateAndTime>>#asMicroseconds

which go along with the existing API:

        DateAndTime class>>#fromSeconds:
        DateAndTime>>#asSeconds

- Every Squeak with the substring "utcMicrosecond" in the selector name refers to the number of microseconds since the POSIX epoch (1/1/1971@00:00:00.000), __except for one__:  Time utcMicroseconds.  Therefore, to avoid astonishment when using it with the "utc" API of DateAndTime, rename it without the "utc" prefix.

=============== Diff against Chronology-Core-nice.52 ===============

Item was added:
+ ----- Method: DateAndTime class>>fromMicroseconds: (in category 'smalltalk-80') -----
+ fromMicroseconds: anInteger
+       "Answer a DateAndTime anInteger microseconds since the Squeak epoch: 1 January 1901."
+       ^ self
+               utcMicroseconds: anInteger - (self epochOffset * 1000000)
+               offset: self localOffsetSeconds!

Item was added:
+ ----- Method: DateAndTime>>asMicroseconds (in category 'smalltalk-80') -----
+ asMicroseconds
+       "Return the number of microseconds since the Squeak epoch, 1/1/1901 @ 00:00:00."
+       ^ utcMicroseconds + self class epochOffsetMicros!

Item was changed:
  ----- Method: Time class>>estimateHighResClockTicksPerMillisecond (in category 'clock') -----
  estimateHighResClockTicksPerMillisecond

        | t0 t1 t2 t3 |

        "Count the ticks ellapsed during a 10ms busy loop"
+       t0 := Time microsecondClock + 200.
+       [Time microsecondClock >= t0] whileFalse.
-       t0 := Time utcMicrosecondClock + 200.
-       [Time utcMicrosecondClock >= t0] whileFalse.
        t1 := self highResClock.
+       [Time microsecondClock >= (t0 + 10000)] whileFalse.
+       t1 := self highResClock - t1 * 1000 // (Time microsecondClock - t0).
-       [Time utcMicrosecondClock >= (t0 + 10000)] whileFalse.
-       t1 := self highResClock - t1 * 1000 // (Time utcMicrosecondClock - t0).

        "Count the ticks ellapsed during a 20ms busy loop"
+       t0 := Time microsecondClock + 200.
+       [Time microsecondClock >= t0] whileFalse.
-       t0 := Time utcMicrosecondClock + 200.
-       [Time utcMicrosecondClock >= t0] whileFalse.
        t2 := self highResClock.
+       [Time microsecondClock >= (t0 + 20000)] whileFalse.
+       t2 := self highResClock - t2 * 1000 // (Time microsecondClock - t0).
-       [Time utcMicrosecondClock >= (t0 + 20000)] whileFalse.
-       t2 := self highResClock - t2 * 1000 // (Time utcMicrosecondClock - t0).

        "Count the ticks ellapsed during a 30ms busy loop"
+       t0 := Time microsecondClock + 200.
+       [Time microsecondClock >= t0] whileFalse.
-       t0 := Time utcMicrosecondClock + 200.
-       [Time utcMicrosecondClock >= t0] whileFalse.
        t3 := self highResClock.
+       [Time microsecondClock >= (t0 + 30000)] whileFalse.
+       t3 := self highResClock - t3 * 1000 // (Time microsecondClock - t0).
-       [Time utcMicrosecondClock >= (t0 + 30000)] whileFalse.
-       t3 := self 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 changed:
  ----- Method: Time class>>localMicrosecondClock (in category 'clock') -----
  localMicrosecondClock
        "Answer the local microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
         The value is derived from the current UTC wallclock time and the image's current notion of time zone."
+       ^self microsecondClock + (DateAndTime localOffset asSeconds * 1000000)!
-       ^self utcMicrosecondClock + (DateAndTime localOffset asSeconds * 1000000)!

Item was added:
+ ----- Method: Time class>>microsecondClock (in category 'clock') -----
+ microsecondClock
+       "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
+        The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
+        between the two epochs according to RFC 868."
+       <primitive: 240>
+       ^0!

Item was changed:
  ----- Method: Time class>>microsecondsToRun: (in category 'general inquiries') -----
  microsecondsToRun: timedBlock
        "Answer the number of microseconds timedBlock takes to return its value."

        | startUsecs |
        (self useHighResClockForTiming and: [self highResClock ~= 0])
                ifTrue: [       ^(self nanosecondsToRunHighRes: timedBlock) + 500 // 1000].
+       startUsecs := self microsecondClock.
-       startUsecs := self utcMicrosecondClock.
        timedBlock value.
+       ^self microsecondClock - startUsecs!
-       ^self utcMicrosecondClock - startUsecs!

Item was changed:
  ----- Method: Time class>>millisecondClockValue (in category 'general inquiries') -----
  millisecondClockValue
        "Answer the value of the millisecond clock."

+       ^self microsecondClock // 1000!
-       ^self utcMicrosecondClock // 1000!

Item was changed:
  ----- Method: Time class>>nanosecondsToRun: (in category 'general inquiries') -----
  nanosecondsToRun: timedBlock
        "Answer the number of nanoseconds timedBlock takes to return its value.
        Use high resolution clock if available and preferred."

        | startUsecs |
        (self useHighResClockForTiming and: [self highResClock ~= 0])
                ifTrue: [       ^(self nanosecondsToRunHighRes: timedBlock)].
        "Fallback to microseconds clock"
+       startUsecs := self microsecondClock.
-       startUsecs := self utcMicrosecondClock.
        timedBlock value.
+       ^self microsecondClock - startUsecs * 1000!
-       ^self utcMicrosecondClock - startUsecs * 1000!

Item was added:
+ ----- Method: Time class>>totalMicroSeconds (in category 'smalltalk-80') -----
+ totalMicroSeconds
+       "Answer the total seconds since the Squeak epoch: 1 January 1901, in local time."
+
+       ^self localMicrosecondClock // 1000000!

Item was changed:
  ----- Method: Time class>>utcMicrosecondClock (in category 'clock') -----
  utcMicrosecondClock
        "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
         The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
         between the two epochs according to RFC 868."
        <primitive: 240>
+ self deprecated: 'Use #microsecondClock'.
        ^0!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Chronology-Core-cmm.53.mcz

Levente Uzonyi
In reply to this post by Chris Muller-3
Hi Chris,

On Wed, 29 Apr 2020, Chris Muller wrote:

> One of the main benefits of converting former Chronology's internal 3-element Array to an Integer should be to be able to easily translate back-and-forth between Integer and object (DateAndTime) representations.  With this,
> when creating log entries, you can simply access Time class>>#microsecondClock, which creates no garbage.  Then, to display the log, DateAndTime class>>#fromMicroseconds: will instantiate the proper instance of that time.

You may as well store the posix microseconds and recreate the
DateAndTime instance with #utcMicroseconds:offset:.
To get the clock value, you can either use
#primPosixMicrosecondClockWithOffset: directly or you can use primitive
240 and subtract the offset yourself.
That way you can avoid introducing a new API serving only a very specific
goal.
The VM clock is not monotonic, so you may want to use Time class >>
#posixMicrosecondClockWithOffset: to get monotonic values.

Because of the above and because of the non-descriptive names, -1 from me
for #fromMicroseconds: and #asMicroseconds.

Also -1 for #microsecondClock. That would be the third (actually fourth
but one was a typo) name for that primitive, and I'm bored migrating code
from one to another because someone didn't like some part of the selector.

>
> The "utc" prefix seems to be related to the name that Dave gave his alternative version of Chronology, and retained some of it when it was integrated into trunk.  I don't recall whether Time>>#utcMicrosecond was part of that,
> but if we can be willing to drop the prefix for that one selector, the API won't have this ambiguity that confused me for an evening.

The utc prefix tells me about the time zone offset. Its use is clear;
removing it would introduce amiguity.

Dave's "new" implementation uses the posix epoch. I'm surprised people
who took part in its discussion 4-5 years ago seem to not be aware of
that.


Levente

>
> Best,
>   Chris
>
>
> On Wed, Apr 29, 2020 at 6:51 PM <[hidden email]> wrote:
>       Chris Muller uploaded a new version of Chronology-Core to project The Inbox:
>       http://source.squeak.org/inbox/Chronology-Core-cmm.53.mcz
>
>       ==================== Summary ====================
>
>       Name: Chronology-Core-cmm.53
>       Author: cmm
>       Time: 29 April 2020, 6:51:53.53317 pm
>       UUID: b930b208-c85e-4c6b-8254-2837493384bd
>       Ancestors: Chronology-Core-nice.52
>
>       - Extend the API to allow an integral representation of DateAndTime's, by introducing
>
>               DateAndTime class>>#fromMicroseconds:
>               DateAndTime>>#asMicroseconds
>
>       which go along with the existing API:
>
>               DateAndTime class>>#fromSeconds:
>               DateAndTime>>#asSeconds
>
>       - Every Squeak with the substring "utcMicrosecond" in the selector name refers to the number of microseconds since the POSIX epoch (1/1/1971@00:00:00.000), __except for one__:  Time utcMicroseconds.  Therefore, to
>       avoid astonishment when using it with the "utc" API of DateAndTime, rename it without the "utc" prefix.
>
>       =============== Diff against Chronology-Core-nice.52 ===============
>
>       Item was added:
>       + ----- Method: DateAndTime class>>fromMicroseconds: (in category 'smalltalk-80') -----
>       + fromMicroseconds: anInteger
>       +       "Answer a DateAndTime anInteger microseconds since the Squeak epoch: 1 January 1901."
>       +       ^ self
>       +               utcMicroseconds: anInteger - (self epochOffset * 1000000)
>       +               offset: self localOffsetSeconds!
>
>       Item was added:
>       + ----- Method: DateAndTime>>asMicroseconds (in category 'smalltalk-80') -----
>       + asMicroseconds
>       +       "Return the number of microseconds since the Squeak epoch, 1/1/1901 @ 00:00:00."
>       +       ^ utcMicroseconds + self class epochOffsetMicros!
>
>       Item was changed:
>         ----- Method: Time class>>estimateHighResClockTicksPerMillisecond (in category 'clock') -----
>         estimateHighResClockTicksPerMillisecond
>
>               | t0 t1 t2 t3 |
>
>               "Count the ticks ellapsed during a 10ms busy loop"
>       +       t0 := Time microsecondClock + 200.
>       +       [Time microsecondClock >= t0] whileFalse.
>       -       t0 := Time utcMicrosecondClock + 200.
>       -       [Time utcMicrosecondClock >= t0] whileFalse.
>               t1 := self highResClock.
>       +       [Time microsecondClock >= (t0 + 10000)] whileFalse.
>       +       t1 := self highResClock - t1 * 1000 // (Time microsecondClock - t0).
>       -       [Time utcMicrosecondClock >= (t0 + 10000)] whileFalse.
>       -       t1 := self highResClock - t1 * 1000 // (Time utcMicrosecondClock - t0).
>
>               "Count the ticks ellapsed during a 20ms busy loop"
>       +       t0 := Time microsecondClock + 200.
>       +       [Time microsecondClock >= t0] whileFalse.
>       -       t0 := Time utcMicrosecondClock + 200.
>       -       [Time utcMicrosecondClock >= t0] whileFalse.
>               t2 := self highResClock.
>       +       [Time microsecondClock >= (t0 + 20000)] whileFalse.
>       +       t2 := self highResClock - t2 * 1000 // (Time microsecondClock - t0).
>       -       [Time utcMicrosecondClock >= (t0 + 20000)] whileFalse.
>       -       t2 := self highResClock - t2 * 1000 // (Time utcMicrosecondClock - t0).
>
>               "Count the ticks ellapsed during a 30ms busy loop"
>       +       t0 := Time microsecondClock + 200.
>       +       [Time microsecondClock >= t0] whileFalse.
>       -       t0 := Time utcMicrosecondClock + 200.
>       -       [Time utcMicrosecondClock >= t0] whileFalse.
>               t3 := self highResClock.
>       +       [Time microsecondClock >= (t0 + 30000)] whileFalse.
>       +       t3 := self highResClock - t3 * 1000 // (Time microsecondClock - t0).
>       -       [Time utcMicrosecondClock >= (t0 + 30000)] whileFalse.
>       -       t3 := self 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 changed:
>         ----- Method: Time class>>localMicrosecondClock (in category 'clock') -----
>         localMicrosecondClock
>               "Answer the local microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
>                The value is derived from the current UTC wallclock time and the image's current notion of time zone."
>       +       ^self microsecondClock + (DateAndTime localOffset asSeconds * 1000000)!
>       -       ^self utcMicrosecondClock + (DateAndTime localOffset asSeconds * 1000000)!
>
>       Item was added:
>       + ----- Method: Time class>>microsecondClock (in category 'clock') -----
>       + microsecondClock
>       +       "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
>       +        The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
>       +        between the two epochs according to RFC 868."
>       +       <primitive: 240>
>       +       ^0!
>
>       Item was changed:
>         ----- Method: Time class>>microsecondsToRun: (in category 'general inquiries') -----
>         microsecondsToRun: timedBlock
>               "Answer the number of microseconds timedBlock takes to return its value."
>
>               | startUsecs |
>               (self useHighResClockForTiming and: [self highResClock ~= 0])
>                       ifTrue: [       ^(self nanosecondsToRunHighRes: timedBlock) + 500 // 1000].
>       +       startUsecs := self microsecondClock.
>       -       startUsecs := self utcMicrosecondClock.
>               timedBlock value.
>       +       ^self microsecondClock - startUsecs!
>       -       ^self utcMicrosecondClock - startUsecs!
>
>       Item was changed:
>         ----- Method: Time class>>millisecondClockValue (in category 'general inquiries') -----
>         millisecondClockValue
>               "Answer the value of the millisecond clock."
>
>       +       ^self microsecondClock // 1000!
>       -       ^self utcMicrosecondClock // 1000!
>
>       Item was changed:
>         ----- Method: Time class>>nanosecondsToRun: (in category 'general inquiries') -----
>         nanosecondsToRun: timedBlock
>               "Answer the number of nanoseconds timedBlock takes to return its value.
>               Use high resolution clock if available and preferred."
>
>               | startUsecs |
>               (self useHighResClockForTiming and: [self highResClock ~= 0])
>                       ifTrue: [       ^(self nanosecondsToRunHighRes: timedBlock)].
>               "Fallback to microseconds clock"
>       +       startUsecs := self microsecondClock.
>       -       startUsecs := self utcMicrosecondClock.
>               timedBlock value.
>       +       ^self microsecondClock - startUsecs * 1000!
>       -       ^self utcMicrosecondClock - startUsecs * 1000!
>
>       Item was added:
>       + ----- Method: Time class>>totalMicroSeconds (in category 'smalltalk-80') -----
>       + totalMicroSeconds
>       +       "Answer the total seconds since the Squeak epoch: 1 January 1901, in local time."
>       +
>       +       ^self localMicrosecondClock // 1000000!
>
>       Item was changed:
>         ----- Method: Time class>>utcMicrosecondClock (in category 'clock') -----
>         utcMicrosecondClock
>               "Answer the UTC microseconds since the Smalltalk epoch (January 1st 1901, the start of the 20th century).
>                The value is derived from the Posix epoch with a constant offset corresponding to elapsed microseconds
>                between the two epochs according to RFC 868."
>               <primitive: 240>
>       + self deprecated: 'Use #microsecondClock'.
>               ^0!
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Chronology-Core-cmm.53.mcz

Chris Muller-3
Hi Levente,

> One of the main benefits of converting former Chronology's internal 3-element Array to an Integer should be to be able to easily translate back-and-forth between Integer and object (DateAndTime) representations.  With this,
> when creating log entries, you can simply access Time class>>#microsecondClock, which creates no garbage.  Then, to display the log, DateAndTime class>>#fromMicroseconds: will instantiate the proper instance of that time.

You may as well store the posix microseconds and recreate the
DateAndTime instance with #utcMicroseconds:offset:.
To get the clock value, you can either use
#primPosixMicrosecondClockWithOffset: directly

As I mentioned to Dave, I wish to not create a bunch of unnecessary garbage.  Maybe you're suggesting I create my own two-pointer object only once and use it over and over, but I need thread safety.
 
or you can use primitive
240 and subtract the offset yourself.

That's all what this does.  Brings two parts of the API into compatible use with each other...
 
That way you can avoid introducing a new API

We already have #fromSeconds: and #asSeconds, so this is not really "new API", as much as rounding out existing API that just allows the domain to expose its underlying precision.  UTC DateAndTime's new internal representation was supposed to be one of its main selling points...
 
serving only a very specific
goal.

Efficient sub-second timings are not application-specific.  Look at all the new API added from Chronology-Core-nice.41 through Chronology-Core-nice.44 -- way more than this -- introduced to support high-precision clocks.  I don't recall you ever objecting to that..

The VM clock is not monotonic, so you may want to use Time class >>
#posixMicrosecondClockWithOffset: to get monotonic values.

I don't actually need monotonicity here.  I really just want efficiency.  I thought you, of all, would appreciate that.
 
Because of the above and because of the non-descriptive names, -1 from me
for #fromMicroseconds: and #asMicroseconds.

Also -1 for #microsecondClock. That would be the third (actually fourth
but one was a typo) name for that primitive, and I'm bored migrating code
from one to another because someone didn't like some part of the selector.

:)  Well, I don't want you to be bored, but I'm afraid that's not an argument.  You know how Squeak respects its users for upgrading their code.  This is only deprecated.  Check that box, you won't have to migrate anything.  But Squeak must continue to move forward...  :)

And it isn't about "not liking it" due to taste, but because it fosters a major disconnect in the reader due to the similar nomenclature used between Time and DateAndTime.  Seriously, you're okay with Time utcMicrosecondClock being so misleadingly (and, silently!) incompatible with DateAndTime utcMicroseconds:offset:?

> The "utc" prefix seems to be related to the name that Dave gave his alternative version of Chronology, and retained some of it when it was integrated into trunk.  I don't recall whether Time>>#utcMicrosecond was part of that,
> but if we can be willing to drop the prefix for that one selector, the API won't have this ambiguity that confused me for an evening.

The utc prefix tells me about the time zone offset. Its use is clear;
removing it would introduce amiguity.

Dave's "new" implementation uses the posix epoch. I'm surprised people
who took part in its discussion 4-5 years ago seem to not be aware of
that.

A testament to how confusingly disjointed this particular part of the API is, Levente.  Please consider users' experience of when they read Squeak's API's the first time.  Smalltalk is supposed to be a "legendary" class library.  Chronology's API is fantastic, but this blemish stands out.  IMO, we should fix it.

 - Chris



Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Chronology-Core-cmm.53.mcz

David T. Lewis
In reply to this post by commits-2
On Wed, Apr 29, 2020 at 11:51:55PM +0000, [hidden email] wrote:

> Chris Muller uploaded a new version of Chronology-Core to project The Inbox:
> http://source.squeak.org/inbox/Chronology-Core-cmm.53.mcz
>
> ==================== Summary ====================
>
> Name: Chronology-Core-cmm.53
> Author: cmm
> Time: 29 April 2020, 6:51:53.53317 pm
> UUID: b930b208-c85e-4c6b-8254-2837493384bd
> Ancestors: Chronology-Core-nice.52
>
> - Extend the API to allow an integral representation of DateAndTime's, by introducing
>
> DateAndTime class>>#fromMicroseconds:
> DateAndTime>>#asMicroseconds
>
> which go along with the existing API:
>
> DateAndTime class>>#fromSeconds:
> DateAndTime>>#asSeconds

-1

There is no need to add to the API. You already have Smalltalk seconds
at any level of precision care to use.

  now := DateAndTime now. "==> 2020-05-01T09:54:37.73365-04:00"
  seconds := now asExactSeconds.
  seconds asScaledDecimal. "==> 3765794077.73365s5"
  copyOfNow := DateAndTime fromSeconds: seconds.
  copyOfNow utcMicroseconds. "1588341277733650"
  now utcMicroseconds. "==> 1588341277733650"
  copyOfNow = now. "==> true"

>
> - Every Squeak with the substring "utcMicrosecond" in the selector name refers to the number of microseconds since the POSIX epoch (1/1/1971@00:00:00.000), __except for one__:  Time utcMicroseconds.  Therefore, to avoid astonishment when using it with the "utc" API of DateAndTime, rename it without the "utc" prefix.
>

+1

However, it is probably not a good idea to modify the existing method.
It may be safer to "deprecate" it by hiding it in a private category,
and updating the method comment to encourage people to use the new
name in the future.

Dave

Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Chronology-Core-cmm.53.mcz

Levente Uzonyi
In reply to this post by Chris Muller-3
Hi Chris,

On Thu, 30 Apr 2020, Chris Muller wrote:

> Hi Levente,
>
>       > One of the main benefits of converting former Chronology's internal 3-element Array to an Integer should be to be able to easily translate back-and-forth between Integer and object (DateAndTime) representations.  With this,
>       > when creating log entries, you can simply access Time class>>#microsecondClock, which creates no garbage.  Then, to display the log, DateAndTime class>>#fromMicroseconds: will instantiate the proper instance of that time.
>
>       You may as well store the posix microseconds and recreate the
>       DateAndTime instance with #utcMicroseconds:offset:.
>       To get the clock value, you can either use
>       #primPosixMicrosecondClockWithOffset: directly
>
>
> As I mentioned to Dave, I wish to not create a bunch of unnecessary garbage.  Maybe you're suggesting I create my own two-pointer object only once and use it over and over, but I need thread safety.
It's fairly easy to achieve that with a process local variable.

>  
>       or you can use primitive
>       240 and subtract the offset yourself.
>
>
> That's all what this does.  Brings two parts of the API into compatible use with each other...

It brings two things closer together, but those two things are not as
much related as you think.
And the way it does that causes problems for others.
If I were to do this, I just would add


Time class >> #posixUtcMicrosecondClock
  "Answer the UTC microseconds since the POSIX epoch."

  ^self utcMicrosecondClock - MicrosecondsBetweenPosixEpochAndSqueakEpoch


and


ChronologyConstants class >> #initialize
  "ChronologyConstants initialize"

  ...

  MicrosecondsBetweenPosixEpochAndSqueakEpoch := 2177452800000000


Efficient, unambiguous, thread-safe.
To turn the number into a DateAndTime object, #utcMicroseconds:offset:
is already there. (Yes, it would be better if that method had a 'posix'
prefix.)

>  
>       That way you can avoid introducing a new API
>
>
> We already have #fromSeconds: and #asSeconds, so this is not really "new API", as much as rounding out existing API that just allows the domain to expose its underlying precision.  UTC DateAndTime's new internal representation was supposed to be one of its main selling points...

Just because there's existing bad API, we shouldn't add more, should we?

>  
>       serving only a very specific
>       goal.
>
>
> Efficient sub-second timings are not application-specific.  Look at all the new API added from Chronology-Core-nice.41 through Chronology-Core-nice.44 -- way more than this -- introduced to support high-precision clocks.  I don't recall you ever objecting to that..

I'm not against introducting new API. I'm against introducting bad API.

>
>       The VM clock is not monotonic, so you may want to use Time class >>
>       #posixMicrosecondClockWithOffset: to get monotonic values.
>
>
> I don't actually need monotonicity here.  I really just want efficiency.  I thought you, of all, would appreciate that.

I suppose my suggestion above is the best you can achieve in Smalltalk
in terms of efficiency.

>  
>       Because of the above and because of the non-descriptive names, -1 from me
>       for #fromMicroseconds: and #asMicroseconds.
>
>       Also -1 for #microsecondClock. That would be the third (actually fourth
>       but one was a typo) name for that primitive, and I'm bored migrating code
>       from one to another because someone didn't like some part of the selector.
>
>
> :)  Well, I don't want you to be bored, but I'm afraid that's not an argument.  You know how Squeak respects its users for upgrading their code.  This is only deprecated.  Check that box, you won't have to migrate anything.  But Squeak must continue to move forward...  :)
>
> And it isn't about "not liking it" due to taste, but because it fosters a major disconnect in the reader due to the similar nomenclature used between Time and DateAndTime.  Seriously, you're okay with Time utcMicrosecondClock being so misleadingly (and, silently!) incompatible with DateAndTime
> utcMicroseconds:offset:?
It is unfortunate that
- #utcMicrosecondsClock is implemented as a class side method of Time,
because it's unrelated to Time (renaming it to #microsecondsClock would
not help with that)
- #utcMicroseconds:offset: is not called #posixUtcMicroseconds:offset:

>
>       > The "utc" prefix seems to be related to the name that Dave gave his alternative version of Chronology, and retained some of it when it was integrated into trunk.  I don't recall whether Time>>#utcMicrosecond was part of that,
>       > but if we can be willing to drop the prefix for that one selector, the API won't have this ambiguity that confused me for an evening.
>
>       The utc prefix tells me about the time zone offset. Its use is clear;
>       removing it would introduce amiguity.
>
>       Dave's "new" implementation uses the posix epoch. I'm surprised people
>       who took part in its discussion 4-5 years ago seem to not be aware of
>       that.
>
>
> A testament to how confusingly disjointed this particular part of the API is, Levente.  Please consider users' experience of when they read Squeak's API's the first time.  Smalltalk is supposed to be a "legendary" class library.  Chronology's API is fantastic, but this blemish stands out.  IMO, we should fix it.
Sorry, but I don't see it fantastic at all.


Levente

>
>  - Chris
>
>
>