[Pharo-project] DateAndTime bug: we should do something about it
I tried to find the cause but failed... this thing is annoying.. lets look at the code and brainstorm, about: 1) what happening 2) how we can fix it because i am out of ideas.. and having this crap replicating itself in our images is not tolerable. -- Best regards, Igor Stasenko.
+1. No clue either. But discovered the terminate process shortcut to kill them faster... Coping over solving ... 2013/4/12 Igor Stasenko <siguctua@gmail.com>
I tried to find the cause but failed...
this thing is annoying..
lets look at the code and brainstorm, about: 1) what happening 2) how we can fix it
because i am out of ideas.. and having this crap replicating itself in our images is not tolerable.
-- Best regards, Igor Stasenko.
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range.. c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer. For that: i would use non-existing-yet primitive, lets say: <primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''> and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM.. because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs. -- Best regards, Igor Stasenko.
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens? I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important. My wild guess would be the startup initialization of DateAndTime. It takes quite while to do. So the code forks off the initialization in order not to slow down startup. Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again? Norbert
That whole nanos thing in DateAndTime is really weird. I'd love getting millisecs instead (got some trouble with Toothpick logging due to that). 2013/4/12 Norbert Hartl <norbert@hartl.name>
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens? I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do. So the code forks off the initialization in order not to slow down startup. Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again?
Norbert
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;) The offending code starts from here: initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds (notice that 1000 multiplier, which gives us "nanosecond" precision) But that's fine.. now look at secondsWhenClockTicks "waits for the moment when a new second begins" | lastSecond | lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ]. ^ lastSecond + 1 that is complete nonsense. Sorry. This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second.. then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision.. I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision. (But i can be wrong with that.. if so, please explain why)
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens?
Sure. See initializeOffsets secondsWhenClockTicks and all of the users of LastMilliSeconds class var.. btw, did i mentioned, that if we get rid of that code, DateAndTime will no longer need startup? I am just amazed at the shitloads of code which doing this stuff.. and has nothing to do with correct/precise measurement of system date and time. Sorry if it offends you or anyone else. As i said before, my attacks is always against bad code, never against people. I just saying how i feel when i see it.
I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
What is most funny was that TimeStamp simply erases nanoseconds back to ZERO.. But of course it does it in a very peculiar way, that you don't really understand what it is: TimeStamp class>>current | ts ticks | ts := super now. ticks := ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset. ^ ts instead of something like: TimeStamp class>>current ^super now clearNanoseconds That code, btw also offends me a lot , especially "ticks at: 3 put: 0."
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do.
yes, you could call ~ 2^31 milliseconds delay wait time as a "while".. sure , it is still nothing in terms of known universe existence time, which is around 13 bil years :)
So the code forks off the initialization in order not to slow down startup.
hahaha... kind of ;) the "code" in image uses timestamps everywhere (like showing new startup time in transcript)... and god knows where else in system. The point is that every time you say something like "Date now" or "DateAndTime now" it will be blocked until this fork will finish its work.
Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again?
yes.. but still we're not guessing what was before big bang.. i hope :)
Norbert
-- Best regards, Igor Stasenko.
On 13 April 2013 00:16, Igor Stasenko <siguctua@gmail.com> wrote:
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;)
The offending code starts from here:
initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds
(notice that 1000 multiplier, which gives us "nanosecond" precision)
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
yeah.. and if you need millisecond precision so badly, with same success i could do just: MilliSecondOffset := secondsSinceMidnight * 1000 -/+ (1000 atRandom). .. you know.. much less to code, after all :)
(But i can be wrong with that.. if so, please explain why)
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens?
Sure. See initializeOffsets secondsWhenClockTicks and all of the users of LastMilliSeconds class var..
btw, did i mentioned, that if we get rid of that code, DateAndTime will no longer need startup? I am just amazed at the shitloads of code which doing this stuff.. and has nothing to do with correct/precise measurement of system date and time.
Sorry if it offends you or anyone else. As i said before, my attacks is always against bad code, never against people. I just saying how i feel when i see it.
I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
What is most funny was that TimeStamp simply erases nanoseconds back to ZERO.. But of course it does it in a very peculiar way, that you don't really understand what it is:
TimeStamp class>>current
| ts ticks | ts := super now.
ticks := ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset.
^ ts
instead of something like:
TimeStamp class>>current
^super now clearNanoseconds
That code, btw also offends me a lot , especially "ticks at: 3 put: 0."
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do.
yes, you could call ~ 2^31 milliseconds delay wait time as a "while".. sure , it is still nothing in terms of known universe existence time, which is around 13 bil years :)
So the code forks off the initialization in order not to slow down startup.
hahaha... kind of ;)
the "code" in image uses timestamps everywhere (like showing new startup time in transcript)... and god knows where else in system. The point is that every time you say something like "Date now" or "DateAndTime now" it will be blocked until this fork will finish its work.
Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again?
yes.. but still we're not guessing what was before big bang.. i hope :)
Norbert
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
ROFL... just make sure that in the same second we get increasing millisecs 2013/4/13 Igor Stasenko <siguctua@gmail.com>
On 13 April 2013 00:16, Igor Stasenko <siguctua@gmail.com> wrote:
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to
kill
them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;)
The offending code starts from here:
initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds
(notice that 1000 multiplier, which gives us "nanosecond" precision)
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
yeah.. and if you need millisecond precision so badly, with same success i could do just:
MilliSecondOffset := secondsSinceMidnight * 1000 -/+ (1000 atRandom).
.. you know.. much less to code, after all :)
(But i can be wrong with that.. if so, please explain why)
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens?
Sure. See initializeOffsets secondsWhenClockTicks and all of the users of LastMilliSeconds class var..
btw, did i mentioned, that if we get rid of that code, DateAndTime will no longer need startup? I am just amazed at the shitloads of code which doing this stuff.. and has nothing to do with correct/precise measurement of system date and time.
Sorry if it offends you or anyone else. As i said before, my attacks is always against bad code, never against people. I just saying how i feel when i see it.
I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
What is most funny was that TimeStamp simply erases nanoseconds back to ZERO.. But of course it does it in a very peculiar way, that you don't really understand what it is:
TimeStamp class>>current
| ts ticks | ts := super now.
ticks := ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset.
^ ts
instead of something like:
TimeStamp class>>current
^super now clearNanoseconds
That code, btw also offends me a lot , especially "ticks at: 3 put: 0."
My wild guess would be the startup initialization of DateAndTime. It
takes quite while to do.
yes, you could call ~ 2^31 milliseconds delay wait time as a "while".. sure , it is still nothing in terms of known universe existence time, which is around 13 bil years :)
So the code forks off the initialization in order not to slow down startup.
hahaha... kind of ;)
the "code" in image uses timestamps everywhere (like showing new startup time in transcript)... and god knows where else in system. The point is that every time you say something like "Date now" or "DateAndTime now" it will be blocked until this fork will finish its work.
Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again?
yes.. but still we're not guessing what was before big bang.. i hope :)
Norbert
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Just another wild guess: somewhere we introduced a code which uses 'DateAndTime now' before Delay startup code is run. that means that it will put a very wrong Delay object into schedule with random delay time. -- Best regards, Igor Stasenko.
Igor, On 13 Apr 2013, at 00:41, Igor Stasenko <siguctua@gmail.com> wrote:
Just another wild guess: somewhere we introduced a code which uses 'DateAndTime now' before Delay startup code is run.
Yes, my feeling is also that there is Delay has something to do with it.
that means that it will put a very wrong Delay object into schedule with random delay time.
-- Best regards, Igor Stasenko.
In response to all your other mails in this thread: let's please simplify all this and make it understandable. Sven -- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
No offense taken. It is not my code. I'm just guilty by resolving a ticket and integrating it. So maybe I should have taken more time looking at it. Norbert Am 13.04.2013 um 00:16 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range.. Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;)
The offending code starts from here:
initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds
(notice that 1000 multiplier, which gives us "nanosecond" precision)
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens?
Sure. See initializeOffsets secondsWhenClockTicks and all of the users of LastMilliSeconds class var..
btw, did i mentioned, that if we get rid of that code, DateAndTime will no longer need startup? I am just amazed at the shitloads of code which doing this stuff.. and has nothing to do with correct/precise measurement of system date and time.
Sorry if it offends you or anyone else. As i said before, my attacks is always against bad code, never against people. I just saying how i feel when i see it.
I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
What is most funny was that TimeStamp simply erases nanoseconds back to ZERO.. But of course it does it in a very peculiar way, that you don't really understand what it is:
TimeStamp class>>current
| ts ticks | ts := super now.
ticks := ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset.
^ ts
instead of something like:
TimeStamp class>>current
^super now clearNanoseconds
That code, btw also offends me a lot , especially "ticks at: 3 put: 0."
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do.
yes, you could call ~ 2^31 milliseconds delay wait time as a "while".. sure , it is still nothing in terms of known universe existence time, which is around 13 bil years :)
So the code forks off the initialization in order not to slow down startup.
hahaha... kind of ;)
the "code" in image uses timestamps everywhere (like showing new startup time in transcript)... and god knows where else in system. The point is that every time you say something like "Date now" or "DateAndTime now" it will be blocked until this fork will finish its work.
Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again? yes.. but still we're not guessing what was before big bang.. i hope :)
Norbert
-- Best regards, Igor Stasenko.
No problem. We want simple and not overly "smart" code. So we should do another pass on it. Stef
No offense taken. It is not my code. I'm just guilty by resolving a ticket and integrating it. So maybe I should have taken more time looking at it.
Norbert
Am 13.04.2013 um 00:16 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range.. Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;)
The offending code starts from here:
initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds
(notice that 1000 multiplier, which gives us "nanosecond" precision)
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens?
Sure. See initializeOffsets secondsWhenClockTicks and all of the users of LastMilliSeconds class var..
btw, did i mentioned, that if we get rid of that code, DateAndTime will no longer need startup? I am just amazed at the shitloads of code which doing this stuff.. and has nothing to do with correct/precise measurement of system date and time.
Sorry if it offends you or anyone else. As i said before, my attacks is always against bad code, never against people. I just saying how i feel when i see it.
I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
What is most funny was that TimeStamp simply erases nanoseconds back to ZERO.. But of course it does it in a very peculiar way, that you don't really understand what it is:
TimeStamp class>>current
| ts ticks | ts := super now.
ticks := ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset.
^ ts
instead of something like:
TimeStamp class>>current
^super now clearNanoseconds
That code, btw also offends me a lot , especially "ticks at: 3 put: 0."
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do.
yes, you could call ~ 2^31 milliseconds delay wait time as a "while".. sure , it is still nothing in terms of known universe existence time, which is around 13 bil years :)
So the code forks off the initialization in order not to slow down startup.
hahaha... kind of ;)
the "code" in image uses timestamps everywhere (like showing new startup time in transcript)... and god knows where else in system. The point is that every time you say something like "Date now" or "DateAndTime now" it will be blocked until this fork will finish its work.
Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again? yes.. but still we're not guessing what was before big bang.. i hope :)
Norbert
-- Best regards, Igor Stasenko.
Igor since we are investing in the fact that we can build better systems now and for the future, I would be rewriting all this ugly code. Stef On Apr 13, 2013, at 12:16 AM, Igor Stasenko <siguctua@gmail.com> wrote:
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;)
The offending code starts from here:
initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds
(notice that 1000 multiplier, which gives us "nanosecond" precision)
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens?
Sure. See initializeOffsets secondsWhenClockTicks and all of the users of LastMilliSeconds class var..
btw, did i mentioned, that if we get rid of that code, DateAndTime will no longer need startup? I am just amazed at the shitloads of code which doing this stuff.. and has nothing to do with correct/precise measurement of system date and time.
Sorry if it offends you or anyone else. As i said before, my attacks is always against bad code, never against people. I just saying how i feel when i see it.
I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
What is most funny was that TimeStamp simply erases nanoseconds back to ZERO.. But of course it does it in a very peculiar way, that you don't really understand what it is:
TimeStamp class>>current
| ts ticks | ts := super now.
ticks := ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset.
^ ts
instead of something like:
TimeStamp class>>current
^super now clearNanoseconds
That code, btw also offends me a lot , especially "ticks at: 3 put: 0."
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do.
yes, you could call ~ 2^31 milliseconds delay wait time as a "while".. sure , it is still nothing in terms of known universe existence time, which is around 13 bil years :)
So the code forks off the initialization in order not to slow down startup.
hahaha... kind of ;)
the "code" in image uses timestamps everywhere (like showing new startup time in transcript)... and god knows where else in system. The point is that every time you say something like "Date now" or "DateAndTime now" it will be blocked until this fork will finish its work.
Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again?
yes.. but still we're not guessing what was before big bang.. i hope :)
Norbert
-- Best regards, Igor Stasenko.
On Sat, 13 Apr 2013, Igor Stasenko wrote:
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;)
The offending code starts from here:
initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds
(notice that 1000 multiplier, which gives us "nanosecond" precision)
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
(1 to: 10) collect: [ :e | Time secondsWhenClockTicks. [ Time secondsWhenClockTicks ] timeToRun ]. "==> #(1000 1000 1000 1000 1000 1000 1000 1000 1000 1000)" It seems like the resolution is 1 seconds, but the accuracy is 1 millisecond or smaller. Which means that the code will give you a millisecond resolution timestamp. About DateAndTime: having it nanosecond resolution is a future proof idea. It will take a while till software can create better accuracy timestamps. Reducing the resolution to milliseconds is a very bad idea. The VM and external software can give you a microsecond or smaller resolution timestamp which you want to represent as DateAndTime (or whatever class you use to create a timestamp) in the image. Levente
c) i see it completely stupid to try to do magic tricks trying to be smart and squeeze more precision than underlying system can offer.
For that: i would use non-existing-yet primitive, lets say:
<primitive: 'NanoSecondSystemTimeFrom1Jan1900' module: ''>
and since this primitive fails, because it don't exists, the fallback will use old primitive which currently in VM..
because (repeating again) doing black magick and trickery in image buys us nothing and only serves as a source of bugs.
Can you explain where the black magic happens?
Sure. See initializeOffsets secondsWhenClockTicks and all of the users of LastMilliSeconds class var..
btw, did i mentioned, that if we get rid of that code, DateAndTime will no longer need startup? I am just amazed at the shitloads of code which doing this stuff.. and has nothing to do with correct/precise measurement of system date and time.
Sorry if it offends you or anyone else. As i said before, my attacks is always against bad code, never against people. I just saying how i feel when i see it.
I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
What is most funny was that TimeStamp simply erases nanoseconds back to ZERO.. But of course it does it in a very peculiar way, that you don't really understand what it is:
TimeStamp class>>current
| ts ticks | ts := super now.
ticks := ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset.
^ ts
instead of something like:
TimeStamp class>>current
^super now clearNanoseconds
That code, btw also offends me a lot , especially "ticks at: 3 put: 0."
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do.
yes, you could call ~ 2^31 milliseconds delay wait time as a "while".. sure , it is still nothing in terms of known universe existence time, which is around 13 bil years :)
So the code forks off the initialization in order not to slow down startup.
hahaha... kind of ;)
the "code" in image uses timestamps everywhere (like showing new startup time in transcript)... and god knows where else in system. The point is that every time you say something like "Date now" or "DateAndTime now" it will be blocked until this fork will finish its work.
Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again?
yes.. but still we're not guessing what was before big bang.. i hope :)
Norbert
-- Best regards, Igor Stasenko.
On 13 April 2013 09:13, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 13 Apr 2013, Igor Stasenko wrote:
On 12 April 2013 23:47, Norbert Hartl <norbert@hartl.name> wrote:
Am 12.04.2013 um 23:23 schrieb Igor Stasenko <siguctua@gmail.com>:
On 12 April 2013 23:14, phil@highoctane.be <phil@highoctane.be> wrote:
+1. No clue either. But discovered the terminate process shortcut to kill them faster...
Coping over solving ...
One of the "solutions" i proposed is to rewrite the code and get rid of "nano-second" """"synchronization""" of date and time with system clock because a) there is no real users of it (to my knowledge) b) you cannot have precision higher than precision of system primitive we're using, which is in millisecond range..
Where do you see a nanosecond synchronization? It is still millisecond clock as far as I can see. Only the instVar is called nanos.
Ah, sorry.. i mistaken by some orders of magnitude. ;)
The offending code starts from here:
initializeOffsets | durationSinceEpoch secondsSinceMidnight nowSecs | LastTick := 0. nowSecs := self clock secondsWhenClockTicks. LastMilliSeconds := self millisecondClockValue. durationSinceEpoch := Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: nowSecs. DaysSinceEpoch := durationSinceEpoch days. secondsSinceMidnight := (durationSinceEpoch - (Duration days: DaysSinceEpoch hours: 0 minutes: 0 seconds: 0)) asSeconds. MilliSecondOffset := secondsSinceMidnight * 1000 - LastMilliSeconds
(notice that 1000 multiplier, which gives us "nanosecond" precision)
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
(1 to: 10) collect: [ :e | Time secondsWhenClockTicks. [ Time secondsWhenClockTicks ] timeToRun ]. "==> #(1000 1000 1000 1000 1000 1000 1000 1000 1000 1000)"
It seems like the resolution is 1 seconds, but the accuracy is 1 millisecond or smaller. Which means that the code will give you a millisecond resolution timestamp.
Both #timeToRun and secondsWhenClockTicks (via Delay) using same primitive - #millisecondClockValue. Sure thing, precision of this primitive should be it is 1 millisecond or smaller.. But it has nothing to do with precision of primSecondsClock and you cannot increase precision of it using #millisecondClockValue. Because this code: [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ]. actually means: [ lastSecond = self primSecondsClock ] whileTrue: [ block not less than 1 ms ]. but not: [ lastSecond = self primSecondsClock ] whileTrue: [ block exactly 1 ms ]. the upper bound of "(Delay forMilliseconds: 1) wait" is undefined.. and you know it well.
About DateAndTime: having it nanosecond resolution is a future proof idea. It will take a while till software can create better accuracy timestamps. Reducing the resolution to milliseconds is a very bad idea. The VM and external software can give you a microsecond or smaller resolution timestamp which you want to represent as DateAndTime (or whatever class you use to create a timestamp) in the image.
Yes i know. My problem is the amount of code which does something "userful" with nanoseconds while everybody knows that we have no such resolution.. and won't have in 10 years or so.
Levente
-- Best regards, Igor Stasenko.
Levente, i slightly modified your example to simulate interrupt between two primitive invocations: | sema quit result secondsWhenTick | sema := Semaphore new. quit := false. [ [ quit ] whileFalse: [ sema wait. (Delay forSeconds: 2) wait. sema signal ]. ] forkAt: Processor activePriority - 1. secondsWhenTick := [ | lastSecond | lastSecond := Time primSecondsClock. [ lastSecond = Time primSecondsClock ] whileTrue: [ sema signal. sema wait. (Delay forMilliseconds: 1) wait ]]. result := (1 to: 10) collect: [:i | secondsWhenTick value. [ secondsWhenTick value ] timeToRun ]. quit := true. result #(2002 2002 2004 2003 2004 2004 2003 2003 2004 2004) You know that interrupt can happen at any moment. Even if it is not VM, it can be hardware interrupt, OS interrupt and god knows what else. Like that we can only state: well, there is some >0 probability that error of measurement using #secondsWhenTick will be within ~1 msec interval.. but it is never == 1. Which at the end means that expression: DateAndTime now nanoSecond and: 1000000000 atRandom can be used more or less interchangeably, because both has nothing to do with measurement of current system time. -- Best regards, Igor Stasenko.
On Sat, 13 Apr 2013, Igor Stasenko wrote:
Both #timeToRun and secondsWhenClockTicks (via Delay) using same primitive - #millisecondClockValue. Sure thing, precision of this primitive should be it is 1 millisecond or smaller.. But it has nothing to do with precision of primSecondsClock and you cannot increase precision of it using #millisecondClockValue.
The only thing I wanted to point out is that the value of #primSecondsClock changes when the actual second changes (the difference is less than 1ms). So while its resolution is just 1 second, it's accuracy is better than 1ms. Here's another example using the microsecond clock: (1 to: 10) collect: [ :e | | start | Time secondsWhenClockTicks. start := Time primUTCMicrosecondClock. Time secondsWhenClockTicks. Time primUTCMicrosecondClock - start ]. "==> #(1000136 999914 999961 999926 1000029 999988 999991 999985 998089 1000034)"
Because this code:
[ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
actually means:
[ lastSecond = self primSecondsClock ] whileTrue: [ block not less than 1 ms ].
but not:
[ lastSecond = self primSecondsClock ] whileTrue: [ block exactly 1 ms ].
the upper bound of "(Delay forMilliseconds: 1) wait" is undefined.. and you know it well.
Of course Delays are not ideal here, but there was nothing better to use when the code was written. As you can see in the above example, in 1 out of 10 cases the difference was less than 999 ms. Levente
About DateAndTime: having it nanosecond resolution is a future proof idea. It will take a while till software can create better accuracy timestamps. Reducing the resolution to milliseconds is a very bad idea. The VM and external software can give you a microsecond or smaller resolution timestamp which you want to represent as DateAndTime (or whatever class you use to create a timestamp) in the image.
Yes i know. My problem is the amount of code which does something "userful" with nanoseconds while everybody knows that we have no such resolution.. and won't have in 10 years or so.
Levente
-- Best regards, Igor Stasenko.
On 13 April 2013 21:36, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 13 Apr 2013, Igor Stasenko wrote:
Both #timeToRun and secondsWhenClockTicks (via Delay) using same primitive - #millisecondClockValue. Sure thing, precision of this primitive should be it is 1 millisecond or smaller.. But it has nothing to do with precision of primSecondsClock and you cannot increase precision of it using #millisecondClockValue.
The only thing I wanted to point out is that the value of #primSecondsClock changes when the actual second changes (the difference is less than 1ms). So while its resolution is just 1 second, it's accuracy is better than 1ms. Here's another example using the microsecond clock:
(1 to: 10) collect: [ :e | | start | Time secondsWhenClockTicks. start := Time primUTCMicrosecondClock. Time secondsWhenClockTicks. Time primUTCMicrosecondClock - start ]. "==> #(1000136 999914 999961 999926 1000029 999988 999991 999985 998089 1000034)"
My gut feeling that here you are rather measuring accuracy of 1ms Delay operation (in secondsWhenClockTicks method). by sampling it using system time function. Because for both primitives (primUTCMicrosecondClock and primSecondsClock) the source is system time. But Delay, inside also uses system time at some point... so, here we're trying to reason about how to measure accuracy of some function (which stays behind all of these) by using very same function.. I am not genius in rules of correct measurement, but doesn't it sounds silly to you?
Because this code:
[ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
actually means:
[ lastSecond = self primSecondsClock ] whileTrue: [ block not less than 1 ms ].
but not:
[ lastSecond = self primSecondsClock ] whileTrue: [ block exactly 1 ms ].
the upper bound of "(Delay forMilliseconds: 1) wait" is undefined.. and you know it well.
Of course Delays are not ideal here, but there was nothing better to use when the code was written. As you can see in the above example, in 1 out of 10 cases the difference was less than 999 ms.
Levente
About DateAndTime: having it nanosecond resolution is a future proof idea. It will take a while till software can create better accuracy timestamps. Reducing the resolution to milliseconds is a very bad idea. The VM and external software can give you a microsecond or smaller resolution timestamp which you want to represent as DateAndTime (or whatever class you use to create a timestamp) in the image.
Yes i know. My problem is the amount of code which does something "userful" with nanoseconds while everybody knows that we have no such resolution.. and won't have in 10 years or so.
Levente
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
Hi igor and levente I want to thank you because I love this thread. Why because it makes me think and I learn things :) I will reread it several time and browse the system... to learn again Thanks
Both #timeToRun and secondsWhenClockTicks (via Delay) using same primitive - #millisecondClockValue. Sure thing, precision of this primitive should be it is 1 millisecond or smaller.. But it has nothing to do with precision of primSecondsClock and you cannot increase precision of it using #millisecondClockValue.
The only thing I wanted to point out is that the value of #primSecondsClock changes when the actual second changes (the difference is less than 1ms). So while its resolution is just 1 second, it's accuracy is better than 1ms. Here's another example using the microsecond clock:
(1 to: 10) collect: [ :e | | start | Time secondsWhenClockTicks. start := Time primUTCMicrosecondClock. Time secondsWhenClockTicks. Time primUTCMicrosecondClock - start ]. "==> #(1000136 999914 999961 999926 1000029 999988 999991 999985 998089 1000034)"
My gut feeling that here you are rather measuring accuracy of 1ms Delay operation (in secondsWhenClockTicks method). by sampling it using system time function. Because for both primitives (primUTCMicrosecondClock and primSecondsClock) the source is system time. But Delay, inside also uses system time at some point...
so, here we're trying to reason about how to measure accuracy of some function (which stays behind all of these) by using very same function..
I am not genius in rules of correct measurement, but doesn't it sounds silly to you?
Because this code:
[ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
actually means:
[ lastSecond = self primSecondsClock ] whileTrue: [ block not less than 1 ms ].
but not:
[ lastSecond = self primSecondsClock ] whileTrue: [ block exactly 1 ms ].
the upper bound of "(Delay forMilliseconds: 1) wait" is undefined.. and you know it well.
Of course Delays are not ideal here, but there was nothing better to use when the code was written. As you can see in the above example, in 1 out of 10 cases the difference was less than 999 ms.
Levente
About DateAndTime: having it nanosecond resolution is a future proof idea. It will take a while till software can create better accuracy timestamps. Reducing the resolution to milliseconds is a very bad idea. The VM and external software can give you a microsecond or smaller resolution timestamp which you want to represent as DateAndTime (or whatever class you use to create a timestamp) in the image.
Yes i know. My problem is the amount of code which does something "userful" with nanoseconds while everybody knows that we have no such resolution.. and won't have in 10 years or so.
Levente
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
On Sat, 13 Apr 2013, Igor Stasenko wrote:
On 13 April 2013 21:36, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 13 Apr 2013, Igor Stasenko wrote:
Both #timeToRun and secondsWhenClockTicks (via Delay) using same primitive - #millisecondClockValue. Sure thing, precision of this primitive should be it is 1 millisecond or smaller.. But it has nothing to do with precision of primSecondsClock and you cannot increase precision of it using #millisecondClockValue.
The only thing I wanted to point out is that the value of #primSecondsClock changes when the actual second changes (the difference is less than 1ms). So while its resolution is just 1 second, it's accuracy is better than 1ms. Here's another example using the microsecond clock:
(1 to: 10) collect: [ :e | | start | Time secondsWhenClockTicks. start := Time primUTCMicrosecondClock. Time secondsWhenClockTicks. Time primUTCMicrosecondClock - start ]. "==> #(1000136 999914 999961 999926 1000029 999988 999991 999985 998089 1000034)"
My gut feeling that here you are rather measuring accuracy of 1ms Delay operation (in secondsWhenClockTicks method).
No. I just wanted to show that this method works in practice (yeah, it's there for years and actually noone had any problems with it). And even though there's a slight chance for it to drift away by a few milliseconds, your statement - using a random number for the millisecond part is not worse than using this method - is not true. Levente
by sampling it using system time function. Because for both primitives (primUTCMicrosecondClock and primSecondsClock) the source is system time. But Delay, inside also uses system time at some point...
so, here we're trying to reason about how to measure accuracy of some function (which stays behind all of these) by using very same function..
I am not genius in rules of correct measurement, but doesn't it sounds silly to you?
Because this code:
[ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
actually means:
[ lastSecond = self primSecondsClock ] whileTrue: [ block not less than 1 ms ].
but not:
[ lastSecond = self primSecondsClock ] whileTrue: [ block exactly 1 ms ].
the upper bound of "(Delay forMilliseconds: 1) wait" is undefined.. and you know it well.
Of course Delays are not ideal here, but there was nothing better to use when the code was written. As you can see in the above example, in 1 out of 10 cases the difference was less than 999 ms.
Levente
About DateAndTime: having it nanosecond resolution is a future proof idea. It will take a while till software can create better accuracy timestamps. Reducing the resolution to milliseconds is a very bad idea. The VM and external software can give you a microsecond or smaller resolution timestamp which you want to represent as DateAndTime (or whatever class you use to create a timestamp) in the image.
Yes i know. My problem is the amount of code which does something "userful" with nanoseconds while everybody knows that we have no such resolution.. and won't have in 10 years or so.
Levente
-- Best regards, Igor Stasenko.
-- Best regards, Igor Stasenko.
On 14 April 2013 12:50, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 13 Apr 2013, Igor Stasenko wrote:
On 13 April 2013 21:36, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 13 Apr 2013, Igor Stasenko wrote:
Both #timeToRun and secondsWhenClockTicks (via Delay) using same primitive - #millisecondClockValue. Sure thing, precision of this primitive should be it is 1 millisecond or smaller.. But it has nothing to do with precision of primSecondsClock and you cannot increase precision of it using #millisecondClockValue.
The only thing I wanted to point out is that the value of #primSecondsClock changes when the actual second changes (the difference is less than 1ms). So while its resolution is just 1 second, it's accuracy is better than 1ms. Here's another example using the microsecond clock:
(1 to: 10) collect: [ :e | | start | Time secondsWhenClockTicks. start := Time primUTCMicrosecondClock. Time secondsWhenClockTicks. Time primUTCMicrosecondClock - start ]. "==> #(1000136 999914 999961 999926 1000029 999988 999991 999985 998089 1000034)"
My gut feeling that here you are rather measuring accuracy of 1ms Delay operation (in secondsWhenClockTicks method).
No. I just wanted to show that this method works in practice (yeah, it's there for years and actually noone had any problems with it). And even though there's a slight chance for it to drift away by a few milliseconds, your statement - using a random number for the millisecond part is not worse than using this method - is not true.
Maybe you are right. But i do not see a compelling reason having DateAndTime soo precise. It makes not sense. And TimeStamp's resetting nanosecs field (in very peculiar way) by rounding it to 1sec heavily backing up my argument. If you need precision/accuracy higher than 1 sec, you should use milli/micro second clock counter. The mess in DateAndTime is imo a big piece of overengineering.
Levente
-- Best regards, Igor Stasenko.
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked! So no, that method is not complete nonsense. Cheers, Henry
On 15 April 2013 12:14, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Cheers, Henry
-- Best regards, Igor Stasenko.
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes. However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.' Which in my case translated to that in a Time2 class with #now defined: now | microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000 and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap): seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight." ^ self basicNew seconds: seconds nanoSeconds: nanoCount To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.' Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now. Cheers, Henry
On 15 April 2013 16:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes.
However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.'
Which in my case translated to that in a Time2 class with #now defined: now
| microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000
and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap):
seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight."
^ self basicNew seconds: seconds nanoSeconds: nanoCount
To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.'
Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now.
Well, i am not started modifying Time now, (will start in couple minutes ;) but here results of DateAndTime now before and after: before: [ DateAndTime now ] bench '316,000 per second.' after: [ DateAndTime now ] bench '414,000 per second.' with Time now, i think even if it will be "2,300,000" answers per second, it is fairly acceptable , when accuracy of primitive is 1 microsecond, you actually don't need more than 1 million answers per second, or you will receive same answers. But aside of it, may i ask, why performance is so important/critical for those? What is use case?
Cheers, Henry
-- Best regards, Igor Stasenko.
On 15 April 2013 16:43, Igor Stasenko <siguctua@gmail.com> wrote:
On 15 April 2013 16:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes.
However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.'
Which in my case translated to that in a Time2 class with #now defined: now
| microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000
and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap):
seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight."
^ self basicNew seconds: seconds nanoSeconds: nanoCount
To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.'
Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now.
Well, i am not started modifying Time now, (will start in couple minutes ;) but here results of DateAndTime now before and after:
before:
[ DateAndTime now ] bench '316,000 per second.'
after:
[ DateAndTime now ] bench '414,000 per second.'
with Time now, i think even if it will be "2,300,000" answers per second, it is fairly acceptable , when accuracy of primitive is 1 microsecond, you actually don't need more than 1 million answers per second, or you will receive same answers.
But aside of it, may i ask, why performance is so important/critical for those? What is use case?
everything is good in comparison: [ self yourself ] bench '58,800,000 per second.' does nothing and just 25 times faster.. than Time now, so what is the point? :) -- Best regards, Igor Stasenko.
On Apr 15, 2013, at 4:50 PM, Igor Stasenko wrote:
On 15 April 2013 16:43, Igor Stasenko <siguctua@gmail.com> wrote:
On 15 April 2013 16:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes.
However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.'
Which in my case translated to that in a Time2 class with #now defined: now
| microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000
and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap):
seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight."
^ self basicNew seconds: seconds nanoSeconds: nanoCount
To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.'
Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now.
Well, i am not started modifying Time now, (will start in couple minutes ;) but here results of DateAndTime now before and after:
before:
[ DateAndTime now ] bench '316,000 per second.'
after:
[ DateAndTime now ] bench '414,000 per second.'
with Time now, i think even if it will be "2,300,000" answers per second, it is fairly acceptable , when accuracy of primitive is 1 microsecond, you actually don't need more than 1 million answers per second, or you will receive same answers.
But aside of it, may i ask, why performance is so important/critical for those? What is use case?
everything is good in comparison:
[ self yourself ] bench '58,800,000 per second.'
does nothing and just 25 times faster.. than Time now, so what is the point? :)
The point was raising awareness that performance differences are also worthy of measuring when doing a reimplementation, not just code cleanliness. A 3x decrease in performance is worth at least consideration as part of a reimplementation, even when the conclusion is "it's plenty fast enough for most uses anyways". Not to mention, "Made X Y% faster" looks better in the release notes than "Restructured the internals of X" :) Cheers, Henry
On 16 April 2013 11:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 4:50 PM, Igor Stasenko wrote:
On 15 April 2013 16:43, Igor Stasenko <siguctua@gmail.com> wrote:
On 15 April 2013 16:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes.
However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.'
Which in my case translated to that in a Time2 class with #now defined: now
| microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000
and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap):
seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight."
^ self basicNew seconds: seconds nanoSeconds: nanoCount
To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.'
Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now.
Well, i am not started modifying Time now, (will start in couple minutes ;) but here results of DateAndTime now before and after:
before:
[ DateAndTime now ] bench '316,000 per second.'
after:
[ DateAndTime now ] bench '414,000 per second.'
with Time now, i think even if it will be "2,300,000" answers per second, it is fairly acceptable , when accuracy of primitive is 1 microsecond, you actually don't need more than 1 million answers per second, or you will receive same answers.
But aside of it, may i ask, why performance is so important/critical for those? What is use case?
everything is good in comparison:
[ self yourself ] bench '58,800,000 per second.'
does nothing and just 25 times faster.. than Time now, so what is the point? :)
The point was raising awareness that performance differences are also worthy of measuring when doing a reimplementation, not just code cleanliness. A 3x decrease in performance is worth at least consideration as part of a reimplementation, even when the conclusion is "it's plenty fast enough for most uses anyways".
Not to mention, "Made X Y% faster" looks better in the release notes than "Restructured the internals of X" :)
RIght. So, it is 3x slower , 1000x more accurate (milli vs micro), do not requires startup code do not need to account for counter wrapping and day change => much cleaner and nicer. + less buggy. As to me , the choice is obvious.
Cheers, Henry
-- Best regards, Igor Stasenko.
On 16/04/13 5:56 AM, Igor Stasenko wrote:
So, it is 3x slower , 1000x more accurate (milli vs micro), do not requires startup code do not need to account for counter wrapping and day change => much cleaner and nicer. + less buggy.
Is this a candidate for back porting to Pharo-2.0? (Eliminating the startup code is the main concern, I think).
On 16 April 2013 17:51, Yanni Chiu <yanni@rogers.com> wrote:
On 16/04/13 5:56 AM, Igor Stasenko wrote:
So, it is 3x slower , 1000x more accurate (milli vs micro), do not requires startup code do not need to account for counter wrapping and day change => much cleaner and nicer. + less buggy.
Is this a candidate for back porting to Pharo-2.0? (Eliminating the startup code is the main concern, I think).
Most probably yes. But we will see -- Best regards, Igor Stasenko.
On Tue, Apr 16, 2013 at 2:56 AM, Igor Stasenko <siguctua@gmail.com> wrote:
On 16 April 2013 11:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 4:50 PM, Igor Stasenko wrote:
On 15 April 2013 16:43, Igor Stasenko <siguctua@gmail.com> wrote:
On 15 April 2013 16:32, Henrik Johansen <henrik.s.johansen@veloxit.no>
wrote:
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <
henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is.....
(drum
roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes.
However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.'
Which in my case translated to that in a Time2 class with #now defined: now
| microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000
and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap):
seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight."
^ self basicNew seconds: seconds nanoSeconds: nanoCount
To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.'
Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now.
Well, i am not started modifying Time now, (will start in couple minutes ;) but here results of DateAndTime now before and after:
before:
[ DateAndTime now ] bench '316,000 per second.'
after:
[ DateAndTime now ] bench '414,000 per second.'
with Time now, i think even if it will be "2,300,000" answers per second, it is fairly acceptable , when accuracy of primitive is 1 microsecond, you actually don't need more than 1 million answers per second, or you will receive same answers.
But aside of it, may i ask, why performance is so important/critical for those? What is use case?
everything is good in comparison:
[ self yourself ] bench '58,800,000 per second.'
does nothing and just 25 times faster.. than Time now, so what is the point? :)
The point was raising awareness that performance differences are also worthy of measuring when doing a reimplementation, not just code cleanliness. A 3x decrease in performance is worth at least consideration as part of a reimplementation, even when the conclusion is "it's plenty fast enough for most uses anyways".
Not to mention, "Made X Y% faster" looks better in the release notes than "Restructured the internals of X" :)
RIght. So, it is 3x slower , 1000x more accurate (milli vs micro), do not requires startup code do not need to account for counter wrapping and day change => much cleaner and nicer. + less buggy. As to me , the choice is obvious.
and when we implement a proper 64-bit system with e.g. 61-bit SmallIntegers it will no longer be 3 times slower :)
Cheers, Henry
-- Best regards, Igor Stasenko.
-- best, Eliot
On Apr 16, 2013, at 7:50 PM, Eliot Miranda wrote:
On Tue, Apr 16, 2013 at 2:56 AM, Igor Stasenko <siguctua@gmail.com> wrote: On 16 April 2013 11:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 4:50 PM, Igor Stasenko wrote:
On 15 April 2013 16:43, Igor Stasenko <siguctua@gmail.com> wrote:
On 15 April 2013 16:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is..... (drum roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes.
However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.'
Which in my case translated to that in a Time2 class with #now defined: now
| microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000
and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap):
seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight."
^ self basicNew seconds: seconds nanoSeconds: nanoCount
To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.'
Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now.
Well, i am not started modifying Time now, (will start in couple minutes ;) but here results of DateAndTime now before and after:
before:
[ DateAndTime now ] bench '316,000 per second.'
after:
[ DateAndTime now ] bench '414,000 per second.'
with Time now, i think even if it will be "2,300,000" answers per second, it is fairly acceptable , when accuracy of primitive is 1 microsecond, you actually don't need more than 1 million answers per second, or you will receive same answers.
But aside of it, may i ask, why performance is so important/critical for those? What is use case?
everything is good in comparison:
[ self yourself ] bench '58,800,000 per second.'
does nothing and just 25 times faster.. than Time now, so what is the point? :)
The point was raising awareness that performance differences are also worthy of measuring when doing a reimplementation, not just code cleanliness. A 3x decrease in performance is worth at least consideration as part of a reimplementation, even when the conclusion is "it's plenty fast enough for most uses anyways".
Not to mention, "Made X Y% faster" looks better in the release notes than "Restructured the internals of X" :)
RIght. So, it is 3x slower , 1000x more accurate (milli vs micro), do not requires startup code do not need to account for counter wrapping and day change => much cleaner and nicer. + less buggy. As to me , the choice is obvious.
and when we implement a proper 64-bit system with e.g. 61-bit SmallIntegers it will no longer be 3 times slower :)
Sorry for the derail, but why not 62? ;) http://forum.world.st/Fwd-Plan-discussion-communication-around-new-object-fo... Cheers, Henry
On Wed, Apr 17, 2013 at 2:31 AM, Henrik Johansen < henrik.s.johansen@veloxit.no> wrote:
On Apr 16, 2013, at 7:50 PM, Eliot Miranda wrote:
On Tue, Apr 16, 2013 at 2:56 AM, Igor Stasenko <siguctua@gmail.com> wrote:
On 16 April 2013 11:32, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Apr 15, 2013, at 4:50 PM, Igor Stasenko wrote:
On 15 April 2013 16:43, Igor Stasenko <siguctua@gmail.com> wrote:
On 15 April 2013 16:32, Henrik Johansen <henrik.s.johansen@veloxit.no>
wrote:
On Apr 15, 2013, at 3:25 PM, Igor Stasenko wrote:
On 15 April 2013 12:14, Henrik Johansen <
henrik.s.johansen@veloxit.no> wrote:
On Apr 13, 2013, at 12:16 AM, Igor Stasenko wrote:
But that's fine.. now look at
secondsWhenClockTicks
"waits for the moment when a new second begins"
| lastSecond |
lastSecond := self primSecondsClock. [ lastSecond = self primSecondsClock ] whileTrue: [ (Delay forMilliseconds: 1) wait ].
^ lastSecond + 1
that is complete nonsense. Sorry.
This code relying on primSecondsClock resolution, which is.....
(drum
roll..... ) 1 second..
then it is combined with millisecondClockValue , as you see later to get system time with millisecond precision..
I am not genius in math and physics.. but even i understand that if you measurement has error X you cannot get more precision than X, even if you combine it with another measurement with higher precision.
(But i can be wrong with that.. if so, please explain why)
Because, as Levente said in code, resolution != accuracy. When you measure a single sample, sure, that value has an error of max resolution / 2. But when you measure when that value _changes_, you have an error of the underlying accuracy / 2. Clock s value: 1 2 resolution: |_______|_______| accuracy: ||||||||||||||||||||||||||||||||||| ^ Here's to hoping the above ascii art(?) worked!
So no, that method is not complete nonsense.
Okay. Now i rewriting the code which uses new primitive (primUTCMicrosecondClock), and then we will no longer need this startup logic nor wrap around check & other gory details... just use a primitive.
Sounds clearer, yes.
However, be aware, at least on my VM: [Time millisecondClockValue] bench '34,600,000 per second.' [Time primUTCMicrosecondClock] bench '12,400,000 per second.'
Which in my case translated to that in a Time2 class with #now defined: now
| microSecondsToday | microSecondsToday := self primUTCMicrosecondClock \\ 86400000000. ^ self seconds: microSecondsToday // 1000000 nanoSeconds: microSecondsToday * 1000
and changing the relatively low-hanging fruit in standard Time (removing Duration creation and other crap):
seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight."
^ self basicNew seconds: seconds nanoSeconds: nanoCount
To benchmarks that looked like this: "Old code" [Time now ] bench '7,330,000 per second.' '7,280,000 per second.' '7,170,000 per second.' "Using microsecondClock every call" [Time2 now ] bench '2,280,000 per second.''2,300,000 per second.' '2,180,000 per second.'
Also note, Time2 lacked translation to Local time, which would be needed for consistency with Time now.
Well, i am not started modifying Time now, (will start in couple minutes ;) but here results of DateAndTime now before and after:
before:
[ DateAndTime now ] bench '316,000 per second.'
after:
[ DateAndTime now ] bench '414,000 per second.'
with Time now, i think even if it will be "2,300,000" answers per second, it is fairly acceptable , when accuracy of primitive is 1 microsecond, you actually don't need more than 1 million answers per second, or you will receive same answers.
But aside of it, may i ask, why performance is so important/critical for those? What is use case?
everything is good in comparison:
[ self yourself ] bench '58,800,000 per second.'
does nothing and just 25 times faster.. than Time now, so what is the point? :)
The point was raising awareness that performance differences are also worthy of measuring when doing a reimplementation, not just code cleanliness. A 3x decrease in performance is worth at least consideration as part of a reimplementation, even when the conclusion is "it's plenty fast enough for most uses anyways".
Not to mention, "Made X Y% faster" looks better in the release notes than "Restructured the internals of X" :)
RIght. So, it is 3x slower , 1000x more accurate (milli vs micro), do not requires startup code do not need to account for counter wrapping and day change => much cleaner and nicer. + less buggy. As to me , the choice is obvious.
and when we implement a proper 64-bit system with e.g. 61-bit SmallIntegers it will no longer be 3 times slower :)
Sorry for the derail, but why not 62? ;)
http://forum.world.st/Fwd-Plan-discussion-communication-around-new-object-fo...
sure, perhaps (devil's in the details), but >= 60 is 36k years of microseconds :)
Cheers, Henry
-- best, Eliot
Can you explain where the black magic happens? I integrated the cuis changeset back then because I wanted something more fine grained than seconds. Do you think this is already black magic? I think we can make smaller slices today :) That it forces the whole DateAndTime in this precision is probably not necessary and I understand that Sven did his own timestamp. The same goes for timezones. Maybe we need more levels of features in the hierarchy. If the system (or any software) is not dependent on precision below a second it would be good to have such a coarse grained type at hand. But to have the possibility to have at least milliseconds I find important.
My wild guess would be the startup initialization of DateAndTime. It takes quite while to do. So the code forks off the initialization in order not to slow down startup. Without knowing exactly my gut tells me this is not a good idea. It might be that it produces late jumps of time in startup which makes timeouts inactive. Or jumps the check for negative delays and introduces some negative wait which will native wise quit big. Were we at "wild guessing" or "very wild guessing" again?
agreed.
funny, I wanted to look at it in my actual 2.0 working image and I don't have a single occurrence of it. It is a 2.0 image? Norbert Am 12.04.2013 um 23:08 schrieb Igor Stasenko <siguctua@gmail.com>:
I tried to find the cause but failed...
this thing is annoying..
lets look at the code and brainstorm, about: 1) what happening 2) how we can fix it
because i am out of ideas.. and having this crap replicating itself in our images is not tolerable.
-- Best regards, Igor Stasenko. <Screen Shot 2013-04-12 at 11.05.49 PM.png>
On 12 April 2013 23:20, Norbert Hartl <norbert@hartl.name> wrote:
funny, I wanted to look at it in my actual 2.0 working image and I don't have a single occurrence of it. It is a 2.0 image?
3.0 latest.. it looks like it depends on something .. (like the way you look, and what you ate today on breakfast ;)
Norbert
Am 12.04.2013 um 23:08 schrieb Igor Stasenko <siguctua@gmail.com>:
I tried to find the cause but failed...
this thing is annoying..
lets look at the code and brainstorm, about: 1) what happening 2) how we can fix it
because i am out of ideas.. and having this crap replicating itself in our images is not tolerable.
-- Best regards, Igor Stasenko. <Screen Shot 2013-04-12 at 11.05.49 PM.png>
-- Best regards, Igor Stasenko.
Igor I have the impression that this is happening for us because we always download the image from jenkins. Did we experience the same once the processes are cleaned? and we do not get an image from another os/system? Stef On Apr 12, 2013, at 11:25 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 12 April 2013 23:20, Norbert Hartl <norbert@hartl.name> wrote:
funny, I wanted to look at it in my actual 2.0 working image and I don't have a single occurrence of it. It is a 2.0 image?
3.0 latest..
it looks like it depends on something .. (like the way you look, and what you ate today on breakfast ;)
Norbert
Am 12.04.2013 um 23:08 schrieb Igor Stasenko <siguctua@gmail.com>:
I tried to find the cause but failed...
this thing is annoying..
lets look at the code and brainstorm, about: 1) what happening 2) how we can fix it
because i am out of ideas.. and having this crap replicating itself in our images is not tolerable.
-- Best regards, Igor Stasenko. <Screen Shot 2013-04-12 at 11.05.49 PM.png>
-- Best regards, Igor Stasenko.
On Apr 13, 2013, at 7:10 AM, stephane ducasse <stephane.ducasse@free.fr> wrote:
Igor
I have the impression that this is happening for us because we always download the image from jenkins. Did we experience the same once the processes are cleaned? and we do not get an image from another os/system?
Yes, every time the image is saved on Jenkins we get one more. There is some other strange problem with saving images from the CommandLine: some things are deferred until the GUI is available, which is when you open it after downloading from jenkins. As for 2.0: we cleaned it by hand⦠(the release image). Marcus
On 13 April 2013 09:52, Marcus Denker <marcus.denker@inria.fr> wrote:
On Apr 13, 2013, at 7:10 AM, stephane ducasse <stephane.ducasse@free.fr> wrote:
Igor
I have the impression that this is happening for us because we always download the image from jenkins. Did we experience the same once the processes are cleaned? and we do not get an image from another os/system?
Yes, every time the image is saved on Jenkins we get one more.
There is some other strange problem with saving images from the CommandLine: some things are deferred until the GUI is available, which is when you open it after downloading from jenkins.
As for 2.0: we cleaned it by hand⦠(the release image).
yes.. and it still popping new ones. so problem is still there.
Marcus
-- Best regards, Igor Stasenko.
participants (10)
-
Eliot Miranda -
Henrik Johansen -
Igor Stasenko -
Levente Uzonyi -
Marcus Denker -
Norbert Hartl -
phil@highoctane.be -
stephane ducasse -
Sven Van Caekenberghe -
Yanni Chiu