microsecond timing for GC work

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

microsecond timing for GC work

johnmci
 
The attached change set and sq.h enable microsecond timing for GC work.
Please review for consideration for VMMaker.

I've added a named primitive

primitiveMicrosecondClock
        "This is a named (not numbered) primitive in the null module (ie the VM)"
        self export: true.
        self pop: 1 thenPush: (self positive64BitIntegerFor: (self ioMicroSeconds)).


I used the 'sqLong' data type, but we don't seem to have a usqLong type to get unsigned long long  ?
Since in this case I'd like the 64bit value to be positive only value...

Where on OS-X Cocoa VM V5 it is

sqLong ioMicroSeconds(void)
{
        //API Documented
        struct timeval now;
        sqLong theTimeIs;
       
        gettimeofday(&now, 0);
        if ((now.tv_usec-= startUpTime.tv_usec) < 0) {
                now.tv_usec+= 1000000;
                now.tv_sec-= 1;
        }
        now.tv_sec-= startUpTime.tv_sec;
        theTimeIs = now.tv_usec;
        theTimeIs = theTimeIs + now.tv_sec * 1000000;
        return theTimeIs;
}

This follows the pattern for ioMicroMSecs which has it roots in the Unix code, which is:

sqInt ioMSecs(void)
{
  struct timeval now;
  gettimeofday(&now, 0);
  if ((now.tv_usec-= startUpTime.tv_usec) < 0)
    {
      now.tv_usec+= 1000000;
      now.tv_sec-= 1;
    }
  now.tv_sec-= startUpTime.tv_sec;
  return lowResMSecs= (now.tv_usec / 1000 + now.tv_sec * 1000);
}


An interesting thing here btw is that the unix variation uses "startUpTime" which gets set to a clock time at VM startup time, so
the value zero is the start time of VM, versus a time from the squeak epoch time start value.  Also I use theTimeIs to ensure we don't have a 64bit overflow in the math
** Assuming the C compiler actually realizes the math has to be long long  for the now.tv_sec * 1000000  (interesting question perhaps)....  ***


and then I  had to alter

        aCCodeGenerator var: #statGCTime type: #'sqLong'.
        aCCodeGenerator var: #statFullGCMSecs type: #'sqLong'.
        aCCodeGenerator var: #statIGCDeltaTime type: #'sqLong'.
        aCCodeGenerator var: #statIncrGCMSecs type: #'sqLong'.

and
        startTime in fullGC and incrementalGC

so that they are 64bit values.



--
===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================






sq.h (17K) Download Attachment
JMMAddMicroSecondsForGCTiming.1.cs (22K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

David T. Lewis
 
This all looks reasonable to me.

The unix implementation is presumably straightforward. Windows is using
GetTickCount() for ioMSecs(), so very likely it would be sufficient to
use GetTickCount() * 1000 for ioMicroSeconds().

As a sanity check though - I'm not sure that any of the platforms can
actually measure a time resolution to accuracy greater than 1 msec.
You may not be getting any practical benefit from reporting time to a
precision greater than this.

Dave

On Sun, Jan 17, 2010 at 03:57:10PM -0800, John M McIntosh wrote:

>  
> The attached change set and sq.h enable microsecond timing for GC work.
> Please review for consideration for VMMaker.
>
> I've added a named primitive
>
> primitiveMicrosecondClock
> "This is a named (not numbered) primitive in the null module (ie the VM)"
> self export: true.
> self pop: 1 thenPush: (self positive64BitIntegerFor: (self ioMicroSeconds)).
>
>
> I used the 'sqLong' data type, but we don't seem to have a usqLong type to get unsigned long long  ?
> Since in this case I'd like the 64bit value to be positive only value...
>
> Where on OS-X Cocoa VM V5 it is
>
> sqLong ioMicroSeconds(void)
> {
> //API Documented
> struct timeval now;
> sqLong theTimeIs;
>
> gettimeofday(&now, 0);
> if ((now.tv_usec-= startUpTime.tv_usec) < 0) {
> now.tv_usec+= 1000000;
> now.tv_sec-= 1;
> }
> now.tv_sec-= startUpTime.tv_sec;
> theTimeIs = now.tv_usec;
> theTimeIs = theTimeIs + now.tv_sec * 1000000;
> return theTimeIs;
> }
>
> This follows the pattern for ioMicroMSecs which has it roots in the Unix code, which is:
>
> sqInt ioMSecs(void)
> {
>   struct timeval now;
>   gettimeofday(&now, 0);
>   if ((now.tv_usec-= startUpTime.tv_usec) < 0)
>     {
>       now.tv_usec+= 1000000;
>       now.tv_sec-= 1;
>     }
>   now.tv_sec-= startUpTime.tv_sec;
>   return lowResMSecs= (now.tv_usec / 1000 + now.tv_sec * 1000);
> }
>
>
> An interesting thing here btw is that the unix variation uses "startUpTime" which gets set to a clock time at VM startup time, so
> the value zero is the start time of VM, versus a time from the squeak epoch time start value.  Also I use theTimeIs to ensure we don't have a 64bit overflow in the math
> ** Assuming the C compiler actually realizes the math has to be long long  for the now.tv_sec * 1000000  (interesting question perhaps)....  ***
>
>
> and then I  had to alter
>
> aCCodeGenerator var: #statGCTime type: #'sqLong'.
> aCCodeGenerator var: #statFullGCMSecs type: #'sqLong'.
> aCCodeGenerator var: #statIGCDeltaTime type: #'sqLong'.
> aCCodeGenerator var: #statIncrGCMSecs type: #'sqLong'.
>
> and
> startTime in fullGC and incrementalGC
>
> so that they are 64bit values.
>
>
>
> --
> ===========================================================================
> John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
> Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
> ===========================================================================
>



>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

johnmci

The incremental GC delta counter returns values like 181 microseconds on os-x for me.

On 2010-01-18, at 10:02 AM, David T. Lewis wrote:

> This all looks reasonable to me.
>
> The unix implementation is presumably straightforward. Windows is using
> GetTickCount() for ioMSecs(), so very likely it would be sufficient to
> use GetTickCount() * 1000 for ioMicroSeconds().
>
> As a sanity check though - I'm not sure that any of the platforms can
> actually measure a time resolution to accuracy greater than 1 msec.
> You may not be getting any practical benefit from reporting time to a
> precision greater than this.
>
> Dave

===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================




Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

David T. Lewis
In reply to this post by johnmci
 
On Sun, Jan 17, 2010 at 03:57:10PM -0800, John M McIntosh wrote:

>  
> The attached change set and sq.h enable microsecond timing for GC work.
> Please review for consideration for VMMaker.
>
> I've added a named primitive
>
> primitiveMicrosecondClock
> "This is a named (not numbered) primitive in the null module (ie the VM)"
> self export: true.
> self pop: 1 thenPush: (self positive64BitIntegerFor: (self ioMicroSeconds)).
>
>
> I used the 'sqLong' data type, but we don't seem to have a usqLong type to get unsigned long long  ?
> Since in this case I'd like the 64bit value to be positive only value...
>

I would not worry too much about using a sqLong here. If you report time
in microseconds since the Posix epoch, you can go nearly 300 centuries
before overflowing a 64 bit signed integer.

  bigLong := (2 raisedTo: 63) - 1.
  biggestMicrosecAsSeconds := bigLong / 1000000.
  secondsPerYear := 365.25 * 24 * 60 * 60.
  maxYears := biggestMicrosecAsSeconds / secondsPerYear.
  lastYear := 1970 + maxYears asInteger ==> 294241

Dave

Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

Eliot Miranda-2
 


On Tue, Jan 19, 2010 at 4:02 AM, David T. Lewis <[hidden email]> wrote:

On Sun, Jan 17, 2010 at 03:57:10PM -0800, John M McIntosh wrote:
>
> The attached change set and sq.h enable microsecond timing for GC work.
> Please review for consideration for VMMaker.
>
> I've added a named primitive
>
> primitiveMicrosecondClock
>       "This is a named (not numbered) primitive in the null module (ie the VM)"
>       self export: true.
>       self pop: 1 thenPush: (self positive64BitIntegerFor: (self ioMicroSeconds)).
>
>
> I used the 'sqLong' data type, but we don't seem to have a usqLong type to get unsigned long long  ?
> Since in this case I'd like the 64bit value to be positive only value...
>

I would not worry too much about using a sqLong here. If you report time
in microseconds since the Posix epoch, you can go nearly 300 centuries
before overflowing a 64 bit signed integer.

 bigLong := (2 raisedTo: 63) - 1.
 biggestMicrosecAsSeconds := bigLong / 1000000.
 secondsPerYear := 365.25 * 24 * 60 * 60.
 maxYears := biggestMicrosecAsSeconds / secondsPerYear.
 lastYear := 1970 + maxYears asInteger ==> 294241

Please keep to the Smalltalk epoch (start of the 20th century, 12am January 1 1901).  Then deriving the second clock from the microsecond clock requires only division, not division and subtraction.  Small point, but keep it as simple as possible.  i.e. the Smalltalk code for the second clock could read ^self microsecondClock // 1000000, with the VM losing the secondClock primitive.


Dave


Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

johnmci
In reply to this post by David T. Lewis

Well this is using a sqlLong which is signed 64bit, the default choice is sqInt 32bit signed which won't last long.
However I'm think more from a completeness viewpoint there should be a usqlLong  anyway.

On 2010-01-19, at 4:02 AM, David T. Lewis wrote:

> I would not worry too much about using a sqLong here. If you report time
> in microseconds since the Posix epoch, you can go nearly 300 centuries
> before overflowing a 64 bit signed integer.
>
>  bigLong := (2 raisedTo: 63) - 1.
>  biggestMicrosecAsSeconds := bigLong / 1000000.
>  secondsPerYear := 365.25 * 24 * 60 * 60.
>  maxYears := biggestMicrosecAsSeconds / secondsPerYear.
>  lastYear := 1970 + maxYears asInteger ==> 294241
>
> Dave
>

--
===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================




Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

johnmci
In reply to this post by Eliot Miranda-2
 
Ok, we maybe Ian can comment since the the code for the millisecond clock has been start at zero. 

Also if we return a value starting at epoch then we'll always end up with a large integer object which is costly and on base squeak systems could trigger a GC event, right
now we just end up with a small integer at least for a few day(s)... 

Perhaps we could look at having  two primitives one to return the microsecond clock from image startup, the other to return it from epoch start? 

Also the ioSecond primitive has been based on localTime versus  time() as per the Unix VM code below. 




time_t convertToSqueakTime(time_t unixTime)
{
#ifdef HAVE_TM_GMTOFF
  unixTime+= localtime(&unixTime)->tm_gmtoff;
#else
# ifdef HAVE_TIMEZONE
  unixTime+= ((daylight) * 60*60) - timezone;
# else
#  error: cannot determine timezone correction
# endif
#endif
  /* Squeak epoch is Jan 1, 1901.  Unix epoch is Jan 1, 1970: 17 leap years
     and 52 non-leap years later than Squeak. */
  return unixTime + ((52*365UL + 17*366UL) * 24*60*60UL);
}

/* returns the local wall clock time */
sqInt ioSeconds(void)
{
  return convertToSqueakTime(time(0));
}

--------------------------------------

On OS-X I do 

sqInt ioSeconds(void) {
//API Documented
time_t unixTime;
sqInt theSecondsAre; 


unixTime = time(0);
unixTime += localtime(&unixTime)->tm_gmtoff;
/* Squeak epoch is Jan 1, 1901.  Unix epoch is Jan 1, 1970: 17 leap years
and 52 non-leap years later than Squeak. */
theSecondsAre = unixTime + ((52*365UL + 17*366UL) * 24*60*60UL);
return theSecondsAre;
}


The original C code written by John Maloney did the following and has a most fascinating issue, anyone care to guess? 
I even opened an official bug with Apple on it and 20 months later got a curt reply from an Apple/NeXt unix engineer.

int ioSeconds(void) {
/* return the time in seconds since midnight of Jan 1, 1901.  */
/* optional: could simply return 0.  */

struct tm timeRec;
time_t time1904, timeNow;

/* start of ANSI epoch is midnight of Jan 1, 1904 */
timeRec.tm_sec   = 0;
timeRec.tm_min   = 0;
timeRec.tm_hour  = 0;
timeRec.tm_mday  = 1;
timeRec.tm_mon   = 0;
timeRec.tm_year  = 4;
timeRec.tm_wday  = 0;
timeRec.tm_yday  = 0;
timeRec.tm_isdst = 0;
time1904 = mktime(&timeRec);

timeNow = time(NULL);

/* Squeak epoch is Jan 1, 1901, 3 non-leap years earlier than ANSI one */
return (timeNow - time1904) + (3 * 365 * 24 * 60 * 60);
}




On 2010-01-19, at 9:26 AM, Eliot Miranda wrote:

Please keep to the Smalltalk epoch (start of the 20th century, 12am January 1 1901).  Then deriving the second clock from the microsecond clock requires only division, not division and subtraction.  Small point, but keep it as simple as possible.  i.e. the Smalltalk code for the second clock could read ^self microsecondClock // 1000000, with the VM losing the secondClock primitive.


Dave

--
===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================




Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

David T. Lewis
 
On Tue, Jan 19, 2010 at 10:54:35AM -0800, John M McIntosh wrote:
>  
> Ok, we maybe Ian can comment since the the code for the millisecond clock has been start at zero.
>
> Also if we return a value starting at epoch then we'll always end up with a large integer object which is costly and on base squeak systems could trigger a GC event, right
> now we just end up with a small integer at least for a few day(s)...
>
> Perhaps we could look at having  two primitives one to return the microsecond clock from image startup, the other to return it from epoch start?
>

Yes I agree, two separate primitives would be better for this.

> Also the ioSecond primitive has been based on localTime versus  time() as per the Unix VM code below.
>

And this is a Very Bad Thing if you want to support time zones with
daylight savings transitions.

Lex Spoon suggested 10 years ago that we should have a primitive
that answers UTC time plus time zone offset in a single call. He
was right, and I guess somebody (tm) should do something about that
one of these days.

The Smalltalk epoch is ambiguous in Squeak, so it would be better to
use the more clearly defined Posix epoch. Conversion to Squeak epoch
is trivial as long once you decide what time zone the Squeak epoch
occurred in.

Would anyone object to the addition of a primitive that answers
Posix seconds (to some reasonable precision) plus time zone offset?
This would be a named primitive in addition to John's microsecond
primitive.

Dave

Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

johnmci


On 2010-01-19, at 2:30 PM, David T. Lewis wrote:

> Would anyone object to the addition of a primitive that answers
> Posix seconds (to some reasonable precision) plus time zone offset?
> This would be a named primitive in addition to John's microsecond
> primitive.


So it would return an array with two items, the microseconds from posix time, and the time zone offset in seconds?

Isn't there something to let us build a time value using that then?  Also to convert back/forward to squeak epoch based time value?


--
===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================




Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

Andreas.Raab
In reply to this post by David T. Lewis
 
David T. Lewis wrote:
> On Tue, Jan 19, 2010 at 10:54:35AM -0800, John M McIntosh wrote:
>> Also the ioSecond primitive has been based on localTime versus  time() as per the Unix VM code below.
>
> And this is a Very Bad Thing if you want to support time zones with
> daylight savings transitions.

How so? I must be missing some background here, could you elaborate?

> Lex Spoon suggested 10 years ago that we should have a primitive
> that answers UTC time plus time zone offset in a single call. He
> was right, and I guess somebody (tm) should do something about that
> one of these days.

I fail to see what that achieves.

> The Smalltalk epoch is ambiguous in Squeak, so it would be better to
> use the more clearly defined Posix epoch. Conversion to Squeak epoch
> is trivial as long once you decide what time zone the Squeak epoch
> occurred in.
>
> Would anyone object to the addition of a primitive that answers
> Posix seconds (to some reasonable precision) plus time zone offset?
> This would be a named primitive in addition to John's microsecond
> primitive.

I'm not sure what the point of it would be. Both of you are speaking in
riddles at this point; it would be good if you could spell out the
issues more clearly.

Thanks,
   - Andreas
Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

David T. Lewis
 
On Tue, Jan 19, 2010 at 04:28:47PM -0800, Andreas Raab wrote:
> >
> >Would anyone object to the addition of a primitive that answers
> >Posix seconds (to some reasonable precision) plus time zone offset?
> >This would be a named primitive in addition to John's microsecond
> >primitive.
>
> I'm not sure what the point of it would be. Both of you are speaking in
> riddles at this point; it would be good if you could spell out the
> issues more clearly.

The clock in Squeak is done in local time (UTC translated to local
seconds in the VM before it is reported to the image). Consider a
Squeak image running in a locale with daylight savings time. Once
per year in the fall, there is a period of one hour during which the
Squeak clock has "jumped backwards" one hour. All of the values of the
Squeak clock are repeated during for the next hour. The values are
ambiguous, and the calculation of durations and times based on them
is problematic.

Time and duration manipulation is much simpler if you use a monotonically
increasing clock and calculate local times based on UTC and the local
offset value. The earliest Smalltalk systems were probably single
user systems for which time zones and duration calculations would
have been of little concern, but in an era when Squeak is used for
server applications and shared images in different parts of the world,
it is better to get this stuff right.

Dave

Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

Bert Freudenberg
In reply to this post by Andreas.Raab

On 20.01.2010, at 01:28, Andreas Raab wrote:
>
> David T. Lewis wrote:
>
>> Lex Spoon suggested 10 years ago that we should have a primitive
>> that answers UTC time plus time zone offset in a single call. He
>> was right, and I guess somebody (tm) should do something about that
>> one of these days.
>
> I fail to see what that achieves.

It atomically gives you both local time and UTC which is hard to do without such a primitive, because DST can kick in any moment.

Just adding a UTC primitive would go a long way, but this would be even better and hopefully future-proof (POSIX gettimeofday() managed quite well I think).

- Bert -

Reply | Threaded
Open this post in threaded view
|

Re: microsecond timing for GC work

Andreas.Raab
In reply to this post by David T. Lewis
 
David T. Lewis wrote:

> On Tue, Jan 19, 2010 at 04:28:47PM -0800, Andreas Raab wrote:
>>> Would anyone object to the addition of a primitive that answers
>>> Posix seconds (to some reasonable precision) plus time zone offset?
>>> This would be a named primitive in addition to John's microsecond
>>> primitive.
>> I'm not sure what the point of it would be. Both of you are speaking in
>> riddles at this point; it would be good if you could spell out the
>> issues more clearly.
>
> The clock in Squeak is done in local time (UTC translated to local
> seconds in the VM before it is reported to the image). Consider a
> Squeak image running in a locale with daylight savings time. Once
> per year in the fall, there is a period of one hour during which the
> Squeak clock has "jumped backwards" one hour. All of the values of the
> Squeak clock are repeated during for the next hour. The values are
> ambiguous, and the calculation of durations and times based on them
> is problematic.

Ah, I see. Thanks for clearing this up. How does that relate to posix
seconds as stated above? Are posix seconds UTC? If not, shouldn't we
rather make sure all time in UTC (regardless of epoch) and leave it to
the image to work out the timezone it's in? That seems the better
long-term option to me.

Cheers,
   - Andreas
Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] microsecond timing for GC work

David T. Lewis
 
On Tue, Jan 19, 2010 at 05:44:26PM -0800, Andreas Raab wrote:

>
> David T. Lewis wrote:
> >On Tue, Jan 19, 2010 at 04:28:47PM -0800, Andreas Raab wrote:
> >>>Would anyone object to the addition of a primitive that answers
> >>>Posix seconds (to some reasonable precision) plus time zone offset?
> >>>This would be a named primitive in addition to John's microsecond
> >>>primitive.
> >>I'm not sure what the point of it would be. Both of you are speaking in
> >>riddles at this point; it would be good if you could spell out the
> >>issues more clearly.
> >
> >The clock in Squeak is done in local time (UTC translated to local
> >seconds in the VM before it is reported to the image). Consider a
> >Squeak image running in a locale with daylight savings time. Once
> >per year in the fall, there is a period of one hour during which the
> >Squeak clock has "jumped backwards" one hour. All of the values of the
> >Squeak clock are repeated during for the next hour. The values are
> >ambiguous, and the calculation of durations and times based on them
> >is problematic.
>
> Ah, I see. Thanks for clearing this up. How does that relate to posix
> seconds as stated above? Are posix seconds UTC? If not, shouldn't we
> rather make sure all time in UTC (regardless of epoch) and leave it to
> the image to work out the timezone it's in? That seems the better
> long-term option to me.

Wikipedia has a very good overview:
  http://en.wikipedia.org/wiki/POSIX_time
  http://en.wikipedia.org/wiki/Coordinated_Universal_Time

Yes, I meant the same thing by "Posix seconds" and "UTC".

The Smalltalk epoch is a constant number of seconds apart from the
Posix epoch, although in Squeak it is not clear whether this should
be measured from Palo Alto or from London. If you use the Posix epoch
as the origin of your timeline and compute local time representation
from UTC seconds and an offset corresponding to your own timezone,
things just work.

Given the history of Squeak as a single user system with no awareness
of time zones, it is easiest to think of the current Squeak clock
as if the Smalltalk epoch was measured in your own local time zone,
and just pretend that daylight savings transitions do not happen.
That is perfectly sufficient for a single user computer (i.e.  99%
of all Squeak users), but it's wrong if you need to handle time
zones or calculate durations properly.

Dave

Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] microsecond timing for GC work

Andreas.Raab
 
Hi David -

Sounds good to me - proceed for truth :-)

Cheers,
   - Andreas

David T. Lewis wrote:

>  
> On Tue, Jan 19, 2010 at 05:44:26PM -0800, Andreas Raab wrote:
>> David T. Lewis wrote:
>>> On Tue, Jan 19, 2010 at 04:28:47PM -0800, Andreas Raab wrote:
>>>>> Would anyone object to the addition of a primitive that answers
>>>>> Posix seconds (to some reasonable precision) plus time zone offset?
>>>>> This would be a named primitive in addition to John's microsecond
>>>>> primitive.
>>>> I'm not sure what the point of it would be. Both of you are speaking in
>>>> riddles at this point; it would be good if you could spell out the
>>>> issues more clearly.
>>> The clock in Squeak is done in local time (UTC translated to local
>>> seconds in the VM before it is reported to the image). Consider a
>>> Squeak image running in a locale with daylight savings time. Once
>>> per year in the fall, there is a period of one hour during which the
>>> Squeak clock has "jumped backwards" one hour. All of the values of the
>>> Squeak clock are repeated during for the next hour. The values are
>>> ambiguous, and the calculation of durations and times based on them
>>> is problematic.
>> Ah, I see. Thanks for clearing this up. How does that relate to posix
>> seconds as stated above? Are posix seconds UTC? If not, shouldn't we
>> rather make sure all time in UTC (regardless of epoch) and leave it to
>> the image to work out the timezone it's in? That seems the better
>> long-term option to me.
>
> Wikipedia has a very good overview:
>   http://en.wikipedia.org/wiki/POSIX_time
>   http://en.wikipedia.org/wiki/Coordinated_Universal_Time
>
> Yes, I meant the same thing by "Posix seconds" and "UTC".
>
> The Smalltalk epoch is a constant number of seconds apart from the
> Posix epoch, although in Squeak it is not clear whether this should
> be measured from Palo Alto or from London. If you use the Posix epoch
> as the origin of your timeline and compute local time representation
> from UTC seconds and an offset corresponding to your own timezone,
> things just work.
>
> Given the history of Squeak as a single user system with no awareness
> of time zones, it is easiest to think of the current Squeak clock
> as if the Smalltalk epoch was measured in your own local time zone,
> and just pretend that daylight savings transitions do not happen.
> That is perfectly sufficient for a single user computer (i.e.  99%
> of all Squeak users), but it's wrong if you need to handle time
> zones or calculate durations properly.
>
> Dave
>
Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] microsecond timing for GC work

David T. Lewis
 
OK, attached is an implementation of #primitiveUtcWithOffset. It
answers an array with UTC time in microseconds since the Posix epoch,
and with GMT offset in seconds in the local time zone.

The choice of microsecond precision (rather than milliseconds)
implies a meaningless degree of precision, but it allows time to
be specified to effectivly unlimited precision for centuries to
come. If folks think that millisecond precision is more sensible,
it's a trivial change.

This is intended to be complimentary to (not a replacement for)
John's #primitiveMicrosecondClock primitive.

For a GCC compiler on unix, the support code function is:

  sqInt ioUtcWithOffset(sqLong *microSeconds, int *offset)
  {
    struct timeval timeval;
    if (gettimeofday(&timeval, NULL) == -1) return -1;
    long long seconds = timeval.tv_sec;
    suseconds_t usec = timeval.tv_usec;
    *microSeconds = seconds * 1000000 + usec;
    *offset = localtime(&seconds)->tm_gmtoff;
    return 0;
  }

The above is probably not portable to all unices, but I think
it works with any GCC based system. I have not looked at win32,
though I am sure there is an equivalent implementation.

Dave

On Tue, Jan 19, 2010 at 06:42:27PM -0800, Andreas Raab wrote:

>
> Hi David -
>
> Sounds good to me - proceed for truth :-)
>
> Cheers,
>   - Andreas
>
> David T. Lewis wrote:
> >
> >On Tue, Jan 19, 2010 at 05:44:26PM -0800, Andreas Raab wrote:
> >>David T. Lewis wrote:
> >>>On Tue, Jan 19, 2010 at 04:28:47PM -0800, Andreas Raab wrote:
> >>>>>Would anyone object to the addition of a primitive that answers
> >>>>>Posix seconds (to some reasonable precision) plus time zone offset?
> >>>>>This would be a named primitive in addition to John's microsecond
> >>>>>primitive.
> >>>>I'm not sure what the point of it would be. Both of you are speaking in
> >>>>riddles at this point; it would be good if you could spell out the
> >>>>issues more clearly.
> >>>The clock in Squeak is done in local time (UTC translated to local
> >>>seconds in the VM before it is reported to the image). Consider a
> >>>Squeak image running in a locale with daylight savings time. Once
> >>>per year in the fall, there is a period of one hour during which the
> >>>Squeak clock has "jumped backwards" one hour. All of the values of the
> >>>Squeak clock are repeated during for the next hour. The values are
> >>>ambiguous, and the calculation of durations and times based on them
> >>>is problematic.
> >>Ah, I see. Thanks for clearing this up. How does that relate to posix
> >>seconds as stated above? Are posix seconds UTC? If not, shouldn't we
> >>rather make sure all time in UTC (regardless of epoch) and leave it to
> >>the image to work out the timezone it's in? That seems the better
> >>long-term option to me.
> >
> >Wikipedia has a very good overview:
> >  http://en.wikipedia.org/wiki/POSIX_time
> >  http://en.wikipedia.org/wiki/Coordinated_Universal_Time
> >
> >Yes, I meant the same thing by "Posix seconds" and "UTC".
> >
> >The Smalltalk epoch is a constant number of seconds apart from the
> >Posix epoch, although in Squeak it is not clear whether this should
> >be measured from Palo Alto or from London. If you use the Posix epoch
> >as the origin of your timeline and compute local time representation
> >from UTC seconds and an offset corresponding to your own timezone,
> >things just work.
> >
> >Given the history of Squeak as a single user system with no awareness
> >of time zones, it is easiest to think of the current Squeak clock
> >as if the Smalltalk epoch was measured in your own local time zone,
> >and just pretend that daylight savings transitions do not happen.
> >That is perfectly sufficient for a single user computer (i.e.  99%
> >of all Squeak users), but it's wrong if you need to handle time
> >zones or calculate durations properly.
> >
> >Dave
> >

Interpreter-primitiveUtcWithOffset-dtl.1.cs (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] microsecond timing for GC work

David T. Lewis
In reply to this post by johnmci
 
On Sun, Jan 17, 2010 at 03:57:10PM -0800, John M McIntosh wrote:
>  
> The attached change set and sq.h enable microsecond timing for GC work.
> Please review for consideration for VMMaker.

This is being tracked for follow up on Mantis:
  http://bugs.squeak.org/view.php?id=7458

Dave

Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] microsecond timing for GC work

Bert Freudenberg
In reply to this post by David T. Lewis

On 21.01.2010, at 03:41, David T. Lewis wrote:

>
> OK, attached is an implementation of #primitiveUtcWithOffset. It
> answers an array with UTC time in microseconds since the Posix epoch,
> and with GMT offset in seconds in the local time zone.
>
> The choice of microsecond precision (rather than milliseconds)
> implies a meaningless degree of precision, but it allows time to
> be specified to effectivly unlimited precision for centuries to
> come. If folks think that millisecond precision is more sensible,
> it's a trivial change.
>
> This is intended to be complimentary to (not a replacement for)
> John's #primitiveMicrosecondClock primitive.
>
> For a GCC compiler on unix, the support code function is:
>
>  sqInt ioUtcWithOffset(sqLong *microSeconds, int *offset)
>  {
>    struct timeval timeval;
>    if (gettimeofday(&timeval, NULL) == -1) return -1;
>    long long seconds = timeval.tv_sec;
>    suseconds_t usec = timeval.tv_usec;
>    *microSeconds = seconds * 1000000 + usec;
>    *offset = localtime(&seconds)->tm_gmtoff;
>    return 0;
>  }
>
> The above is probably not portable to all unices, but I think
> it works with any GCC based system. I have not looked at win32,
> though I am sure there is an equivalent implementation.
>
> Dave

I was about to comment that gettimeofday() answers UTC while ioSeconds() currently uses time() which is "seconds since 0:00:00, Jan 1, 1970, Coordinated Universal Time, *without including leap seconds*" according to the BSD man page, but apparently it was later redefined in terms of UTC:
http://en.wikipedia.org/wiki/Unix_time

In any case, in the LocalePlugin I took care to have the timezone offset match the behavior of convertToSqueakTime() which in turn is used by ioSeconds():

platforms/unix/vm/sqUnixMain.c:

time_t convertToSqueakTime(time_t unixTime)
{
#ifdef HAVE_TM_GMTOFF
  unixTime+= localtime(&unixTime)->tm_gmtoff;
#else
# ifdef HAVE_TIMEZONE
  unixTime+= ((daylight) * 60*60) - timezone;
# else
#  error: cannot determine timezone correction
# endif
#endif
  /* Squeak epoch is Jan 1, 1901.  Unix epoch is Jan 1, 1970: 17 leap years
     and 52 non-leap years later than Squeak. */
  return unixTime + ((52*365UL + 17*366UL) * 24*60*60UL);
}

platforms/unix/plugins/LocalePlugin/sqUnixLocale.c:

/* Answer the offset to (number of minutes EAST of) GMT.
 */
sqInt sqLocGetTimezoneOffset(void)
{
  /* Match the behaviour of convertToSqueakTime(). */
#ifdef HAVE_TM_GMTOFF
  time_t now= time(0);
  return localtime(&now)->tm_gmtoff / 60;
#else
# ifdef HAVE_TIMEZONE
  extern long timezone;
  extern int daylight;
  return daylight * 60 - timezone / 60;
# else
#  error: cannot determine timezone correction
# endif
#endif
}

I think we should arrange to have ioUtcWithOffset() be used in all the other places to ensure a consistent interpretation of time ...

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] microsecond timing for GC work

David T. Lewis
 
On Thu, Jan 21, 2010 at 11:46:29AM +0100, Bert Freudenberg wrote:
>
> On 21.01.2010, at 03:41, David T. Lewis wrote:
> >
> > OK, attached is an implementation of #primitiveUtcWithOffset. It
> > answers an array with UTC time in microseconds since the Posix epoch,
> > and with GMT offset in seconds in the local time zone.
> >

> I was about to comment that gettimeofday() answers UTC while ioSeconds() currently uses time() which is "seconds since 0:00:00, Jan 1, 1970, Coordinated Universal Time, *without including leap seconds*" according to the BSD man page, but apparently it was later redefined in terms of UTC:
> http://en.wikipedia.org/wiki/Unix_time
>
> In any case, in the LocalePlugin I took care to have the timezone offset match the behavior of convertToSqueakTime() which in turn is used by ioSeconds():

> I think we should arrange to have ioUtcWithOffset() be used in all the other places to ensure a consistent interpretation of time ...

Bert,

Does the use of microseconds for time and seconds for offset make sense
to you?  In both cases this is more precision than required, but I could
see no good reason to reduce the precision.

We will need to be careful about using this everywhere, because use of
large integers for time values might have performance implications. It
will probably be OK, but I have not measured anything to check.

Dave