Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2011-10

Problem with Now() and time changed by ntpd

118 messages · 21 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

zeljko

Hi,

I have daemon which uses Now() for getting current date/time, but something is wrong, time on server changed from 03:00 to 02:00 this weekend, but daemon's Now() was on old time ... until now ... I've just restarted it and now it applied new time.
fpc-2.4.5, centos 5.5 ....
Also this confirms something what happens sometimes when ntpd changes time ... Any hints ? What to do ? Any workaround ?

zeljko

Reply by email

Michael Van Canneyt
to zeljko
zeljko wrote 13 lines
Hi, I have daemon which uses Now() for getting current date/time, but something is wrong, time on server changed from 03:00 to 02:00 this weekend, but daemon's Now() was on old time ... until now ... I've just restarted it and now it applied new time. fpc-2.4.5, centos 5.5 .... Also this confirms something what happens sometimes when ntpd changes time ... Any hints ? What to do ? Any workaround ?

It's probably the timezone information which is loaded only once at program startup.

This has been reported before, but no satisfying solution was found at the time. re-reading this file at each now() would be extremely slowing.

Michael.

Reply by email

zeljko
to Michael Van Canneyt
you wrote 21 lines
On Mon, 31 Oct 2011, zeljko wrote: > Hi, > > > I have daemon which uses Now() for getting current date/time, but > something is wrong, time on server changed from 03:00 to 02:00 this > weekend, but daemon's Now() was on old time ... until now ... I've just > restarted it and now it applied new time. > > fpc-2.4.5, centos 5.5 .... > > Also this confirms something what happens sometimes when ntpd changes > time ... > > Any hints ? What to do ? Any workaround ? It's probably the timezone information which is loaded only once at program startup. This has been reported before, but no satisfying solution was found at the time. re-reading this file at each now() would be extremely slowing.

uuuh...that's *huge* problem now. I'm not sure but I think that it worked ok with dcc, since I didn't need to restart services before migration to fpc. Maybe best way would be to use libc....uhhhh don't know, this thing desperated me completely ... must connect to client sites tomorrow all day and restart services.
Do you know issue # where that bug is reported ?

zeljko

Reply by email

zeljko
to Michael Van Canneyt: It's probably the timezone information which is loaded only once at program startup. This…
you wrote 21 lines
On Mon, 31 Oct 2011, zeljko wrote: > Hi, > > > I have daemon which uses Now() for getting current date/time, but > something is wrong, time on server changed from 03:00 to 02:00 this > weekend, but daemon's Now() was on old time ... until now ... I've just > restarted it and now it applied new time. > > fpc-2.4.5, centos 5.5 .... > > Also this confirms something what happens sometimes when ntpd changes > time ... > > Any hints ? What to do ? Any workaround ? It's probably the timezone information which is loaded only once at program startup. This has been reported before, but no satisfying solution was found at the time. re-reading this file at each now() would be extremely slowing.

hm... dcc (kylix) uses localtime_r and this is from man page of that function.

The localtime() function converts the calendar time timep to broken-time representation, expressed relative to the user's specified time zone. The function acts as if it called tzset(3) and sets the external variables tzname with information about the current time zone, timezone with the difference between Coordinated Universal Time (UTC) and local standard time in seconds, and daylight to a non-zero value if daylight savings time rules apply during some part of the year. The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. The localtime_r() function does the same, but stores the data in a user-supplied struct. It need not set tzname.

What uses fpgettimeofday() ?

zeljko

Reply by email

Sven Barth
to zeljko
zeljko wrote 69 lines
On Monday 31 of October 2011 20:17:46 you wrote: > On Mon, 31 Oct 2011, zeljko wrote: > > Hi, > > > > > > I have daemon which uses Now() for getting current date/time, but > > something is wrong, time on server changed from 03:00 to 02:00 this > > weekend, but daemon's Now() was on old time ... until now ... I've just > > restarted it and now it applied new time. > > > > fpc-2.4.5, centos 5.5 .... > > > > Also this confirms something what happens sometimes when ntpd changes > > time ... > > > > Any hints ? What to do ? Any workaround ? > > It's probably the timezone information which is loaded only once at program > startup. > > This has been reported before, but no satisfying solution was found at the > time. re-reading this file at each now() would be extremely slowing. hm... dcc (kylix) uses localtime_r and this is from man page of that function. The localtime() function converts the calendar time timep to broken-time representation, expressed relative to the user's specified time zone. The function acts as if it called tzset(3) and sets the external variables tzname with information about the current time zone, timezone with the difference between Coordinated Universal Time (UTC) and local standard time in seconds, and daylight to a non-zero value if daylight savings time rules apply during some part of the year. The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. The localtime_r() function does the same, but stores the data in a user-supplied struct. It need not set tzname. What uses fpgettimeofday() ?

fpgettimeofday uses exactly what it says on the tin: gettimeofday. See here: http://linux.die.net/man/2/gettimeofday

The fp* functions in Linux by default call directly the kernel instead of going through libc, thus avoiding the dependency on that library.

Maybe a possibilty should be implemented in unit Unix to reread the timezone file. This wouldn't solve your problem directly, but it would at least provide the ability to update the time zone information without restarting the application/service. The trigger would need to come from an external source though (maybe by checking that timezone database that was in the media some weeks ago).

Regards,
Sven

Reply by email

zeljko
to Sven Barth
Sven Barth wrote
fpgettimeofday uses exactly what it says on the tin: gettimeofday. See here: http://linux.die.net/man/2/gettimeofday

Yes, I've readed man page of gettimeofday already.

The fp* functions in Linux by default call directly the kernel instead of going through libc, thus avoiding the dependency on that library.

that's ok, but afaik gettimeofday is deprecated.

Show quoted text 7 lines
Maybe a possibilty should be implemented in unit Unix to reread the timezone file. This wouldn't solve your problem directly, but it would at least provide the ability to update the time zone information without restarting the application/service. The trigger would need to come from an external source though (maybe by checking that timezone database that was in the media some weeks ago).

Don't know what to do ... I must fix this asap somehow ... even with using my own Now() implementation by calling libc ... don't know ... this pissed me off totally.

zeljko

Reply by email

José Mejuto
to zeljko

Hello zeljko,

Monday, October 31, 2011, 8:58:14 PM, you wrote:

z> Don't know what to do ... I must fix this asap somehow ... even with using my z> own Now() implementation by calling libc ... don't know ... this pissed me off z> totally.

Is the UTC time reliable (the value that you can get) ? If it is just calculate your local time from UTC instead using Now().

Best regards, José

Reply by email

Tomas Hajny
to Michael Van Canneyt: It's probably the timezone information which is loaded only once at program startup. This…
Michael Van Canneyt wrote 20 lines
On Mon, 31 Oct 2011, zeljko wrote: > > Hi, > > > I have daemon which uses Now() for getting current date/time, but something is wrong, time on server changed from 03:00 > to 02:00 this weekend, but daemon's Now() was on old time ... until now ... I've just restarted it and now it applied > new time. > > fpc-2.4.5, centos 5.5 .... > > Also this confirms something what happens sometimes when ntpd changes time ... > > Any hints ? What to do ? Any workaround ? It's probably the timezone information which is loaded only once at program startup. This has been reported before, but no satisfying solution was found at the time. re-reading this file at each now() would be extremely slowing.

Sorry for a silly question but isn't the DST transition time stored within the same timezone definition file? If it is then you might calculate and store the next DST transition time coming after the time of initialization, compare it to the time requested for translation in EpochToLocal and trigger re-initialization of both TZSeconds and the next transition time whenever the original DST transition time is crossed...

Tomas

Reply by email

waldo kitty
to Sven Barth: fpgettimeofday uses exactly what it says on the tin: gettimeofday. See here:…
Sven Barth wrote 6 lines
Maybe a possibilty should be implemented in unit Unix to reread the timezone file. This wouldn't solve your problem directly, but it would at least provide the ability to update the time zone information without restarting the application/service. The trigger would need to come from an external source though (maybe by checking that timezone database that was in the media some weeks ago).

why should the trigger come from an external source? it is easy enough to have a routine watch and adjust automatically which could trigger the re-read sought...

Reply by email

zeljko
to waldo kitty
waldo kitty wrote 11 lines
On 10/31/2011 15:47, Sven Barth wrote: > Maybe a possibilty should be implemented in unit Unix to reread the > timezone file. This wouldn't solve your problem directly, but it would > at least provide the ability to update the time zone information without > restarting the application/service. The trigger would need to come from > an external source though (maybe by checking that timezone database that > was in the media some weeks ago). why should the trigger come from an external source? it is easy enough to have a routine watch and adjust automatically which could trigger the re-read sought...

Yes, after sleeping one night, I can say that I disagree with Sven about it. This is base rtl function and it must be correct in all cases. It must work correct, or please document it as weak and buggy (for linux). I don't believe that kernel have only gettimeofday() and that kernel don't know accurate datetime. There's more functions in kernel which can give you accurate result. gettimeofday() is deprecated, so maybe that's main reason why it fails to give correct result with daylight changes.

zeljko

Reply by email

zeljko
to Sven Barth: fpgettimeofday uses exactly what it says on the tin: gettimeofday. See here:…
Show quoted text 12 lines
fpgettimeofday uses exactly what it says on the tin: gettimeofday. See here: http://linux.die.net/man/2/gettimeofday The fp* functions in Linux by default call directly the kernel instead of going through libc, thus avoiding the dependency on that library. Maybe a possibilty should be implemented in unit Unix to reread the timezone file. This wouldn't solve your problem directly, but it would at least provide the ability to update the time zone information without restarting the application/service. The trigger would need to come from an external source though (maybe by checking that timezone database that was in the media some weeks ago).

There is possibility:

gettimeofday() can result in incorrect timings if there are processes on your system that change the timer (ie, ntpd). On a "normal" linux, though, I believe the resolution of gettimeofday() is 10us. It can jump forward and backward and time, consequently, based on the processes running on your system.
Look into clock_gettime(CLOCK_MONOTONIC) for timing intervals. It suffers from several less issues due to things like multi-core systems and external clock settings.
Also, look into the clock_getres() function.

So should I open an issue about this ?

zeljko

Reply by email

Sven Barth
to waldo kitty: why should the trigger come from an external source? it is easy enough to have a routine…
waldo kitty wrote 15 lines
On 10/31/2011 15:47, Sven Barth wrote: > Maybe a possibilty should be implemented in unit Unix to reread the > timezone > file. This wouldn't solve your problem directly, but it would at least > provide > the ability to update the time zone information without restarting the > application/service. The trigger would need to come from an external > source > though (maybe by checking that timezone database that was in the media > some > weeks ago). why should the trigger come from an external source? it is easy enough to have a routine watch and adjust automatically which could trigger the re-read sought...

I meant "external" as in "not in the RTL".

Regards,
Sven

Reply by email

Sven Barth
to zeljko: There is possibility: gettimeofday() can result in incorrect timings if there are…
zeljko wrote
Look into clock_gettime(CLOCK_MONOTONIC) for timing intervals. It suffers from several less issues due to things like multi-core systems and external clock settings.

But according to the manpage there is one problem (emphasis mine)

CLOCK_MONOTONIC
Clock that cannot be set and represents monotonic time *since some unspecified starting point*.

Also, look into the clock_getres() function. So should I open an issue about this ?

It might be the best if you want to see this solved.

Regards,
Sven

Reply by email

Sven Barth
to zeljko: Yes, after sleeping one night, I can say that I disagree with Sven about it. This is base…
zeljko wrote
I don't believe that kernel have only gettimeofday() and that kernel don't know accurate datetime. There's more functions in kernel which can give you accurate result. gettimeofday() is deprecated, so maybe that's main reason why it fails to give correct result with daylight changes.

Out of curiosity: Where did you get that gettimeofday is deprecated?

Regards,
Sven

Reply by email

zeljko
to Sven Barth
Sven Barth wrote 7 lines
On 01.11.2011 09:41, zeljko wrote: > I don't believe that kernel have only gettimeofday() and that kernel > don't know accurate datetime. There's more functions in kernel which can > give you accurate result. gettimeofday() is deprecated, so maybe that's > main reason why it fails to give correct result with daylight changes. Out of curiosity: Where did you get that gettimeofday is deprecated?

somewhere in /usr/include ... or time.h or sys/time.h

Show quoted text 7 lines
Regards, Sven _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Henry Vermaak
to Sven Barth: Out of curiosity: Where did you get that gettimeofday is deprecated? Sven
Sven Barth wrote 7 lines
On 01.11.2011 09:41, zeljko wrote: > I don't believe that kernel have only gettimeofday() and that kernel > don't know accurate datetime. There's more functions in kernel which can > give you accurate result. gettimeofday() is deprecated, so maybe that's > main reason why it fails to give correct result with daylight changes. Out of curiosity: Where did you get that gettimeofday is deprecated?

http://www.kernel.org/doc/man-pages/online/pages/man2/gettimeofday.2.html#CONFORMING_TO

Reply by email

Michael Van Canneyt
to zeljko: somewhere in /usr/include ... or time.h or sys/time.h
zeljko wrote 19 lines
On Tuesday 01 of November 2011 11:01:32 Sven Barth wrote: > On 01.11.2011 09:41, zeljko wrote: > > I don't believe that kernel have only gettimeofday() and that kernel > > don't know accurate datetime. There's more functions in kernel which can > > give you accurate result. gettimeofday() is deprecated, so maybe that's > > main reason why it fails to give correct result with daylight changes. > > Out of curiosity: Where did you get that gettimeofday is deprecated? somewhere in /usr/include ... or time.h or sys/time.h

The problem is not in gettimeofday. The problem is in the timezone information.

The clock functions are just a more elaborate form of gettimeofday, they introduce nothing fundamentally new.

Using clock_gettime will not help, since it returns the same time as gettimeofday, namely the elapsed time since the Epoch.

It expliticly says in the man page of clock_gettime: "When its time is changed, timers for a relative interval are unaffected, but timers for an absolute point in time are affected."

As stated, the problem is the time-zone and DST information. The kernel has no idea about time zones, it just keeps ticks since the epoch. All applications must convert the time returned by gettimeofday or clock_gettime to local time. For this, they use the information in the timezone files.

We'll simply need to store the next moment when the DST correction changes, compare the result of gettimeofday with that and re-base the time calculation. If we decide to add some check for the timestamp of the timezone file - that would make Date(), Time() and Now() VERY expensive operations.

All the above is the reason that high-speed loggers simply store the result of gettimeofday in the logs.

Michael.

Reply by email

Felipe Monteiro de Carvalho
to Michael Van Canneyt

One idea: In Now if you read the timezones, then store the value of Now. In subsequent calls check if 1 hour has passed since the last time the timezones were checked. If yes, then update the timezones and store this new base value of Now.

This makes a compromise between speed and correctnees. It would at most be wrong for 1 hour during a long running application. For other applications which call Now very frequently we only add some value checkes more to the overhead, which shouldn't be expensive.

Felipe Monteiro de Carvalho

Reply by email

Sven Barth
to Henry Vermaak: http://www.kernel.org/doc/man-pages/online/pages/man2/gettimeofday.2.html#CONFORMING_TO
Henry Vermaak wrote 10 lines
On 01/11/11 10:01, Sven Barth wrote: > On 01.11.2011 09:41, zeljko wrote: >> I don't believe that kernel have only gettimeofday() and that kernel >> don't know accurate datetime. There's more functions in kernel which can >> give you accurate result. gettimeofday() is deprecated, so maybe that's >> main reason why it fails to give correct result with daylight changes. > > Out of curiosity: Where did you get that gettimeofday is deprecated? http://www.kernel.org/doc/man-pages/online/pages/man2/gettimeofday.2.html#CONFORMING_TO

Thanks.

Regards,
Sven

Reply by email

Tomas Hajny
to Felipe Monteiro de Carvalho: One idea: In Now if you read the timezones, then store the value of Now. In subsequent…
Felipe Monteiro de Carvalho wrote 9 lines
One idea: In Now if you read the timezones, then store the value of Now. In subsequent calls check if 1 hour has passed since the last time the timezones were checked. If yes, then update the timezones and store this new base value of Now. This makes a compromise between speed and correctnees. It would at most be wrong for 1 hour during a long running application. For other applications which call Now very frequently we only add some value checkes more to the overhead, which shouldn't be expensive.

Comparing to the DST transition time as suggested in my previous e-mail (and also mentioned by Michael) is probably equally expensive in terms of runtime overhead (except for the initialization, but that isn't a major factor) but more accurate.

Tomas

Reply by email

Henry Vermaak
to Michael Van Canneyt: The problem is not in gettimeofday. The problem is in the timezone information. The clock…
Michael Van Canneyt wrote 5 lines
We'll simply need to store the next moment when the DST correction changes, compare the result of gettimeofday with that and re-base the time calculation. If we decide to add some check for the timestamp of the timezone file - that would make Date(), Time() and Now() VERY expensive operations.

This seems to be what libc does (from looking at an strace of some gcc binary).

Henry

Reply by email

Michael Van Canneyt
to Henry Vermaak
Henry Vermaak wrote 9 lines
On 01/11/11 10:30, Michael Van Canneyt wrote: > We'll simply need to store the next moment when the DST correction > changes, compare the result of gettimeofday with that and re-base the > time calculation. If we decide to add some check for the timestamp of > the timezone file - that would make Date(), Time() and Now() VERY > expensive operations. This seems to be what libc does (from looking at an strace of some gcc binary).

Correct (I had checked as well), but the only purpose that serves is to check whether the system timezone info has changed.

This is something that normally doesn't happen unless you move your system from one timezone to another or during system setup, so I question the desirability of this check.

Michael.

Reply by email

Felipe Monteiro de Carvalho
to Michael Van Canneyt
Michael Van Canneyt wrote
This is something that normally doesn't happen unless you move your system from one timezone to another or during system setup

In many countries the time zone changes 2 times a year because of the summer time.

Felipe Monteiro de Carvalho

Reply by email

Michael Van Canneyt
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 7 lines
On Tue, Nov 1, 2011 at 12:08 PM, Michael Van Canneyt wrote: > This is something that normally doesn't happen unless you move your system > from one timezone to another or during system setup In many countries the time zone changes 2 times a year because of the summer time.

No, this is DST: Daylight Saving Time.

The indication of the use of DST is included in the timezone information (but currently not correctly applied by FPC's runtime).

The timezone itself does not change, unless you physically move the machine from, say, Belgium to Russia.

Michael.

Reply by email

Henry Vermaak
to Michael Van Canneyt: Correct (I had checked as well), but the only purpose that serves is to check whether the…
Michael Van Canneyt wrote 20 lines
On Tue, 1 Nov 2011, Henry Vermaak wrote: > On 01/11/11 10:30, Michael Van Canneyt wrote: >> We'll simply need to store the next moment when the DST correction >> changes, compare the result of gettimeofday with that and re-base the >> time calculation. If we decide to add some check for the timestamp of >> the timezone file - that would make Date(), Time() and Now() VERY >> expensive operations. > > This seems to be what libc does (from looking at an strace of some gcc > binary). Correct (I had checked as well), but the only purpose that serves is to check whether the system timezone info has changed. This is something that normally doesn't happen unless you move your system from one timezone to another or during system setup, so I question the desirability of this check.

If you don't do this, daemons that were started before e.g. a daylight savings update will report the wrong time after the update. Rather solve this correctly than take short cuts because you want to keep the time functions "fast". Someone can always add performance timing helpers that use the correct functions on various OSes.

Henry

Reply by email

Marco van de Voort
to Michael Van Canneyt: Correct (I had checked as well), but the only purpose that serves is to check whether the…

In our previous episode, Michael Van Canneyt said:

Show quoted text 7 lines
Correct (I had checked as well), but the only purpose that serves is to check whether the system timezone info has changed. This is something that normally doesn't happen unless you move your system from one timezone to another or during system setup, so I question the desirability of this check.

E.g. the US DST times have changed in the very recent past. Updates can also update timezone data.

Reply by email

zeljko
to Henry Vermaak: http://www.kernel.org/doc/man-pages/online/pages/man2/gettimeofday.2.html#CONFORMING_TO
Henry Vermaak wrote 13 lines
On 01/11/11 10:01, Sven Barth wrote: > On 01.11.2011 09:41, zeljko wrote: >> I don't believe that kernel have only gettimeofday() and that kernel >> don't know accurate datetime. There's more functions in kernel which can >> give you accurate result. gettimeofday() is deprecated, so maybe that's >> main reason why it fails to give correct result with daylight changes. > > Out of curiosity: Where did you get that gettimeofday is deprecated? http://www.kernel.org/doc/man-pages/online/pages/man2/gettimeofday.2.html#C ONFORMING_TO _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Thanks Henry, that's exactly what I mean.

zeljko

Reply by email

Tomas Hajny
to Marco van de Voort: In our previous episode, Michael Van Canneyt said: E.g. the US DST times have changed in…
Marco van de Voort wrote 12 lines
In our previous episode, Michael Van Canneyt said: > > Correct (I had checked as well), but the only purpose that serves > is to check whether the system timezone info has changed. > > This is something that normally doesn't happen unless you move your > system from one timezone to another or during system setup, so I > question the desirability of this check. E.g. the US DST times have changed in the very recent past. Updates can also update timezone data.

The definitions changed just now for Russia (well, the change was effective since the last weekend). I also believe that it isn't a completely theoretical case. It shouldn't be necessary to perform this kind of check more often than once a day though (the definition doesn't change on the same day since which it should be effective).

Tomas

Reply by email

Michael Van Canneyt
to Marco van de Voort: In our previous episode, Michael Van Canneyt said: E.g. the US DST times have changed in…
Marco van de Voort wrote 11 lines
In our previous episode, Michael Van Canneyt said: > > Correct (I had checked as well), but the only purpose that serves > is to check whether the system timezone info has changed. > > This is something that normally doesn't happen unless you move your > system from one timezone to another or during system setup, so I > question the desirability of this check. E.g. the US DST times have changed in the very recent past. Updates can also update timezone data.

This falls under 'system setup'.

Michael.

Reply by email

Michael Van Canneyt
to Henry Vermaak: If you don't do this, daemons that were started before e.g. a daylight savings update…
Henry Vermaak wrote 27 lines
On 01/11/11 11:08, Michael Van Canneyt wrote: > > > On Tue, 1 Nov 2011, Henry Vermaak wrote: > >> On 01/11/11 10:30, Michael Van Canneyt wrote: >>> We'll simply need to store the next moment when the DST correction >>> changes, compare the result of gettimeofday with that and re-base the >>> time calculation. If we decide to add some check for the timestamp of >>> the timezone file - that would make Date(), Time() and Now() VERY >>> expensive operations. >> >> This seems to be what libc does (from looking at an strace of some gcc >> binary). > > Correct (I had checked as well), but the only purpose that serves is to > check whether the system timezone info has changed. > > This is something that normally doesn't happen unless you move your > system from one timezone to another or during system setup, so I > question the desirability of this check. If you don't do this, daemons that were started before e.g. a daylight savings update will report the wrong time after the update. Rather solve this correctly than take short cuts because you want to keep the time functions "fast". Someone can always add performance timing helpers that use the correct functions on various OSes.

The problem with that is that a LOT of existing code contains many calls to Now() and Date(), because these calls are very cheap on Windows. If all these calls will suddenly cause a stat() of /etc/localtime, that's simply not acceptable, since that will cause a noticeable error in your reported time, as disk access is very slow and dependent on system load.

As I see it, it is a 2 step program:

1. First off, we must correctly take into account DST. That should fix Zejlko's problem.

2. Then we can include a variable to regulate the behaviour of detecting TZ definition changes. (i.e. the Stat() call)

Michael.

Reply by email

Tomas Hajny
to Michael Van Canneyt: This falls under 'system setup'. Michael.
Michael Van Canneyt wrote 15 lines
On Tue, 1 Nov 2011, Marco van de Voort wrote: > In our previous episode, Michael Van Canneyt said: >> >> Correct (I had checked as well), but the only purpose that serves >> is to check whether the system timezone info has changed. >> >> This is something that normally doesn't happen unless you move your >> system from one timezone to another or during system setup, so I >> question the desirability of this check. > > E.g. the US DST times have changed in the very recent past. Updates can > also > update timezone data. This falls under 'system setup'.

I believe that the assigned category isn't so important; the point IMHO is that it can happen easily while some FPC written program is running (e.g. due to regular "apt-get update" & "apt-get upgrade" and the administrator would never know that he or she should restart certain daemon after such a change (normally, the administrator shouldn't care whether the daemon was written in FPC, C or PL/I).

Tomas

Reply by email

Michael Van Canneyt
to Tomas Hajny: The definitions changed just now for Russia (well, the change was effective since the…
Tomas Hajny wrote 19 lines
On Tue, November 1, 2011 12:49, Marco van de Voort wrote: > In our previous episode, Michael Van Canneyt said: >> >> Correct (I had checked as well), but the only purpose that serves >> is to check whether the system timezone info has changed. >> >> This is something that normally doesn't happen unless you move your >> system from one timezone to another or during system setup, so I >> question the desirability of this check. > > E.g. the US DST times have changed in the very recent past. Updates can > also > update timezone data. The definitions changed just now for Russia (well, the change was effective since the last weekend). I also believe that it isn't a completely theoretical case. It shouldn't be necessary to perform this kind of check more often than once a day though (the definition doesn't change on the same day since which it should be effective).

I was also thinking along these lines.

Michael.

Reply by email

zeljko
to Michael Van Canneyt: The problem is not in gettimeofday. The problem is in the timezone information. The clock…
Show quoted text 5 lines
We'll simply need to store the next moment when the DST correction changes, compare the result of gettimeofday with that and re-base the time calculation. If we decide to add some check for the timestamp of the timezone file - that would make Date(), Time() and Now() VERY expensive operations.

IMO, better correct and slow than incorrect and fast (especially in this case , since 24/7 apps compiled with fpc aren't 24/7 apps anymore).

At least this must be documented in fpc until it's fixed or provided some kind of workaround, eg that our 24/7 service (or any other app - doesn't matter at all) can trigger rtl from time to time to read tzdata.

eg. imagine bool FpReadTZDataNextTime: Boolean = False; (global variable). when we call fpgettimeofday() we check if FpReadTZDataNextTime is false/true. If I say in my app:
SysUtils.FPReadTZDataNextTime := True;
That will mean read tzdatadb in next call of fpgettimeofday() and then correct time if needed and set FPReadTZDataNextTime to false.

In that case rtl stays clear and fast and it re-reads tzdata only when it's called from application.
Not best solution , but can help a lot until final solution is found.

zeljko

Reply by email

Henry Vermaak
to Michael Van Canneyt: The problem with that is that a LOT of existing code contains many calls to Now() and…
Michael Van Canneyt wrote 12 lines
On Tue, 1 Nov 2011, Henry Vermaak wrote: > If you don't do this, daemons that were started before e.g. a daylight > savings update will report the wrong time after the update. Rather > solve this correctly than take short cuts because you want to keep the > time functions "fast". Someone can always add performance timing > helpers that use the correct functions on various OSes. The problem with that is that a LOT of existing code contains many calls to Now() and Date(), because these calls are very cheap on Windows. If all these calls will suddenly cause a stat() of /etc/localtime, that's simply not acceptable, since that will cause a noticeable error in your reported time, as disk access is very slow and dependent on system load.

This is just speculation. There will always be an error in the reported time, these calls are not atomic. It would be slower doing a stat, yes, but saying that the error will be "noticeable" I will leave for you to prove.

Also, how cheap is this on Windows? Presumably they will also have to deal with potential system services running while updates fix daylight saving time changes? If they don't use shared memory for this, I'd wager that it's just as slow as libc localtime.

I don't think the definition of "acceptable" for the RTL should be "may be wrong in corner cases, as long as it's fast". I'm sure you'd agree.

Henry

Reply by email

José Mejuto
to zeljko

Hello zeljko,

you wrote
> 1. First off, we must correctly take into account DST. That should fix > Zejlko's problem.

z> Am I the only one who produces 24/7 services with fpc in the world (and z> around) ? ;)

For sure no :) I found that problem 2 years ago, but not exactly related to real time, but to stored local times that must be processed across time zones, so I wrote PascalTZ http://wiki.lazarus.freepascal.org/PascalTZ

Best regards, José

Reply by email

Hans-Peter Diettrich
to Michael Van Canneyt: The problem is not in gettimeofday. The problem is in the timezone information. The clock…
Show quoted text 5 lines
We'll simply need to store the next moment when the DST correction changes, compare the result of gettimeofday with that and re-base the time calculation. If we decide to add some check for the timestamp of the timezone file - that would make Date(), Time() and Now() VERY expensive operations.

Doesn't the system signal such changes? IMO Windows does...

DoDi

Reply by email

Hans-Peter Diettrich
to Felipe Monteiro de Carvalho: On Tue, Nov 1, 2011 at 12:08 PM, Michael Van Canneyt In many countries the time zone…
Show quoted text 7 lines
On Tue, Nov 1, 2011 at 12:08 PM, Michael Van Canneyt wrote: > This is something that normally doesn't happen unless you move your system > from one timezone to another or during system setup In many countries the time zone changes 2 times a year because of the summer time.

Just in those countries (Germany...) it would be better to log UTC values, with no overlapping or skipped hours.

But the difference between UTC and local time is low in western Europe, in other countries UTC timestamps may look strange.

DoDi

Reply by email

Thaddy
to Jonas Maebe: This happens regularly with laptops (and at least I almost never shut down my laptop when…
Jonas Maebe wrote 9 lines
On 01 Nov 2011, at 12:30, Michael Van Canneyt wrote: > The timezone itself does not change, unless you physically move the machine from, say, Belgium to Russia. This happens regularly with laptops (and at least I almost never shut down my laptop when traveling, I just let it hibernate so programs keep running). Jonas_______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Yes. Traveling between London and Amsterdam is enough. (Not at all uncommon, here)

Reply by email

zeljko
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 6 lines
zeljko schrieb: > Am I the only one who produces 24/7 services with fpc in the world (and > around) ? ;) You seem to be the only one who provides such services based on *local* time, with 23..25 hours per day ;-)

Lucky me :)

zeljko

Reply by email

Michael Van Canneyt
to zeljko: IMO, better correct and slow than incorrect and fast (especially in this case , since…
zeljko wrote 23 lines
> We'll simply need to store the next moment when the DST correction changes, > compare the result of gettimeofday with that and re-base the time > calculation. If we decide to add some check for the timestamp of the > timezone file - that would make Date(), Time() and Now() VERY expensive > operations. IMO, better correct and slow than incorrect and fast (especially in this case , since 24/7 apps compiled with fpc aren't 24/7 apps anymore). At least this must be documented in fpc until it's fixed or provided some kind of workaround, eg that our 24/7 service (or any other app - doesn't matter at all) can trigger rtl from time to time to read tzdata. eg. imagine bool FpReadTZDataNextTime: Boolean = False; (global variable). when we call fpgettimeofday() we check if FpReadTZDataNextTime is false/true.

It will be something like that, yes. I was thinking of introducing a

CheckRefreshTZInfoInterval: integer;

-1 : never check for refresh (current behaviour)
0 : refresh on each call (like LibC, will be new default)

0 : Only refresh every N [yourfavouriteinterval].

But of course not in fpgettimeofday, in EpochToLocalTime. I repeat: fpgettimeofday returns UTC time, it does not need to read timezone info.

It is the step which converts this time to local time that must re-read the timezone files if needed. (EpochToLocalTime, the equivalent of localtime_r in libc)

However, meanwhile:

1. You can force a re-calculation of DST with the call (unix unit):

   GetLocalTimezone(fptime);

This will not refresh the TZ data from file, but will re-calculate the DST settings.

2. You can force a re-read of the timezone file with (unix unit):

   ReadTimezoneFile(GetTimezoneFile);

Then you must still do the recalculation of DST.
These calls were already present in the RTL.

3. A more simple mechanism is using the (newly added) ReReadTimeZone (unix unit):

   ReReadTimeZone;

Which will re-read TZ and re-calculate DST settings all in one go. I added this in revision 19569. The idea is that the new 'automation' mechanism will call this routine.

Michael.

Reply by email

zeljko
you wrote 7 lines
zeljko schrieb: > Now() must return exactly what it's name says. Anything of that is > bug. Okay, so what's the *exact* definition of Now()? Is a local calendar system taken into account?

It should return exactly same information as you can see in clock in right of systemtray (KDE, Windows etc ..). That's how I see Now(). Does it look for moon phases , local settings etc... I don't care.

zeljko

Reply by email

zeljko
to Michael Van Canneyt: It will be something like that, yes. I was thinking of introducing a…
you wrote 11 lines
It will be something like that, yes. I was thinking of introducing a CheckRefreshTZInfoInterval: integer; -1 : never check for refresh (current behaviour) 0 : refresh on each call (like LibC, will be new default) >0 : Only refresh every N [yourfavouriteinterval]. But of course not in fpgettimeofday, in EpochToLocalTime. I repeat: fpgettimeofday returns UTC time, it does not need to read timezone info.

Yes, you're correct here.

Show quoted text 14 lines
It is the step which converts this time to local time that must re-read the timezone files if needed. (EpochToLocalTime, the equivalent of localtime_r in libc) However, meanwhile: 3. A more simple mechanism is using the (newly added) ReReadTimeZone (unix unit): ReReadTimeZone; Which will re-read TZ and re-calculate DST settings all in one go. I added this in revision 19569. The idea is that the new 'automation' mechanism will call this routine.

Ok, will this routine be merged into 2.4.5 and 2.6.0 ? If not , then it's not big deal atm since 2.8 will be out at least in one year (but DST will change until then ;))) )

Another question: if I call ReReadTimeZone, it'll just do what it's name says, next Now() call will return correct result ?

Thanks for your time over this problem.

zeljko

Reply by email

Marco van de Voort
to Henry Vermaak: This is just speculation. There will always be an error in the reported time, these…

In our previous episode, Henry Vermaak said:

Also, how cheap is this on Windows? Presumably they will also have to deal with potential system services running while updates fix daylight saving time changes? If they don't use shared memory for this, I'd wager that it's just as slow as libc localtime.

I doubt Windows has a _file_ based concept of timezone.

I don't think the definition of "acceptable" for the RTL should be "may be wrong in corner cases, as long as it's fast". I'm sure you'd agree.

As Michael explained there are multiple usecases for gettime like functionality.

And I agree with him (if only because my business app would break horribly. Worse, if my business app ran on Linux, rescanning the timezone files in a thread that called gettime would probably violate realtime constraints and our quality assurance app would eject valid products because of unexpected latency due to unforseen harddisk access.

Reply by email

Sven Barth
to Henry Vermaak: This is just speculation. There will always be an error in the reported time, these…
Henry Vermaak wrote
Also, how cheap is this on Windows? Presumably they will also have to deal with potential system services running while updates fix daylight saving time changes? If they don't use shared memory for this, I'd wager that it's just as slow as libc localtime.

I've checked the Windows implementation. FPC's RTL in the end calls the function GetLocalTime which - as the name suggests - already returns the time that belongs to the current timezone (and DST settings). The implementation of that is cheap as well: the current bias from UTC is located in a shared memory section which the kernel maps into each running process. Thus only that one location (and the location were this setting is saved) is changed if a change of the timezone or the DST happens. So this is very cheap.

Note: for this I've looked into the source of ReactOS.

Regards,
Sven

Reply by email

Henry Vermaak
to Marco van de Voort: In our previous episode, Henry Vermaak said: I doubt Windows has a _file_ based concept…
Marco van de Voort wrote 7 lines
In our previous episode, Henry Vermaak said: > Also, how cheap is this on Windows?  Presumably they will also have to > deal with potential system services running while updates fix daylight > saving time changes?  If they don't use shared memory for this, I'd > wager that it's just as slow as libc localtime. I doubt Windows has a _file_ based concept of timezone.

Explain?

Show quoted text 11 lines
> I don't think the definition of "acceptable" for the RTL should be "may > be wrong in corner cases, as long as it's fast".  I'm sure you'd agree. As Michael explained there are multiple usecases for gettime like functionality. And I agree with him (if only because my business app would break horribly. Worse, if my business app ran on Linux, rescanning the timezone files in a thread that called gettime would probably violate realtime constraints and our quality assurance app would eject valid products because of unexpected latency due to unforseen harddisk access.

Do you even understand how this works on linux? 'localtime' stats the file to see if the timestamp has changed, only then does it reload from the file. It doesn't read the file every time. If you're timing things, you are doing it wrong. If it's more important to you to be fast than correct, then you can weigh up the risks yourself, just don't force it upon all the users of the freepascal compiler.

I appear to be wasting my time if two rtl developers can even consider that giving possible erroneous results is an option.

Henry

Reply by email

Marco van de Voort
to Henry Vermaak

In our previous episode, Henry Vermaak said:

Show quoted text 6 lines
>> saving time changes? ?If they don't use shared memory for this, I'd >> wager that it's just as slow as libc localtime. > > I doubt Windows has a _file_ based concept of timezone. Explain?

It has an in memory concept of timezone, and doesn't have to poll files on the filesystem for timezone changes.

Show quoted text 9 lines
> And I agree with him (if only because my business app would break horribly. > Worse, if my business app ran on Linux, rescanning the timezone files in > a thread that called gettime would probably violate realtime constraints and > our quality assurance app would eject valid products because of unexpected > latency due to unforseen harddisk access. Do you even understand how this works on linux? 'localtime' stats the file to see if the timestamp has changed, only then does it reload from the file.

That would be the primitive way, inotify would make more sense though might not work universally on all filesystems.

But do you agree that _when_ it happens, the directory is rescanned in the same thread as the gettime() call, outside programmer's control? And that that breaks code for people that don't expect the runtime to access the harddisk without they explicitely solicating that? (e.g. to preserve some realtime behaviour(*))?

Because that was my point.

It doesn't read the file every time. If you're timing things, you are doing it wrong.

Explain.

If it's more important to you to be fast than correct, then you can weigh up the risks yourself, just don't force it upon all the users of the freepascal compiler.

That is an symmetrical argument. I could argue exactly the same about correctness. I don't need it, so please don't force it on all users.

The fact remains that the original Windows call has *both* aspects.

I appear to be wasting my time if two rtl developers can even consider that giving possible erroneous results is an option.

No. They are encouraging you to see beyond the immediate need. There is a reason why plugin units are used so much for these kinds of issues, to not hardcode an implementation that is satisfactory for only 90% of the users.

Reply by email

Jonas Maebe
to Marco van de Voort
Marco van de Voort wrote
That is an symmetrical argument. I could argue exactly the same about correctness. I don't need it, so please don't force it on all users.

I suppose you meant that what is correct and what not depends on the specification, rather than than that correctness is an optional design goal. It is possible to specify that the now() call from sysutils is only guaranteed to be correct relative to the timezone settings when the program was started. This would however be Delphi-incompatible (performance differences between Delphi and FPC implementations exist in many more places than just this one, so I'm mainly considering the functionality aspect), and imho if you need "real time behaviour" then using high level routines from the sysutils unit is the wrong way to go since there are no implementation guarantees whatsoever there.

Generally, if you need to time things at a high precision level with minimal overhead, then timezones etc don't matter. In fact, then you probably want to ignore them since the timing deltas matter rather than whatever the user perceives as "how late is it now". Timezone or daylight saving shifts will completely mess up any timing in such cases. If you are in a case where you do want a high precision timer that is only adjusted once to the system's timezone (namely when the program was started), then I think it is quite reasonable if the RTL does not provide such functionality in a standard call.

Jonas

Reply by email

Felipe Monteiro de Carvalho
to Jonas Maebe

One more idea: Do we already have something like NowUTC ? Just like Now, but in UTC.

Maybe that would be something interresting to add. Programs that want to measure time differences could use it instead of hacking Now. NowUTC seams to be much more appropriate for time differences then Now, and it would be extremely fast everywhere.

Felipe Monteiro de Carvalho

Reply by email

Mark Morgan Lloyd
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 7 lines
One more idea: Do we already have something like NowUTC ? Just like Now, but in UTC. Maybe that would be something interresting to add. Programs that want to measure time differences could use it instead of hacking Now. NowUTC seams to be much more appropriate for time differences then Now, and it would be extremely fast everywhere.

Agreed. Basically, the idea of "time" that underpins timers, which should fire correctly irrespective of any DST transitions.

But even in this case, what should happen if the user (or NTP) explicitly changes the system clock? Ultimately, what matters for relative timing is ticks-since-boot.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Graeme Geldenhuys
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote
But even in this case, what should happen if the user (or NTP) explicitly changes the system clock?

NTP client service doesn't explicitly change the system time in one shot. This could cause all kinds of problems. Instead they slow down or speed up the system clock over a set period until it matches the correct time from a NTP server. Thus no other services with have weird (out of sync) timestamps. At least, this is how Linux's NTPD client service works.

eg:

http://wiki.dovecot.org/TimeMovedBackwards

Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Marco van de Voort
to Jonas Maebe: I suppose you meant that what is correct and what not depends on the specification,…

In our previous episode, Jonas Maebe said:

Show quoted text 7 lines
> That is an symmetrical argument. I could argue exactly the same about > correctness. I don't need it, so please don't force it on all users. I suppose you meant that what is correct and what not depends on the specification, rather than than that correctness is an optional design goal.

Well, one could argue that the specification is being delphi compatible here, and point at the large codebases that rely on this.

But let's not go there, that was not the point I was trying to make.

Show quoted text 6 lines
It is possible to specify that the now() call from sysutils is only guaranteed to be correct relative to the timezone settings when the program was started. This would however be Delphi-incompatible (performance differences between Delphi and FPC implementations exist in many more places than just this one, so I'm mainly considering the functionality aspect), and imho if you need "real time behaviour" then

I love the quotes by the way :-) Realtime is a subjective matter.

using high level routines from the sysutils unit is the wrong way to go since there are no implementation guarantees whatsoever there.

It was a use case example. I could replace them within 5 minutes if I wanted to, _if_ I knew what was going on though.

The point was just some encouragement to look further than the immediate need though, and keep the time call relatively cheap. That doesn't exclude being correct, it just means a more elaborate implementation.

Each such issue individually doesn't matter much. Together they are an horrible dragon that porters have to fight.

Generally, if you need to time things at a high precision level with minimal overhead, then timezones etc don't matter.0

They are not really used to time execution times btw, but more to rate limit certain events to xx per second. The events can die out for hours however (if the machine is stopping for maintenance) Strictly speaking that carries a monotonous time requirement, but these are of the kind where a trip once an year doesn't matter.

But harddisk latency can easily be in the half a second to second magnitude (and then I don't even count spindowns, and am I accessing directories that I continously access).

In Delphi, for timing of short intervals, typically queryperformance counter
+ family is used, but iirc these can't measure longer intervals and are very imprecise the too (since the CPU frequency might change)

If you are in a case where you do want a high precision timer that is only adjusted once to the system's timezone (namely when the program was started), then I think it is quite reasonable if the RTL does not provide such functionality in a standard call.

Not entirely related to the discussion, but I don't see is a reason why libc has monotonous time functions.

Anyway, there are other reasons to go for a plugin style for this, namely that you can't predict what libs a certain *nix might need to effectively monitor the mutation of files. (e.g. that allows to do it in a thread)

But to avoid the chaos of umpteen plugin units, we should maybe just define a certain plugin unit (say "cdelphi" or so) that includes all plugins you typically need for bigger apps (cwstring,clocale,cthreads,cwhatevertime), and see if we can convince Lazarus to use it. It would save both projects quite some support issues.

Reply by email

Tomas Hajny
to Marco van de Voort

On Wed, November 2, 2011 09:56, Marco van de Voort wrote: .
.

Show quoted text 10 lines
Anyway, there are other reasons to go for a plugin style for this, namely that you can't predict what libs a certain *nix might need to effectively monitor the mutation of files. (e.g. that allows to do it in a thread) But to avoid the chaos of umpteen plugin units, we should maybe just define a certain plugin unit (say "cdelphi" or so) that includes all plugins you typically need for bigger apps (cwstring,clocale,cthreads,cwhatevertime), and see if we can convince Lazarus to use it. It would save both projects quite some support issues.

I don't get the relation of plugins to the original problem. You don't need any libc (c*) to solve that problem, and using libc wouldn't change the fact that the possibly required reinitialization might take some time (within the EpochToLocal call) according to information about the libc behaviour which appeared in some other messages of this thread because libc apparently doesn't use perform the checks and reinitialization asynchronously either (I can imagine good reasons for this being the case like that it would be a completely unnecessary overhead for many applications).

Tomas

Reply by email

Marco van de Voort
to Tomas Hajny

In our previous episode, Tomas Hajny said:

I don't get the relation of plugins to the original problem. You don't need any libc (c*) to solve that problem,

It does if the solution to monitor filesystem change does, or if you need or want to use a thread for that. So it is not for the time functionality.

Reply by email

Henry Vermaak
to Marco van de Voort: In our previous episode, Henry Vermaak said: It has an in memory concept of timezone, and…
Marco van de Voort wrote 5 lines
But do you agree that _when_ it happens, the directory is rescanned in the same thread as the gettime() call, outside programmer's control? And that that breaks code for people that don't expect the runtime to access the harddisk without they explicitely solicating that? (e.g. to preserve some realtime behaviour(*))?

(I presume that the * here means "insert your definition here"). This is exactly your problem, _assuming_ that you can get any realtime behaviour out of this call. If you need that, use performance counters.

Show quoted text 6 lines
> If it's more important to you to be > fast than correct, then you can weigh up the risks yourself, just > don't force it upon all the users of the freepascal compiler. That is an symmetrical argument. I could argue exactly the same about correctness. I don't need it, so please don't force it on all users.

No, it's not balanced. Most users would not like to go out of their way to make a broken implementation correct. Most users are willing, however, to go out of their way to make something perform better if they need it.

Henry

Reply by email

Sven Barth
to Henry Vermaak: Explain? Do you even understand how this works on linux? 'localtime' stats the file to…
Henry Vermaak wrote 11 lines
On 1 November 2011 21:07, Marco van de Voort wrote: > In our previous episode, Henry Vermaak said: >> Also, how cheap is this on Windows? Presumably they will also have to >> deal with potential system services running while updates fix daylight >> saving time changes? If they don't use shared memory for this, I'd >> wager that it's just as slow as libc localtime. > > I doubt Windows has a _file_ based concept of timezone. Explain?

See my mail where I explain Windows' implementation.

Regards,
Sven

Reply by email

Felipe Monteiro de Carvalho
to Marco van de Voort: In our previous episode, Jonas Maebe said: Well, one could argue that the specification…
Marco van de Voort wrote
Not entirely related to the discussion, but I don't see is a reason why libc has monotonous time functions.

And I think we should have too:

Now() -> Like Michael proposed. Implemented with precision, but with a switch for existing code bases to hack it into being fast.

And for new projects 2 new methods:

NowUTC() -> Current time in UTC
GetMonotonousTimeCount() -> Gives the number of microseconds since an unspecified initial time which is totally fixed. This one people should use for more precision timing.

Felipe Monteiro de Carvalho

Reply by email

Jonas Maebe
to Marco van de Voort: In our previous episode, Jonas Maebe said: Well, one could argue that the specification…

Marco van de Voort wrote on Wed, 02 Nov 2011:

The point was just some encouragement to look further than the immediate need though, and keep the time call relatively cheap. That doesn't exclude being correct, it just means a more elaborate implementation.

I do not think that reporting the time correctly taking into account the current time zone and daylight savings time is a function that needs to be treated as performance-critical.

Show quoted text 5 lines
They are not really used to time execution times btw, but more to rate limit certain events to xx per second. The events can die out for hours however (if the machine is stopping for maintenance) Strictly speaking that carries a monotonous time requirement, but these are of the kind where a trip once an year doesn't matter.

Twice a year. Anyway: a function that reports the local time is simply the wrong tool for the job if you need a "mostly" monotonic timer that you can query at a high frequency. It may work (and apparently it does for you), but instating a plugin architecture just to be able to keep using it for that purpose is the wrong approach as far as I am concerned.

And even if it is eventually transformed into a pluggable API, fixing it now does not require this plug-in architecture to exist, nor does fixing it make it harder to transform it into a pluggable API afterwards.

But harddisk latency can easily be in the half a second to second magnitude (and then I don't even count spindowns, and am I accessing directories that I continously access).

If you are stat'ing that file for changes all the time, either the result will be cached or the hard drive won't spin down. And stat'ing a file will not take half a second when done repeatedly.

In Delphi, for timing of short intervals, typically queryperformance counter + family is used, but iirc these can't measure longer intervals and are very imprecise the too (since the CPU frequency might change)

For longer intervals you can use gettickcount/gettickcount64 on Windows and fpgettimeofday on Unix. I'm not opposed at all to add some kind of extra "return a monotonic clock value" function somewhere.

Show quoted text 7 lines
In our previous episode, Jonas Maebe said: > If you are in a case where you do want a high precision timer that is only > adjusted once to the system's timezone (namely when the program was > started), then I think it is quite reasonable if the RTL does not provide > such functionality in a standard call. Not entirely related to the discussion,

It is related as far as I am concerned, because the above is how Now() currently works on Unix and as far as I understand, you don't want it to be fixed using a straightforward stat/update check because that may reduce the performance/rate properties of that call.

but I don't see is a reason why libc has monotonous time functions.

Yes, but they are presumably not based on timezone information because that inherently defeats the monotonic property.

Jonas

---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.

Reply by email

Jonas Maebe
to Felipe Monteiro de Carvalho: And I think we should have too: Now() -> Like Michael proposed. Implemented with…

Felipe Monteiro de Carvalho wrote on Wed, 02 Nov 2011:

Now() -> Like Michael proposed. Implemented with precision, but with a switch for existing code bases to hack it into being fast.

I don't think it is appropriate to add a hack to the RTL for a case like this. No major incompatibility with existing code is being introduced, nor is it some exotic adjustment to make behaviour compatible with strange Windows-specific functionality.

Jonas

---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.

Reply by email

Unknown author
to Jonas Maebe: Marco van de Voort wrote on Wed, 02 Nov 2011: I do not think that reporting the time…
Jonas Maebe wrote 9 lines
Marco van de Voort wrote on Wed, 02 Nov 2011: > The point was just some encouragement to look further than the immediate > need though, and keep the time call relatively cheap. That doesn't exclude > being correct, it just means a more elaborate implementation. I do not think that reporting the time correctly taking into account the current time zone and daylight savings time is a function that needs to be treated as performance-critical.

Under some (not so uncommon) circumstances it is, e.g. for logging facilities. Our own eventlog facility would suffer from this.

Show quoted text 7 lines
> But harddisk latency can easily be in the half a second to second magnitude > (and then I don't even count spindowns, and am I accessing directories that > I continously access). If you are stat'ing that file for changes all the time, either the result will be cached or the hard drive won't spin down. And stat'ing a file will not take half a second when done repeatedly.

I tested this yesterday, using the following sequence:

fpGettimeOfDay();
if UseStat then
   fpStat('/etc/timezone');
fpGetTimeOfDay();

The sequence becomes 3 times slower when UseStat is true.

Michael.

Reply by email

Marco van de Voort
to Jonas Maebe: Marco van de Voort wrote on Wed, 02 Nov 2011: I do not think that reporting the time…

In our previous episode, Jonas Maebe said:

Show quoted text 6 lines
Anyway: a function that reports the local time is simply the wrong tool for the job if you need a "mostly" monotonic timer that you can query at a high frequency. It may work (and apparently it does for you), but instating a plugin architecture just to be able to keep using it for that purpose is the wrong approach as far as I am concerned.

True, but as said a very common abuse. Oh, and btw, I forgot, I update a clock on my app once a second too (which is not that strange for systems that run fullscreen).

Note again that my apps are not in FPC, and could be easily changed. They are just meant as illustrations of very common use (and thus of the number of support issues you can expect when sb after a lot of debugging finds out that the system reacts differently, *JUST* like the issue that initiated this thread)

And even if it is eventually transformed into a pluggable API, fixing it now does not require this plug-in architecture to exist, nor does fixing it make it harder to transform it into a pluggable API afterwards.

That kind of quick and dirty mentality and pooh,poohing away sideeffects (like a noticably slower gettime) without a way to override it is exactly what I'm afraid of.

Show quoted text 6 lines
> But harddisk latency can easily be in the half a second to second magnitude > (and then I don't even count spindowns, and am I accessing directories that > I continously access). If you are stat'ing that file for changes all the time, either the result will be cached or the hard drive won't spin down.

So this would make FPC apps that use gettime a lot not very eco friendly :-)

And stat'ing a file will not take half a second when done repeatedly.

On average or _always_. Big difference. I'm talking about worst case times, not average times.

Show quoted text 7 lines
> In Delphi, for timing of short intervals, typically queryperformance counter > + family is used, but iirc these can't measure longer intervals and are very > imprecise the too (since the CPU frequency might change) For longer intervals you can use gettickcount/gettickcount64 on Windows and fpgettimeofday on Unix. I'm not opposed at all to add some kind of extra "return a monotonic clock value" function somewhere.

(I'm not sure btw if monotonic is the right term for getticks like solutions. Afaik it is used more for clocks that never go back, e.g. that handle setting clock back by running slower for a while)

Show quoted text 12 lines
> In our previous episode, Jonas Maebe said: >> If you are in a case where you do want a high precision timer that is only >> adjusted once to the system's timezone (namely when the program was >> started), then I think it is quite reasonable if the RTL does not provide >> such functionality in a standard call. > > Not entirely related to the discussion, It is related as far as I am concerned, because the above is how Now() currently works on Unix and as far as I understand, you don't want it to be fixed using a straightforward stat/update check because that may reduce the performance/rate properties of that call.

I meant that wrt compatibility, since such solution requires an audit of all gettime use, and worse awareness. On the other hand I'm not as insensitive to the "time should be correct" arguments as people think I am.

Such code change solution would be like having said "monitor timezone info yourself and update unixutils.tzsecond if you see changes" to Zeljko. The trouble when porting is that you must first find the problem before you can fix it. Argueing that the fix is easy is futile in such case, since diagnosing the problem out is nearly always magnitudes more work (and trouble)

Minimizing that is one of the things compatibility is about. More importantly, the various requirements don't bite eachother, except that a proper solution might require some more functionality in the core set (hence plugin route).

Show quoted text 5 lines
> but I don't see > is a reason why libc has monotonous time functions. Yes, but they are presumably not based on timezone information because that inherently defeats the monotonic property.

I'm not sure. (see "monotonic" remarks above).

Reply by email

Mark Morgan Lloyd
to Felipe Monteiro de Carvalho: And I think we should have too: Now() -> Like Michael proposed. Implemented with…
Felipe Monteiro de Carvalho wrote 15 lines
On Wed, Nov 2, 2011 at 9:56 AM, Marco van de Voort wrote: > Not entirely related to the discussion, but I don't see > is a reason why libc has monotonous time functions. And I think we should have too: Now() -> Like Michael proposed. Implemented with precision, but with a switch for existing code bases to hack it into being fast. And for new projects 2 new methods: NowUTC() -> Current time in UTC GetMonotonousTimeCount() -> Gives the number of microseconds since an unspecified initial time which is totally fixed. This one people should use for more precision timing.

Without meaning to cause offense, I think that should be monotonic (i.e. it is guaranteed to never decrement).

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

zeljko
to Unknown author: Under some (not so uncommon) circumstances it is, e.g. for logging facilities. Our own…
Show quoted text 27 lines
On Wed, 2 Nov 2011, Jonas Maebe wrote: > Marco van de Voort wrote on Wed, 02 Nov 2011: >> The point was just some encouragement to look further than the immediate >> need though, and keep the time call relatively cheap. That doesn't >> exclude being correct, it just means a more elaborate implementation. > > I do not think that reporting the time correctly taking into account the > current time zone and daylight savings time is a function that needs to > be treated as performance-critical. Under some (not so uncommon) circumstances it is, e.g. for logging facilities. Our own eventlog facility would suffer from this. >> But harddisk latency can easily be in the half a second to second >> magnitude (and then I don't even count spindowns, and am I accessing >> directories that I continously access). > > If you are stat'ing that file for changes all the time, either the result > will be cached or the hard drive won't spin down. And stat'ing a file > will not take half a second when done repeatedly. I tested this yesterday, using the following sequence: fpGettimeOfDay(); if UseStat then fpStat('/etc/timezone'); fpGetTimeOfDay();

Please see results about Now() and something that I've mentioned about deprecitation of gettimeofday().According to this test, current fpgettimeofday() is crap when compared with clock_gettime() (kernel) or libc calls (I've copied scenario from kylix sysutils).

*Kernel clock_gettime() NowReal() with 10000000 calls = 4870 ms **Libc gettimeofday()+localtime_r() with 10000000 calls = 5085 ms ***RTL Now() with 10000000 calls = 7659 ms ?!?!?!? Slowest !?!?

Simple program is attached. Maybe I've added something wrong, but you can correct me if I'm wrong.

zeljko

Reply by email

Henry Vermaak
to zeljko
zeljko wrote 13 lines
Please see results about Now() and something that I've mentioned about deprecitation of gettimeofday().According to this test, current fpgettimeofday() is crap when compared with clock_gettime() (kernel) or libc calls (I've copied scenario from kylix sysutils). *Kernel clock_gettime() NowReal() with 10000000 calls = 4870 ms **Libc gettimeofday()+localtime_r() with 10000000 calls = 5085 ms ***RTL Now() with 10000000 calls = 7659 ms ?!?!?!? Slowest !?!?

So fpc rtl is slower even _without_ the stat call in localtime.

Henry

Reply by email

Unknown author
to zeljko: Please see results about Now() and something that I've mentioned about deprecitation of…
zeljko wrote 35 lines
On Wednesday 02 of November 2011 11:23:10 wrote: > On Wed, 2 Nov 2011, Jonas Maebe wrote: >> Marco van de Voort wrote on Wed, 02 Nov 2011: >>> The point was just some encouragement to look further than the immediate >>> need though, and keep the time call relatively cheap. That doesn't >>> exclude being correct, it just means a more elaborate implementation. >> >> I do not think that reporting the time correctly taking into account the >> current time zone and daylight savings time is a function that needs to >> be treated as performance-critical. > > Under some (not so uncommon) circumstances it is, e.g. for logging > facilities. Our own eventlog facility would suffer from this. > >>> But harddisk latency can easily be in the half a second to second >>> magnitude (and then I don't even count spindowns, and am I accessing >>> directories that I continously access). >> >> If you are stat'ing that file for changes all the time, either the result >> will be cached or the hard drive won't spin down. And stat'ing a file >> will not take half a second when done repeatedly. > > I tested this yesterday, using the following sequence: > > fpGettimeOfDay(); > if UseStat then > fpStat('/etc/timezone'); > fpGetTimeOfDay(); Please see results about Now() and something that I've mentioned about deprecitation of gettimeofday().According to this test, current fpgettimeofday() is crap when compared with clock_gettime() (kernel) or libc calls (I've copied scenario from kylix sysutils). *Kernel clock_gettime() NowReal() with 10000000 calls = 4870 ms

You must do also a localtime_r after this call.
clock_gettime returns the same time as gettimeofday.

Michael.

Reply by email

Unknown author
to Unknown author
Show quoted text 41 lines
On Wed, 2 Nov 2011, zeljko wrote: > On Wednesday 02 of November 2011 11:23:10 wrote: >> On Wed, 2 Nov 2011, Jonas Maebe wrote: >>> Marco van de Voort wrote on Wed, 02 Nov 2011: >>>> The point was just some encouragement to look further than the immediate >>>> need though, and keep the time call relatively cheap. That doesn't >>>> exclude being correct, it just means a more elaborate implementation. >>> >>> I do not think that reporting the time correctly taking into account the >>> current time zone and daylight savings time is a function that needs to >>> be treated as performance-critical. >> >> Under some (not so uncommon) circumstances it is, e.g. for logging >> facilities. Our own eventlog facility would suffer from this. >> >>>> But harddisk latency can easily be in the half a second to second >>>> magnitude (and then I don't even count spindowns, and am I accessing >>>> directories that I continously access). >>> >>> If you are stat'ing that file for changes all the time, either the result >>> will be cached or the hard drive won't spin down. And stat'ing a file >>> will not take half a second when done repeatedly. >> >> I tested this yesterday, using the following sequence: >> >> fpGettimeOfDay(); >> if UseStat then >> fpStat('/etc/timezone'); >> fpGetTimeOfDay(); > > Please see results about Now() and something that I've mentioned about > deprecitation of gettimeofday().According to this test, current > fpgettimeofday() is crap when compared with clock_gettime() (kernel) or > libc > calls (I've copied scenario from kylix sysutils). > > *Kernel clock_gettime() NowReal() with 10000000 calls = 4870 ms

and anyway:

fsb: >fpc /home/michael/unixclocks.lpr
Fatal: Can't find unit Libc used by unixclocks
Fatal: Compilation aborted
Error: /usr/local/bin/ppcx64 returned an error exitcode (normal if you did not specify a source file to be compiled)

Michael.

Reply by email

zeljko
to Unknown author
On Wed, 2 Nov 2011, wrote: > On Wed, 2 Nov 2011, zeljko wrote: >> On Wednesday 02 of November 2011 11:23:10
Show quoted text 46 lines
>>> On Wed, 2 Nov 2011, Jonas Maebe wrote: >>>> Marco van de Voort wrote on Wed, 02 Nov 2011: >>>>> The point was just some encouragement to look further than the >>>>> immediate need though, and keep the time call relatively cheap. That >>>>> doesn't exclude being correct, it just means a more elaborate >>>>> implementation. >>>> >>>> I do not think that reporting the time correctly taking into account >>>> the current time zone and daylight savings time is a function that >>>> needs to be treated as performance-critical. >>> >>> Under some (not so uncommon) circumstances it is, e.g. for logging >>> facilities. Our own eventlog facility would suffer from this. >>> >>>>> But harddisk latency can easily be in the half a second to second >>>>> magnitude (and then I don't even count spindowns, and am I accessing >>>>> directories that I continously access). >>>> >>>> If you are stat'ing that file for changes all the time, either the >>>> result will be cached or the hard drive won't spin down. And stat'ing >>>> a file will not take half a second when done repeatedly. >>> >>> I tested this yesterday, using the following sequence: >>> >>> fpGettimeOfDay(); >>> if UseStat then >>> >>> fpStat('/etc/timezone'); >>> >>> fpGetTimeOfDay(); >> >> Please see results about Now() and something that I've mentioned about >> deprecitation of gettimeofday().According to this test, current >> fpgettimeofday() is crap when compared with clock_gettime() (kernel) or >> libc >> calls (I've copied scenario from kylix sysutils). >> >> *Kernel clock_gettime() NowReal() with 10000000 calls = 4870 ms and anyway: fsb: >fpc /home/michael/unixclocks.lpr Fatal: Can't find unit Libc used by unixclocks Fatal: Compilation aborted Error: /usr/local/bin/ppcx64 returned an error exitcode (normal if you did not specify a source file to be compiled)

Then just remove code which uses NowLibc() , and use clock_gettime() ... if Libc isn't available .... maybe it should be libc ... dunno.

zeljko

Show quoted text 5 lines
Michael. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Unknown author
zeljko wrote 7 lines
On Wednesday 02 of November 2011 14:53:05 you wrote: > You must do also a localtime_r after this call. > clock_gettime returns the same time as gettimeofday. But point IS in comparing clock_gettime() vs. gettimeofday() which is used by fpgettimeofday(). I don't see localtime_r() calls in current RTL Now().

Ok.

It turns out that Now() was doing a fpGettimeofday (for time) and a fptime (for date), which is of course really stupid.

I improved that (it does one call only). So, new stats, 64-bit, no optimizations:

sb: >./unixclocks
RTL Now() with 10000000 calls = 3698 ms
Kernel clock_gettime() NowReal() with 10000000 calls = 6564 ms

Revision 19572.

The time is now less than the Libc time you posted (5085ms).

I can't test the libc version, but if you'd care to re-test using the above revision of unix/sysutils.pp, and post the results, I'd be grateful.

Michael.

Reply by email

zeljko
to Unknown author
you wrote 13 lines
On Wed, 2 Nov 2011, zeljko wrote: > On Wednesday 02 of November 2011 14:53:05 you wrote: >> You must do also a localtime_r after this call. >> clock_gettime returns the same time as gettimeofday. > > But point IS in comparing clock_gettime() vs. gettimeofday() which is > used by fpgettimeofday(). I don't see localtime_r() calls in current RTL > Now(). Ok. It turns out that Now() was doing a fpGettimeofday (for time) and a fptime (for date), which is of course really stupid.

Yes, I saw that after posted example.

Show quoted text 11 lines
I improved that (it does one call only). So, new stats, 64-bit, no optimizations: sb: >./unixclocks RTL Now() with 10000000 calls = 3698 ms Kernel clock_gettime() NowReal() with 10000000 calls = 6564 ms Revision 19572. The time is now less than the Libc time you posted (5085ms).

I don't care about libc timing, but why clock_gettime() is so slower now ? It is called only once in my example. Are you sufre that RTL now() returns correct date/time ?

I can't test the libc version, but if you'd care to re-test using the above revision of unix/sysutils.pp, and post the results, I'd be grateful.

Sorry, but I don't want to use 2.7.1 until it's useable.

zeljko

Reply by email

zeljko
to Unknown author: Ok. It turns out that Now() was doing a fpGettimeofday (for time) and a fptime (for…

On Wednesday 02 of November 2011 15:47:46 wrote:
Ok, let's finish this thread.

1.Now() works as it is - it's even twice faster now since extra fptime call is avoided (so an + from this thread) :)

2.Programmer (me in this example) need something to re-read timezone, so Now() can adjust time - please merge your ReReadTimeZone() to 2.4.5 and 2.6.0. Also, documentation should be updated with this routine. If somebody needs accurate time in his timezone, let him call ReReadTimeZone() whenever. eg. I'll call it every day at some time after 03:00 so who cares ...

3.Issue can be resolved in that case, Now() behaviour isn't changed, it's only faster.

4.If kernel clock_gettime() is really twice slower than gettimeodday, then use gettimeofday until it's completely removed from some future kernel, if not , change it to use clock_gettime(CLOCK_REALTIME).

zeljko

Reply by email

Unknown author
to zeljko: Yes, I saw that after posted example. I don't care about libc timing, but why…
zeljko wrote 32 lines
On Wednesday 02 of November 2011 15:47:46 you wrote: > On Wed, 2 Nov 2011, zeljko wrote: >> On Wednesday 02 of November 2011 14:53:05 you wrote: >>> You must do also a localtime_r after this call. >>> clock_gettime returns the same time as gettimeofday. >> >> But point IS in comparing clock_gettime() vs. gettimeofday() which is >> used by fpgettimeofday(). I don't see localtime_r() calls in current RTL >> Now(). > > Ok. > > It turns out that Now() was doing a fpGettimeofday (for time) and a fptime > (for date), which is of course really stupid. Yes, I saw that after posted example. > > I improved that (it does one call only). So, new stats, 64-bit, no > optimizations: > > sb: >./unixclocks > RTL Now() with 10000000 calls = 3698 ms > Kernel clock_gettime() NowReal() with 10000000 calls = 6564 ms > > Revision 19572. > > The time is now less than the Libc time you posted (5085ms). I don't care about libc timing, but why clock_gettime() is so slower now ? It is called only once in my example. Are you sufre that RTL now() returns correct date/time ?

Yes. Of course I tested that first :-)

I assume your version is slower because you call epochtolocaltime twice, for instance.

If I remove the second call (it's not needed anyway) then

RTL Now() with 100000 calls = 2337 ms
Kernel clock_gettime() NowReal() with 100000 calls = 2344 ms

> I can't test the libc version, but if you'd care to re-test using the above > revision of unix/sysutils.pp, and post the results, I'd be grateful. Sorry, but I don't want to use 2.7.1 until it's useable.

I attached the changed file.

Michael.

Reply by email

zeljko
to Unknown author
you wrote 50 lines
On Wed, 2 Nov 2011, zeljko wrote: > On Wednesday 02 of November 2011 15:47:46 you wrote: >> On Wed, 2 Nov 2011, zeljko wrote: >>> On Wednesday 02 of November 2011 14:53:05 you wrote: >>>> You must do also a localtime_r after this call. >>>> clock_gettime returns the same time as gettimeofday. >>> >>> But point IS in comparing clock_gettime() vs. gettimeofday() which is >>> used by fpgettimeofday(). I don't see localtime_r() calls in current >>> RTL Now(). >> >> Ok. >> >> It turns out that Now() was doing a fpGettimeofday (for time) and a >> fptime (for date), which is of course really stupid. > > Yes, I saw that after posted example. > >> I improved that (it does one call only). So, new stats, 64-bit, no >> optimizations: >> >> sb: >./unixclocks >> RTL Now() with 10000000 calls = 3698 ms >> Kernel clock_gettime() NowReal() with 10000000 calls = 6564 ms >> >> Revision 19572. >> >> The time is now less than the Libc time you posted (5085ms). > > I don't care about libc timing, but why clock_gettime() is so slower now > ? It is called only once in my example. Are you sufre that RTL now() > returns correct date/time ? Yes. Of course I tested that first :-) I assume your version is slower because you call epochtolocaltime twice, for instance. If I remove the second call (it's not needed anyway) then RTL Now() with 100000 calls = 2337 ms Kernel clock_gettime() NowReal() with 100000 calls = 2344 ms >> I can't test the libc version, but if you'd care to re-test using the >> above revision of unix/sysutils.pp, and post the results, I'd be >> grateful. > > Sorry, but I don't want to use 2.7.1 until it's useable. I attached the changed file.

No need to test libc version in this case it's timing will be slower anyway because of 2 calls a) gettimeofday() localtime_r() ... so it's not important at all.
That sysutils.pp now looks pretty clean, and again: *I hope* that this changes will be merged to 2.4.5 and 2.6.0 :) ... and of course ReReadTimeZone() (or what was that name...) as solution for issue ... http://bugs.freepascal.org/view.php?id=20604

zeljko

Reply by email

Unknown author
to zeljko: Ok, let's finish this thread. 1.Now() works as it is - it's even twice faster now since…
zeljko wrote 12 lines
On Wednesday 02 of November 2011 15:47:46 wrote: Ok, let's finish this thread. 1.Now() works as it is - it's even twice faster now since extra fptime call is avoided (so an + from this thread) :) 2.Programmer (me in this example) need something to re-read timezone, so Now() can adjust time - please merge your ReReadTimeZone() to 2.4.5 and 2.6.0. Also, documentation should be updated with this routine. If somebody needs accurate time in his timezone, let him call ReReadTimeZone() whenever. eg. I'll call it every day at some time after 03:00 so who cares ...

The call will not be merged. Instead, you can just add

  ReadTimezoneFile(GetTimezoneFile);
  GetLocalTimezone(fptime);

to your code (and add units 'unix' and 'baseunix'). This code does all that is needed, you need not even upgrade FPC for it because these calls exist in 2.4, 2.6 and are documented.

3.Issue can be resolved in that case, Now() behaviour isn't changed, it's only faster.

You mean the bug tracker issue ?

4.If kernel clock_gettime() is really twice slower than gettimeodday, then use gettimeofday until it's completely removed from some future kernel, if not , change it to use clock_gettime(CLOCK_REALTIME).

When we know that BSD and Darwin (and all other unix-like OSes) support this call, yes, then we can do that.

Michael.

Reply by email

Thaddy
to Marco van de Voort: In our previous episode, Jonas Maebe said: True, but as said a very common abuse. Oh, and…

Gentlemen, gentlemen,

Stop this.

Every proper software clock == UTC, not local time. The local time should always be on read time, on the fly.

Thaddy

Marco van de Voort wrote 81 lines
In our previous episode, Jonas Maebe said: > Anyway: a function that reports the local time is simply > the wrong tool for the job if you need a "mostly" monotonic timer that > you can query at a high frequency. It may work (and apparently it does > for you), but instating a plugin architecture just to be able to keep > using it for that purpose is the wrong approach as far as I am > concerned. True, but as said a very common abuse. Oh, and btw, I forgot, I update a clock on my app once a second too (which is not that strange for systems that run fullscreen). Note again that my apps are not in FPC, and could be easily changed. They are just meant as illustrations of very common use (and thus of the number of support issues you can expect when sb after a lot of debugging finds out that the system reacts differently, *JUST* like the issue that initiated this thread) > And even if it is eventually transformed into a pluggable API, fixing > it now does not require this plug-in architecture to exist, nor does > fixing it make it harder to transform it into a pluggable API > afterwards. That kind of quick and dirty mentality and pooh,poohing away sideeffects (like a noticably slower gettime) without a way to override it is exactly what I'm afraid of. >> But harddisk latency can easily be in the half a second to second magnitude >> (and then I don't even count spindowns, and am I accessing directories that >> I continously access). > If you are stat'ing that file for changes all the time, either the > result will be cached or the hard drive won't spin down. So this would make FPC apps that use gettime a lot not very eco friendly :-) > And stat'ing > a file will not take half a second when done repeatedly. On average or _always_. Big difference. I'm talking about worst case times, not average times. >> In Delphi, for timing of short intervals, typically queryperformance counter >> + family is used, but iirc these can't measure longer intervals and are very >> imprecise the too (since the CPU frequency might change) > For longer intervals you can use gettickcount/gettickcount64 on > Windows and fpgettimeofday on Unix. I'm not opposed at all to add some > kind of extra "return a monotonic clock value" function somewhere. (I'm not sure btw if monotonic is the right term for getticks like solutions. Afaik it is used more for clocks that never go back, e.g. that handle setting clock back by running slower for a while) >> In our previous episode, Jonas Maebe said: >>> If you are in a case where you do want a high precision timer that is only >>> adjusted once to the system's timezone (namely when the program was >>> started), then I think it is quite reasonable if the RTL does not provide >>> such functionality in a standard call. >> Not entirely related to the discussion, > It is related as far as I am concerned, because the above is how Now() > currently works on Unix and as far as I understand, you don't want it > to be fixed using a straightforward stat/update check because that may > reduce the performance/rate properties of that call. I meant that wrt compatibility, since such solution requires an audit of all gettime use, and worse awareness. On the other hand I'm not as insensitive to the "time should be correct" arguments as people think I am. Such code change solution would be like having said "monitor timezone info yourself and update unixutils.tzsecond if you see changes" to Zeljko. The trouble when porting is that you must first find the problem before you can fix it. Argueing that the fix is easy is futile in such case, since diagnosing the problem out is nearly always magnitudes more work (and trouble) Minimizing that is one of the things compatibility is about. More importantly, the various requirements don't bite eachother, except that a proper solution might require some more functionality in the core set (hence plugin route). >> but I don't see >> is a reason why libc has monotonous time functions. > Yes, but they are presumably not based on timezone information because > that inherently defeats the monotonic property. I'm not sure. (see "monotonic" remarks above). _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Jonas Maebe
to Marco van de Voort: In our previous episode, Jonas Maebe said: True, but as said a very common abuse. Oh, and…

Marco van de Voort wrote on Wed, 02 Nov 2011:

Show quoted text 10 lines
In our previous episode, Jonas Maebe said: > Anyway: a function that reports the local time is simply > the wrong tool for the job if you need a "mostly" monotonic timer that > you can query at a high frequency. It may work (and apparently it does > for you), but instating a plugin architecture just to be able to keep > using it for that purpose is the wrong approach as far as I am > concerned. True, but as said a very common abuse.

Fine, and in most cases people probably won't notice the difference of an added fpstat call.

Oh, and btw, I forgot, I update a clock on my app once a second too (which is not that strange for systems that run fullscreen).

The only use of displaying this is if it actually matches the real time rather than something that may or may not match it (and matching it most of the time is the best way to cause lots of irritation when it suddenly doesn't match it anymore).

Show quoted text 5 lines
Note again that my apps are not in FPC, and could be easily changed. They are just meant as illustrations of very common use (and thus of the number of support issues you can expect when sb after a lot of debugging finds out that the system reacts differently, *JUST* like the issue that initiated this thread)

I don't expect many application probably wouldn't suddenly start behaving very differently because of one added fpstat call per now() call either.

Show quoted text 8 lines
> And even if it is eventually transformed into a pluggable API, fixing > it now does not require this plug-in architecture to exist, nor does > fixing it make it harder to transform it into a pluggable API > afterwards. That kind of quick and dirty mentality and pooh,poohing away sideeffects (like a noticably slower gettime) without a way to override it is exactly what I'm afraid of.

There is nothing dirty about this fix. It is a completely standard implementation for getting the local time on a Unix platform, and probably used by C libraries everywhere (I'm at least not aware of any C library firing up a separate thread to monitor changes to the timezone file).

Yes, the result slower, but it's also correct (as in "it makes sure that the actual local time is returned"). Just like all UTF-16 code in the RTL is slower than what Martin Schreiber would like, and we didn't change it to UCS-2 when he asked to do so for speed reasons.

It's a quick fix, but if it's not dirty that's a plus rather than a minus as far as I'm concerned.

Show quoted text 7 lines
> It is related as far as I am concerned, because the above is how Now() > currently works on Unix and as far as I understand, you don't want it > to be fixed using a straightforward stat/update check because that may > reduce the performance/rate properties of that call. I meant that wrt compatibility, since such solution requires an audit of all gettime use,

It's the current implementation that requires an audit of all gettime use, because if people expect to always get the local time there then this assumption is wrong.

Minimizing that is one of the things compatibility is about. More importantly, the various requirements don't bite eachother, except that a proper solution might require some more functionality in the core set (hence plugin route).

I disagree that a simple fpstat call is not a proper solution. There may well be solutions that introduce less perturbation, but the basic requirement of gettime/now is that it returns the local time and not that it is executes in the same amount of time as getting the time in a non-adjusted way.

Jonas

---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.

Reply by email

Hans-Peter Diettrich
to Unknown author: The call will not be merged. Instead, you can just add ReadTimezoneFile(GetTimezoneFile);…
Show quoted text 6 lines
The call will not be merged. Instead, you can just add ReadTimezoneFile(GetTimezoneFile); GetLocalTimezone(fptime); to your code (and add units 'unix' and 'baseunix').

What will happen if these are called on other platforms, which don't have timezone files?

IMO a function (UpdateTimeZone?) should be added, that encapsulates these POSIX specific calls and dependencies, for use on all platforms.

DoDi

Reply by email

Martin Schreiber
to Jonas Maebe: Marco van de Voort wrote on Wed, 02 Nov 2011: Fine, and in most cases people probably…
Jonas Maebe wrote 5 lines
Yes, the result slower, but it's also correct (as in "it makes sure that the actual local time is returned"). Just like all UTF-16 code in the RTL is slower than what Martin Schreiber would like, and we didn't change it to UCS-2 when he asked to do so for speed reasons.

???
I never asked this. I asked not to use new code page aware stringtype instead of pre cpstrnew UnicodeString, not to use 16 bit strings in component names and the like and not to use non ASCII characters in RTTI and Pascal identifiers.
I fully agree with your argumentation about Now(). MSEgui already has a nowutc() function, I'll add nowlocal() which will use mselibc on Linux.

Martin

Reply by email

Jonas Maebe
to Martin Schreiber

Martin Schreiber wrote on Wed, 02 Nov 2011:

Show quoted text 8 lines
On Wednesday 02 November 2011 17.13:49 Jonas Maebe wrote: > Just like all UTF-16 code in > the RTL is slower than what Martin Schreiber would like, and we didn't > change it to UCS-2 when he asked to do so for speed reasons. > ??? I never asked this.

http://bugs.freepascal.org/view.php?id=10462 :) ("Please take into account that this functions are called very often for sorting strings, optimal performance is essential. I am not sure if the correct handling of surrogate pairs, which probably not many FPC users really need, is worth the loss on performance.")

Jonas

---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.

Reply by email

Martin Schreiber
to Jonas Maebe
Jonas Maebe wrote 15 lines
Martin Schreiber wrote on Wed, 02 Nov 2011: > On Wednesday 02 November 2011 17.13:49 Jonas Maebe wrote: >> Just like all UTF-16 code in >> the RTL is slower than what Martin Schreiber would like, and we didn't >> change it to UCS-2 when he asked to do so for speed reasons. > > ??? > I never asked this. http://bugs.freepascal.org/view.php?id=10462 :) ("Please take into account that this functions are called very often for sorting strings, optimal performance is essential. I am not sure if the correct handling of surrogate pairs, which probably not many FPC users really need, is worth the loss on performance.")

:-)
Now this is long time ago...
And the emphasis is on performance of string comparing and sorting which still is very bad on Linux.

Martin

Reply by email

Sven Barth
to Hans-Peter Diettrich: What will happen if these are called on other platforms, which don't have timezone files?…
Hans-Peter Diettrich wrote 11 lines
schrieb: > The call will not be merged. Instead, you can just add > > ReadTimezoneFile(GetTimezoneFile); > GetLocalTimezone(fptime); > > to your code (and add units 'unix' and 'baseunix'). What will happen if these are called on other platforms, which don't have timezone files?

As those two functions are implemented in POSIX specific units (Unix and BaseUnix) I expect them to work on all POSIX systems (at least they won't generate a compile time error.

IMO a function (UpdateTimeZone?) should be added, that encapsulates these POSIX specific calls and dependencies, for use on all platforms.

The solution mentioned above is a workaround for 2.4 where no fix is in place. Newer versions of FPC (maybe even 2.6, I don't know about that) will get an improved/fixed version of Now (how exactly seems to still be debated). Also note that on platforms like Windows this would be a unnecessary call as there the current(!) timezone bias is located in a shared memory area which is mapped into each process by the kernel.

Regards,
Sven

Reply by email

Ludo Brands
to Sven Barth
Show quoted text 5 lines
debated). Also note that on platforms like Windows this would be a unnecessary call as there the current(!) timezone bias is located in a shared memory area which is mapped into each process by the kernel.

Apparently not everything is that transparent under windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724944%28v=vs.85%2 9.aspx

"To inform Explorer that the time zone has changed, send the WM_SETTINGCHANGE message."

Or:

http://channel9.msdn.com/coding4fun/articles/Changing-time-zones

"By itself, changing the time zone doesn't have any apparent effect except in new processes. In order to see the change, you need to send a system notification message. This notification is made by calling SendMessageTimeout with WM_SettingChange and a parameter of "intl". "

Ludo

Reply by email

Luca Olivetti
to Mark Morgan Lloyd: Agreed. Basically, the idea of "time" that underpins timers, which should fire correctly…

Al 02/11/11 09:31, En/na Mark Morgan Lloyd ha escrit:

But even in this case, what should happen if the user (or NTP) explicitly changes the system clock? Ultimately, what matters for relative timing is ticks-since-boot. From the link posted before:

http://www.kernel.org/doc/man-pages/online/pages/man2/clock_gettime.2.html

CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific) Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments.

(i.e., similar to GetTickCount under windows, the problem is that's Linux-specific).

Bye

Luca

Reply by email

Vinzent Höfler
to Felipe Monteiro de Carvalho: One more idea: Do we already have something like NowUTC ? Just like Now, but in UTC.…
Felipe Monteiro de Carvalho wrote
Maybe that would be something interresting to add. Programs that want to measure time differences could use it instead of hacking Now.

Well, all what's needed is to differentiate between a political-time and a monotonic/real-time clock.

The latter could be sufficiently substituted on all systems by the underlying facilities of the system with opaque time types. The RTL could provide all necessary conversion functions, so not even the actual resolution of the system would matter.

Vinzent.

Reply by email

Martin Schreiber
to Martin Schreiber: ??? I never asked this. I asked not to use new code page aware stringtype instead of pre…
Martin Schreiber wrote 14 lines
On Wednesday 02 November 2011 17.13:49 Jonas Maebe wrote: > Yes, the result slower, but it's also correct (as in "it makes sure > that the actual local time is returned"). Just like all UTF-16 code in > the RTL is slower than what Martin Schreiber would like, and we didn't > change it to UCS-2 when he asked to do so for speed reasons. ??? I never asked this. I asked not to use new code page aware stringtype instead of pre cpstrnew UnicodeString, not to use 16 bit strings in component names and the like and not to use non ASCII characters in RTTI and Pascal identifiers. I fully agree with your argumentation about Now(). MSEgui already has a nowutc() function, I'll add nowlocal() which will use mselibc on Linux.

The results with 10'000'000 calls:

FPC Now() MSEgui nowutc() MSEgui nowlocal()

Linux
15.29s 3.39s 3.57s

Windows
10.00s 1.22s 1.37s

Martin

Reply by email

Hans-Peter Diettrich
to Luca Olivetti: Al 02/11/11 09:31, En/na Mark Morgan Lloyd ha escrit:…
Show quoted text 12 lines
Al 02/11/11 09:31, En/na Mark Morgan Lloyd ha escrit: > But even in this case, what should happen if the user (or NTP) explicitly changes the system clock? Ultimately, what matters for relative timing is ticks-since-boot. >From the link posted before: http://www.kernel.org/doc/man-pages/online/pages/man2/clock_gettime.2.html CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific) Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments.

Did you also notice this:

>

More clocks may be implemented. The interpretation of the corresponding time values and the effect on timers is unspecified. <<

DoDi

Reply by email

Hans-Peter Diettrich
to Vinzent Höfler: On Wed, 02 Nov 2011 07:35:30 +0100, Felipe Monteiro de Carvalho Well, all what's needed…
Show quoted text 13 lines
On Wed, 02 Nov 2011 07:35:30 +0100, Felipe Monteiro de Carvalho wrote: > Maybe that would be something interresting to add. Programs that want > to measure time differences could use it instead of hacking Now. Well, all what's needed is to differentiate between a political-time and a monotonic/real-time clock. The latter could be sufficiently substituted on all systems by the underlying facilities of the system with opaque time types. The RTL could provide all necessary conversion functions, so not even the actual resolution of the system would matter.

IMO we have to face a problem very similar to Ansi/UTF-8/16: A TDateTime variable can contain local time in a number of timezones (Ansi), or UTC values (UTF), which must be interpreted accordingly, e.g. in DateTimeToStr().

When Delphi compatible Now() provides local time TDateTime (including DST, as is on Windows), and DateTimeToStr() etc. expect a local time argument, a full emulation of these functions has to be provided on other platforms as well.

But Delphi also offers a (monotonic) modified Julian date (type Double), and TTimeStamp, and conversions are required when such values shall be formatted into strings. With overloaded functions the monotonic/local time conversion can be performed in the formatting etc. functions, and specialized functions to get the time in other encodings can be added.

Another feature could switch the application-wide TDateTime content, between local (Windows default) and monotonic/UTC (POSIX) time. This would not require additional functions, instead all date/time functions would take into account that setting internally. Drawback is that only one encoding can be used in an application, i.e. the user must decide whether times are used as unique (monotonic, real-time) time stamps, or in local time for display purposes.

As a third solution the time encoding could be added to TDateTime, similar to the new AnsiString encoding. Care must be taken to keep such an extension compatible with e.g. typecasts (Double from/to TDateTime). Perhaps a conversion of TDateTime into an Object with an added Encoding property would help...

DoDi

Reply by email

Hans-Peter Diettrich
to Sven Barth: As those two functions are implemented in POSIX specific units (Unix and BaseUnix) I…
The solution mentioned above is a workaround for 2.4 where no fix is in place. Newer versions of FPC (maybe even 2.6, I don't know about that) will get an improved/fixed version of Now (how exactly seems to still be debated).

ACK

Also note that on platforms like Windows this would be a unnecessary call as there the current(!) timezone bias is located in a shared memory area which is mapped into each process by the kernel.

I don't think that this really is how Windows works. Delphi Now() retrieves an TSystemTime record (GetLocalTime), and converts its fields into an TDateTime value(EncodeDate/Time). A simple timezone bias is inapplicable to the TSystemTime data structure, but the kernel.dll may keep its conversion information somewhere in the DATA segment. On POSIX platforms gettimeofday and localtime_r is used instead (Delphi XE). All this handling makes Now() quite expensive, so that (a future) FPC should provide cheaper means for getting time stamps.

BTW, Windows itself provides GetSystemTime() based on *UTC*, and stored in TSystemTime. When monotonic timestamps are needed, even a Windows application can use this feature.

DoDi

Reply by email

Hans-Peter Diettrich
to Ludo Brands: Apparently not everything is that transparent under windows:…
Show quoted text 21 lines
> debated). Also note that on platforms like Windows this would be a > unnecessary call as there the current(!) timezone bias is > located in a > shared memory area which is mapped into each process by the kernel. > Apparently not everything is that transparent under windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724944%28v=vs.85%2 9.aspx "To inform Explorer that the time zone has changed, send the WM_SETTINGCHANGE message." Or: http://channel9.msdn.com/coding4fun/articles/Changing-time-zones "By itself, changing the time zone doesn't have any apparent effect except in new processes. In order to see the change, you need to send a system notification message. This notification is made by calling SendMessageTimeout with WM_SettingChange and a parameter of "intl". "

There exists a more specific WM_TIMECHANGE message, with the remark:

>

An application should not broadcast this message, because the system will broadcast this message when the application changes the system time. <<

It remains unclear whether a DST change will cause such an broadcast as well. Most probably *not*, because the system time (UTC) is not affected by DST or timezone changes.

DoDi

Reply by email

zeljko
to Martin Schreiber: The results with 10'000'000 calls: FPC Now() MSEgui nowutc() MSEgui nowlocal() Linux…
Martin Schreiber wrote 24 lines
On Wednesday 02 November 2011 17.43:56 Martin Schreiber wrote: > On Wednesday 02 November 2011 17.13:49 Jonas Maebe wrote: > > Yes, the result slower, but it's also correct (as in "it makes sure > > that the actual local time is returned"). Just like all UTF-16 code in > > the RTL is slower than what Martin Schreiber would like, and we didn't > > change it to UCS-2 when he asked to do so for speed reasons. > > ??? > I never asked this. I asked not to use new code page aware stringtype > instead of pre cpstrnew UnicodeString, not to use 16 bit strings in > component names and the like and not to use non ASCII characters in RTTI > and Pascal identifiers. > I fully agree with your argumentation about Now(). MSEgui already has a > nowutc() function, I'll add nowlocal() which will use mselibc on Linux. The results with 10'000'000 calls: FPC Now() MSEgui nowutc() MSEgui nowlocal() Linux 15.29s 3.39s 3.57s Windows 10.00s 1.22s 1.37s

Have you tried latest Michael's patch for getttimeofday ? It used 2 calls 1 to gettimeofday and 1 to fptime, now it uses only gettimeofday syscall and it's twice faster.
So: your nowutc() and nowlocal() returns timings which I have with my implementation of Now() by using syscall clock_gettime(CLOCK_REALTIME). After Michal patched current trunk , gettimeofday have same timing. Overhead of Now() is now fixed in trunk.
Don't know anything about windows...maybe it should be reviewed for unnecesarry calls.

zeljko

Reply by email

Martin Schreiber
to zeljko
zeljko wrote 14 lines
> > The results with 10'000'000 calls: > > FPC Now() MSEgui nowutc() MSEgui nowlocal() > > Linux > > 15.29s 3.39s 3.57s > > Windows > > 10.00s 1.22s 1.37s Have you tried latest Michael's patch for getttimeofday ?

No, I can not use trunk because of cpstrnew. I'll try the file Michael sent.

Martin

Reply by email

Paul Ishenin
to Martin Schreiber
Martin Schreiber wrote
No, I can not use trunk because of cpstrnew. I'll try the file Michael sent.

If it is not difficult please explain exact problems with cpstrnew you have in a separate thread. It is important to know for me what problems do you have with the new ansistring type.

Best regards,
Paul Ishenin.

Reply by email

zeljko
to Paul Ishenin
Paul Ishenin wrote 7 lines
03.11.2011 15:04, Martin Schreiber wrote: > No, I can not use trunk because of cpstrnew. I'll try the file Michael > sent. If it is not difficult please explain exact problems with cpstrnew you have in a separate thread. It is important to know for me what problems do you have with the new ansistring type.

Maybe it's not problem *now*, but looking into mailing list ppl have a lot of problems, so I think that fear is only problem (at least for me).

zeljko

Reply by email

Martin Schreiber
to Paul Ishenin: If it is not difficult please explain exact problems with cpstrnew you have in a separate…
Paul Ishenin wrote 8 lines
03.11.2011 15:04, Martin Schreiber wrote: > No, I can not use trunk because of cpstrnew. I'll try the file Michael > sent. If it is not difficult please explain exact problems with cpstrnew you have in a separate thread. It is important to know for me what problems do you have with the new ansistring type.

I invested much time into debugging pre 2.0 / post 2.0 WideString and pre 2.7 UnicodeString. I do not plan to do the same for cpstrnew. I think the people who wanted the new strings should do the debugging too. Maybe it is bug free already but I can't really believe it. ;-)

Martin

Reply by email

Martin Schreiber
to Martin Schreiber: No, I can not use trunk because of cpstrnew. I'll try the file Michael sent. Martin
Martin Schreiber wrote 15 lines
On Thursday 03 November 2011 07.44:47 zeljko wrote: > > The results with 10'000'000 calls: > > > > FPC Now() MSEgui nowutc() MSEgui nowlocal() > > > > Linux > > > > 15.29s 3.39s 3.57s > > > > Windows > > > > 10.00s 1.22s 1.37s > > Have you tried latest Michael's patch for getttimeofday ?

RTL recompiled with Michael's file:

Linux
FPC Now() MSEgui nowutc() MSEgui nowlocal()

11.49s 3.86s 4.03s

Martin

Reply by email

Paul Ishenin
to zeljko: Maybe it's not problem *now*, but looking into mailing list ppl have a lot of problems,…
zeljko wrote
Maybe it's not problem *now*, but looking into mailing list ppl have a lot of problems, so I think that fear is only problem (at least for me).

People mostly expressed their FUD although there were few problems and there are some.

But why do you think they should affect you? Do you any ansistring type except 'AnsiString' in your applications?

Best regards,
Paul Ishenin.

Reply by email

zeljko
to Martin Schreiber: RTL recompiled with Michael's file: Linux FPC Now() MSEgui nowutc() MSEgui nowlocal()…
Martin Schreiber wrote 22 lines
On Thursday 03 November 2011 08.04:17 Martin Schreiber wrote: > On Thursday 03 November 2011 07.44:47 zeljko wrote: > > > The results with 10'000'000 calls: > > > > > > FPC Now() MSEgui nowutc() MSEgui nowlocal() > > > > > > Linux > > > > > > 15.29s 3.39s 3.57s > > > > > > Windows > > > > > > 10.00s 1.22s 1.37s > > > > Have you tried latest Michael's patch for getttimeofday ? RTL recompiled with Michael's file: Linux FPC Now() MSEgui nowutc() MSEgui nowlocal() 11.49s 3.86s 4.03s

That's pretty big difference. Can you compare NowReal() from attached program with your functions ?

zeljko

Reply by email

Martin Schreiber
to zeljko
zeljko wrote
That's pretty big difference. Can you compare NowReal() from attached program with your functions ?

Linux
FPC Now() MSEgui nowutc() MSEgui nowlocal() NowReal()

10.28s 3.45s 3.55s 9.86s

Martin

Reply by email

Sven Barth
to Hans-Peter Diettrich: IMO we have to face a problem very similar to Ansi/UTF-8/16: A TDateTime variable can…
Hans-Peter Diettrich wrote 9 lines
IMO we have to face a problem very similar to Ansi/UTF-8/16: A TDateTime variable can contain local time in a number of timezones (Ansi), or UTC values (UTF), which must be interpreted accordingly, e.g. in DateTimeToStr(). When Delphi compatible Now() provides local time TDateTime (including DST, as is on Windows), and DateTimeToStr() etc. expect a local time argument, a full emulation of these functions has to be provided on other platforms as well.

But even in Delphi the programmer has to keep track whether a TDateTime contains a local or UTC based time value (e.g. if he converted the local time returned by Now to UTC).
And functions like DateTimeToStr don't care whether a time value is local or UTC and in my opinion they even MUST NOT. If I use such a function I want the value of the given TDateTime printed to a string no matter what timezone I'm currently in.

Regards,
Sven

Reply by email

Sven Barth
to Hans-Peter Diettrich: ACK I don't think that this really is how Windows works. Delphi Now() retrieves an…
Hans-Peter Diettrich wrote 9 lines
> Also note that on platforms like Windows this would be a unnecessary > call as there the current(!) timezone bias is located in a shared > memory area which is mapped into each process by the kernel. I don't think that this really is how Windows works. Delphi Now() retrieves an TSystemTime record (GetLocalTime), and converts its fields into an TDateTime value(EncodeDate/Time). A simple timezone bias is inapplicable to the TSystemTime data structure, but the kernel.dll may keep its conversion information somewhere in the DATA segment.

FPC's Now on Windows uses GetLocalTime as well. For its implementation please take a look here:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/time.c?revision=52912&view=markup (line 277ff)

The application of the timezone bias is from line 290 to 300. If there is no redirection of the time zone (used for terminal servers) then the bias is read from the beforementioned shared user data.

Here is the implementation of "SharedUserData" in my NativeNT port of FPC (unit NDK):

=== source begin ===

function SharedUserData: PKUSER_SHARED_DATA; register;
begin
   { this is a pointer to a page that is mapped into every process by
the kernel
   }
   SharedUserData := PKUSER_SHARED_DATA(USER_SHARED_DATA);
end;

=== source end ===

And USER_SHARED_DATA has the following value:

=== source begin ===

   USER_SHARED_DATA = $7FFE0000;

=== source end ===

On POSIX platforms gettimeofday and localtime_r is used instead (Delphi XE). All this handling makes Now() quite expensive, so that (a future) FPC should provide cheaper means for getting time stamps.

The problem with localtime_r itself is that it's implemented in LibC which must be avoided for the non-LibC-RTL. So FPC definitely must provide an implementation of its own for this.

Regards,
Sven

Reply by email

Hans-Peter Diettrich
to Sven Barth: But even in Delphi the programmer has to keep track whether a TDateTime contains a local…
Show quoted text 14 lines
Am 03.11.2011 02:39, schrieb Hans-Peter Diettrich: > IMO we have to face a problem very similar to Ansi/UTF-8/16: A TDateTime > variable can contain local time in a number of timezones (Ansi), or UTC > values (UTF), which must be interpreted accordingly, e.g. in > DateTimeToStr(). > > When Delphi compatible Now() provides local time TDateTime (including > DST, as is on Windows), and DateTimeToStr() etc. expect a local time > argument, a full emulation of these functions has to be provided on > other platforms as well. But even in Delphi the programmer has to keep track whether a TDateTime contains a local or UTC based time value (e.g. if he converted the local time returned by Now to UTC).

Right, just like the user currently must remember whether an AnsiString contains Ansi or UTF-8. But how do you want to get the UTC and put it into a TDateTime?

And functions like DateTimeToStr don't care whether a time value is local or UTC and in my opinion they even MUST NOT.

Splitting the TDateTime into year, month etc. is done by a DecodeDate... function, that *assumes* that TDateTime contains a local time. When you feed it an UTC time, the result is unusable.

If I use such a function I want the value of the given TDateTime printed to a string no matter what timezone I'm currently in.

A TDateTime only contains the number of days since the begin of the epoch (of the encoded date). Which epoch should apply? The time part contains the fraction of the day, based on midnight of which timezone?

DoDi

Reply by email

Hans-Peter Diettrich
to Sven Barth: FPC's Now on Windows uses GetLocalTime as well. For its implementation please take a look…
FPC's Now on Windows uses GetLocalTime as well. For its implementation please take a look here: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/time.c?revision=52912&view=markup (line 277ff)

That code doesn't make sense, without additional information :-(

283 do
284 {

   285         SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
   286         SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
   287     }
   288     while (SystemTime.HighPart !=

SharedUserData->SystemTime.High2Time);

As long as no functions are involved, the loop copies the same information into SystemTime, over and over again.

Show quoted text 8 lines
> On POSIX > platforms gettimeofday and localtime_r is used instead (Delphi XE). All > this handling makes Now() quite expensive, so that (a future) FPC should > provide cheaper means for getting time stamps. The problem with localtime_r itself is that it's implemented in LibC which must be avoided for the non-LibC-RTL. So FPC definitely must provide an implementation of its own for this.

Then something like WinAPI SystemTimeToTzSpecificLocalTime has to be implemented. That function can be used for every platform, provided that the SystemTime is stored in an platform independent way.

DoDi

Reply by email

Vinzent Höfler
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 18 lines
> FPC's Now on Windows uses GetLocalTime as well. For its implementation > please take a look here: > http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/time.c?revision=52912&view=markup > (line 277ff) That code doesn't make sense, without additional information :-( 283 do 284 { 285 SystemTime.HighPart = SharedUserData->SystemTime.High1Time; 286 SystemTime.LowPart = SharedUserData->SystemTime.LowPart; 287 } 288 while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time); As long as no functions are involved, the loop copies the same information into SystemTime, over and over again.

Nope. SystemTime.HighXTime is most probably a "volatile", so it is read each time through the loop. I can only guess what High1Time and High2Time is
(I'd assume they basically map to the same variable, so you're right, that is a bit strange somehow, but well...), but this is a common pattern to counterfeit wrong time reads when a wrap-around happens during reading the individual parts.

Consider reading the values when the time value is $0000:$FFFF. First you read the $FFFF, then the time value changes to $0001:0000 and next you read the high part as $0001. Net result: $0001:$FFFF. Thus, a big time jump happens. Seldom enough to detect in testing, but often enough to cause disastrous results at the customer site from time to time.

By checking the high part again, the problem is avoided.

[Well, at least as long as the reading does not take a huge amount of time, so that another wrap of the high part happens... ;)]

Vinzent.

Reply by email

Pete Cervasio
to Hans-Peter Diettrich: Right, just like the user currently must remember whether an AnsiString contains Ansi or…
am Hans-Peter Diettrich wrote 7 lines
Sven Barth schrieb: > And functions like DateTimeToStr don't care whether a time value is > local or UTC and in my opinion they even MUST NOT. Splitting the TDateTime into year, month etc. is done by a DecodeDate... function, that *assumes* that TDateTime contains a local time. When you feed it an UTC time, the result is unusable.

What? How does it assume it's in local time? It assumes it has received the value you want decoded. The value 40850.5 treated as a TDateTime is 03 NOV 2011 @ 12:00. No matter what time zone it's expressed in, the result is the same, but in that zone. If you want a different zone, you have to add in the offset before decoding.

How is that unusable?

Best regards,
Pete C.

Reply by email

Hans-Peter Diettrich
to Pete Cervasio
Show quoted text 9 lines
> Splitting the TDateTime into year, month etc. is done by a DecodeDate... > function, that *assumes* that TDateTime contains a local time. When you > feed it an UTC time, the result is unusable. What? How does it assume it's in local time? It assumes it has received the value you want decoded. The value 40850.5 treated as a TDateTime is 03 NOV 2011 @ 12:00.

How do you get the starting date and time of the epoch?

According to Delphi help a TDateTime of 0.0 represents 12/30/1899 12:00 am, while Wikipedia states "start counting the seconds from the Unix epoch of 1970-01-01T00:00:00 UTC".

DoDi

Reply by email

Sven Barth
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 18 lines
Pete Cervasio schrieb: > > Splitting the TDateTime into year, month etc. is done by a > DecodeDate... > > > function, that *assumes* that TDateTime contains a local time. When you > > > feed it an UTC time, the result is unusable. > > What? How does it assume it's in local time? It assumes it has > received the value you want decoded. The value 40850.5 treated as a > TDateTime is 03 NOV 2011 @ 12:00. How do you get the starting date and time of the epoch? According to Delphi help a TDateTime of 0.0 represents 12/30/1899 12:00 am, while Wikipedia states "start counting the seconds from the Unix epoch of 1970-01-01T00:00:00 UTC".

You are aware that the definition of TDateTime and that of the Unix timestamp are not supposed to be the same? The original TDateTime definiton (Delphi 1 and maybe also 2) started from 01/01/0001 and was later changed to todays 12/30/1899 to be COM compatible.

And still: It does not matter whether we are talking about local or UTC time here.

Regards,
Sven

Reply by email

Sven Barth
to Ludo Brands: Apparently not everything is that transparent under windows:…
Ludo Brands wrote 7 lines
Apparently not everything is that transparent under windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724944%28v=vs.85%2 9.aspx "To inform Explorer that the time zone has changed, send the WM_SETTINGCHANGE message."

WM_SETTINGCHANGE simply notifies you that the user changed the time zone, because otherwise you might not be able to detect that (except you read the settings from the registry yourself).

Show quoted text 8 lines
Or: http://channel9.msdn.com/coding4fun/articles/Changing-time-zones "By itself, changing the time zone doesn't have any apparent effect except in new processes. In order to see the change, you need to send a system notification message. This notification is made by calling SendMessageTimeout with WM_SettingChange and a parameter of "intl". "

This is wrong. Changing the timezone effects e.g. all following calls to GetLocalTime. See the following example program:

=== source begin ===

program timezonetest;
{$apptype console}
{$mode objfpc}{$H+}
uses
   SysUtils;
begin
   Writeln(FormatDateTime('c', Now));
   Writeln('Please change the timezone and then press enter');
   Readln;
   Writeln(FormatDateTime('c', Now));
   Writeln('Done');
   Readln;
end.

=== source end ===

As you see there is no message processing.

My normal timezone is Berlin. Now I've run the program and changed the timezone to Greenland (-3h). The output was the following:

=== output begin ===

03.11.2011 21:16:33
Please change the timezone and then press enter

03.11.2011 17:17:10
Done

=== output end ===

So your link which talks about "only affects new processes" is proven wrong.

Regards,
Sven

Reply by email

Sven Barth
to Hans-Peter Diettrich: That code doesn't make sense, without additional information :-( 283 do 284 { 285…
Hans-Peter Diettrich wrote 18 lines
Sven Barth schrieb: > FPC's Now on Windows uses GetLocalTime as well. For its implementation > please take a look here: > http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/time.c?revision=52912&view=markup > (line 277ff) That code doesn't make sense, without additional information :-( 283 do 284 { 285 SystemTime.HighPart = SharedUserData->SystemTime.High1Time; 286 SystemTime.LowPart = SharedUserData->SystemTime.LowPart; 287 } 288 while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time); As long as no functions are involved, the loop copies the same information into SystemTime, over and over again.

As Vinzent wrote, the SystemTime field is considered volatile (take a look at %fpcdir%\rtl\nativent\ndk\ketypes.inc; I have kept the "volatile" keywords as comments when translating that _KUSER_SHARED_DATA struct). This code is also found throughout ReactOS (and I expect Windows as well) when the time is fetched inside one of the operating system components. I've basically copied this code for the GetLocalTime implementation of my NativeNT port and it definitely works and does not loop till the end of eternity :)

Show quoted text 12 lines
>> On POSIX >> platforms gettimeofday and localtime_r is used instead (Delphi XE). All >> this handling makes Now() quite expensive, so that (a future) FPC should >> provide cheaper means for getting time stamps. > > The problem with localtime_r itself is that it's implemented in LibC > which must be avoided for the non-LibC-RTL. So FPC definitely must > provide an implementation of its own for this. Then something like WinAPI SystemTimeToTzSpecificLocalTime has to be implemented. That function can be used for every platform, provided that the SystemTime is stored in an platform independent way.

Something like this, yes.

Regards,
Sven

Reply by email

Pete Cervasio
to Hans-Peter Diettrich: How do you get the starting date and time of the epoch? According to Delphi help a…
pm Hans-Peter Diettrich wrote 14 lines
Pete Cervasio schrieb: > > Splitting the TDateTime into year, month etc. is done by a > > DecodeDate... > > > > function, that *assumes* that TDateTime contains a local time. When > > you > > > > feed it an UTC time, the result is unusable. > > What? How does it assume it's in local time? It assumes it has received > the value you want decoded. The value 40850.5 treated as a TDateTime is > 03 NOV 2011 @ 12:00. How do you get the starting date and time of the epoch?

With the constant UnixDateDelta. Help says that it "Specifies the difference between TDateTime and TIME_T values".

Here's how I use it. My main software project does all its work in UTC so I use this utc_now rather than the built-in now. Conversion to local time is done only for display or logging purposes.

function utc_now: TDateTime;
var
  TimeVal: TTimeVal;
  TimeZone: PTimeZone;
begin
  TimeZone := nil;
  GetTimeOfDay (TimeVal, TimeZone);
  Result := (TimeVal.tv_Sec / SecsPerDay)
          + ((TimeVal.tv_usec / 1000.0) / MSecsPerDay)
          + UnixDateDelta;
end;

Best regards,
Pete C.

Reply by email

zeljko
to Sven Barth: WM_SETTINGCHANGE simply notifies you that the user changed the time zone, because…
Sven Barth wrote 62 lines
Am 02.11.2011 19:25, schrieb Ludo Brands: > Apparently not everything is that transparent under windows: > http://msdn.microsoft.com/en-us/library/windows/desktop/ms724944%28v=vs.8 > 5%2 9.aspx > > "To inform Explorer that the time zone has changed, send the > WM_SETTINGCHANGE message." WM_SETTINGCHANGE simply notifies you that the user changed the time zone, because otherwise you might not be able to detect that (except you read the settings from the registry yourself). > Or: > > http://channel9.msdn.com/coding4fun/articles/Changing-time-zones > > "By itself, changing the time zone doesn't have any apparent effect > except in new processes. In order to see the change, you need to send a > system notification message. This notification is made by calling > SendMessageTimeout with WM_SettingChange and a parameter of "intl". " This is wrong. Changing the timezone effects e.g. all following calls to GetLocalTime. See the following example program: === source begin === program timezonetest; {$apptype console} {$mode objfpc}{$H+} uses SysUtils; begin Writeln(FormatDateTime('c', Now)); Writeln('Please change the timezone and then press enter'); Readln; Writeln(FormatDateTime('c', Now)); Writeln('Done'); Readln; end. === source end === As you see there is no message processing. My normal timezone is Berlin. Now I've run the program and changed the timezone to Greenland (-3h). The output was the following: === output begin === 03.11.2011 21:16:33 Please change the timezone and then press enter 03.11.2011 17:17:10 Done === output end === So your link which talks about "only affects new processes" is proven wrong.

But this is on windows ? On linux it does not work without re-reading tzdata.

zeljko

Reply by email

Hans-Peter Diettrich
to Sven Barth: You are aware that the definition of TDateTime and that of the Unix timestamp are not…
Show quoted text 8 lines
> According to Delphi help a TDateTime of 0.0 represents 12/30/1899 12:00 > am, while Wikipedia states "start counting the seconds from the Unix > epoch of 1970-01-01T00:00:00 UTC". You are aware that the definition of TDateTime and that of the Unix timestamp are not supposed to be the same? The original TDateTime definiton (Delphi 1 and maybe also 2) started from 01/01/0001 and was later changed to todays 12/30/1899 to be COM compatible.

The use of different types, for Windows local and system time, requires either a conversion when a UTC (system) time is assigned to a TDateTime variable, or overloaded functions are required for dealing with such different encodings. Currently the conversion from SystemTime (record) into TDateTime (Double) makes the TDateTime contain the *local* time, not the UTC time. That's why I wonder how you want to place an true UTC time value into a TDateTime - can you give some code?

And still: It does not matter whether we are talking about local or UTC time here.

It does, as long as there is no guarantee that UTC and local time start at the exactly same date and time.

DoDi

Reply by email

Sven Barth
to Hans-Peter Diettrich: The use of different types, for Windows local and system time, requires either a…
Hans-Peter Diettrich wrote 19 lines
Sven Barth schrieb: >> According to Delphi help a TDateTime of 0.0 represents 12/30/1899 12:00 >> am, while Wikipedia states "start counting the seconds from the Unix >> epoch of 1970-01-01T00:00:00 UTC". > > You are aware that the definition of TDateTime and that of the Unix > timestamp are not supposed to be the same? The original TDateTime > definiton (Delphi 1 and maybe also 2) started from 01/01/0001 and was > later changed to todays 12/30/1899 to be COM compatible. The use of different types, for Windows local and system time, requires either a conversion when a UTC (system) time is assigned to a TDateTime variable, or overloaded functions are required for dealing with such different encodings. Currently the conversion from SystemTime (record) into TDateTime (Double) makes the TDateTime contain the *local* time, not the UTC time. That's why I wonder how you want to place an true UTC time value into a TDateTime - can you give some code?

Huh? I still don't get your problem...

Nevertheless here is an example:

=== source begin ===

program utctest;
{$mode objfpc}{$H+}
{$apptype console}
uses
   Windows, SysUtils;
var
   st: TSystemTime;
   dt: TDateTime;
begin
   GetLocalTime(st);
   dt := SystemTimeToDateTime(st);
   Writeln(FormatDateTime('c', dt));
   GetSystemTime(st);
   dt := SystemTimeToDateTime(st);
   Writeln(FormatDateTime('c', dt));
   Readln;
end.

=== source end ===

As long as your time zone isn't UTC you will see two different times. For me the result was the following:

=== output begin ===

04.11.2011 11:48:16
04.11.2011 10:48:16

=== output end ===

Show quoted text 5 lines
> And still: It does not matter whether we are talking about local or > UTC time here. It does, as long as there is no guarantee that UTC and local time start at the exactly same date and time.

The TDateTime type is completely timezone agnostic. It's integer part is the count of days since 12/30/1899 and it's fracture part is the part of 24 hours. So by definition there is no timezone. And TSystemTime is timezone agnonstic as well. It's just a struct that contains year, month, day, hour, minute, second and millisecond. It can even hold a UTC time or a local time (see the declaration of
SystemTimeToTzSpecificLocalTime). So if you do a
SystemTimeToTzSpecificLocalTime twice you'll get a result where the time is off by twice your timezone offset.

Regards,
Sven

Reply by email

Hans-Peter Diettrich
to Sven Barth
Show quoted text 16 lines
var st: TSystemTime; dt: TDateTime; begin GetLocalTime(st); dt := SystemTimeToDateTime(st); Writeln(FormatDateTime('c', dt)); GetSystemTime(st); dt := SystemTimeToDateTime(st); Writeln(FormatDateTime('c', dt)); Readln; end. === source end === As long as your time zone isn't UTC you will see two different times.

Okay, when you get the *decoded* date/time, the conversion into TDateTime is straight forward. [I missed that the WinAPI provides both times in that format].

But then I wonder why you *ever* want to convert TSystemTime into TDateTime, when it will be converted back again in the date/time formatting (and other) procedures. It would be much faster to display or write out a time stamp, based directly on TSystemTime.

POSIX gettimeofday() instead does not return a decoded date/time, so that Delphi uses localtime_r() to decode it. The inverse function must be used then, to decode a TDateTime for display and other date/time handling. When the RTL implements both these procedures, there should not remain any time difference in the Now() and other procedures on Windows and Linux, based on something like an tick count.

DoDi

Reply by email

Sven Barth
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
But then I wonder why you *ever* want to convert TSystemTime into TDateTime, when it will be converted back again in the date/time formatting (and other) procedures. It would be much faster to display or write out a time stamp, based directly on TSystemTime.

Simple answer: all time/date handling in Delphi/FPC is BASED ON the TDateTime type.

Show quoted text 7 lines
POSIX gettimeofday() instead does not return a decoded date/time, so that Delphi uses localtime_r() to decode it. The inverse function must be used then, to decode a TDateTime for display and other date/time handling. When the RTL implements both these procedures, there should not remain any time difference in the Now() and other procedures on Windows and Linux, based on something like an tick count.

But Delphi also converts the date/time returned by localtime_r() to a TDateTime, because - as I've written above - that is what Delphi's RTL, VCL and FireMonkey use as date/time type.
Also there will still be a time difference as the retrieval of the time zone information on Linux (and other POSIX systems) requires access to a file while on Windows simply the time zone bias in RAM is used. And also basing Now() on a tick count is a bad idea as now is defined as returning the current (local) date and time instead of some monotonic value like the time since the system was started (what GetTickCount on Windows is).

Regards,
Sven

Reply by email