[Lazarus] Portable way to get accurate timestamps?

classic Classic list List threaded Threaded
57 messages Options
123
Reply | Threaded
Open this post in threaded view
|

[Lazarus] Portable way to get accurate timestamps?

Bo Berglund
In my data acquisition program I also need to timestamp the retrieved
data from the instrument. I want this to be as accurate as possible
and also portable Windows->Linux->Embedded Linux

In Delphi/FPC there are two ways to get a time value that I know of:

GetTickCount gives a value that is in millisecond resolution, but I
don't know how accurate it actually is on the various platforms.

Now() retrieves a TDateTime value, but again I don't know how accurate
it is. Resolution-wise since it is a double it should suffice since it
is based on the year 1900 and we have about 40500 days since then and
thus about 3.500.000.000 seconds. So the double resolution should get
a bit into the decimals of a second. But how many accurate decimals
can be expected? Can I reach millisecond accuracy?

If so, which would be the better way?


--
Bo Berglund
Developer in Sweden


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
ik
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

ik
There is a known problem of windows vs linux with timestamps.
Windows for some reason is less accurate and change the clock every usage of Windows, while in Linux it's considered more accurate. I'm saying it from a bad experience so far.

Secondly. you always have to know where the clock is set for. that is timezone etc... If it's UTC or timezone changes the way you should use the timestamp then a local one, unless you are interested in the local time only.



On Sun, Feb 20, 2011 at 11:47, Bo Berglund <[hidden email]> wrote:
In my data acquisition program I also need to timestamp the retrieved
data from the instrument. I want this to be as accurate as possible
and also portable Windows->Linux->Embedded Linux

In Delphi/FPC there are two ways to get a time value that I know of:

GetTickCount gives a value that is in millisecond resolution, but I
don't know how accurate it actually is on the various platforms.

Now() retrieves a TDateTime value, but again I don't know how accurate
it is. Resolution-wise since it is a double it should suffice since it
is based on the year 1900 and we have about 40500 days since then and
thus about 3.500.000.000 seconds. So the double resolution should get
a bit into the decimals of a second. But how many accurate decimals
can be expected? Can I reach millisecond accuracy?

If so, which would be the better way?


--
Bo Berglund
Developer in Sweden


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus


Ido
LINESIP - Opening the source for communication
http://www.linesip.com
http://www.linesip.co.il


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Bo Berglund
On Sun, 20 Feb 2011 11:58:59 +0200, ik <[hidden email]> wrote:

>There is a known problem of windows vs linux with timestamps.
>Windows for some reason is less accurate and change the clock every usage of
>Windows, while in Linux it's considered more accurate. I'm saying it from a
>bad experience so far.
>
>Secondly. you always have to know where the clock is set for. that is
>timezone etc... If it's UTC or timezone changes the way you should use the
>timestamp then a local one, unless you are interested in the local time
>only.
>

In fact I am interested mainly in the time *difference* between
successive measured data points. So if I could get a fix at the first
measure to a complete time stamp, then all following need only a
fairly accurate *relative* time from the first.

I wonder if GetTickCount will get me a better value to milliseconds
than Now()?

I have heard of a "multimedia" time on Windows, which is more
accurate, but I am not sure how to use it and if it exists on Linux...


--
Bo Berglund
Developer in Sweden


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Luca Olivetti
Al 20/02/11 12:42, En/na Bo Berglund ha escrit:

> I wonder if GetTickCount will get me a better value to milliseconds
> than Now()?

Not under linux:

function GetTickCount: DWord;
begin
  Result := DWord(Trunc(Now * 24 * 60 * 60 * 1000));
end;    

Bye
--
Luca Olivetti
Wetron Automatización S.A. http://www.wetron.es/
Tel. +34 93 5883004 (Ext.133)  Fax +34 93 5883007

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Graeme Geldenhuys
In reply to this post by Bo Berglund
On Sun, 2011-02-20 at 12:42 +0100, Bo Berglund wrote:

> In fact I am interested mainly in the time *difference* between
> successive measured data points.

You can try EpicTimer too. It's only a single unit, easy to use,
supports multiple timers, stopwatch and various display modes. It's not
very portable [read not fully implemented] for exotic platforms, but
works perfectly for my needs under Linux and Windows.


--
Regards,
 - Graeme -

--------------------------------------------------------------
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Bo Berglund
On Sun, 20 Feb 2011 20:07:32 +0200, Graeme Geldenhuys
<[hidden email]> wrote:

>On Sun, 2011-02-20 at 12:42 +0100, Bo Berglund wrote:
>
>> In fact I am interested mainly in the time *difference* between
>> successive measured data points.
>
>You can try EpicTimer too. It's only a single unit, easy to use,
>supports multiple timers, stopwatch and various display modes. It's not
>very portable [read not fully implemented] for exotic platforms, but
>works perfectly for my needs under Linux and Windows.
>
>
Now I have tested both the GetTickCount and Now() methods.
I have synched my tests against a GPS receiver to get an accurate
reference.

Turns out that GetTickCount has a sawtooth-like overlaid timing noise
signal which is about 15 ms.

But using Now() I don't see this.

In both cases I could detect a 12 ppm drift in the clock of mt PC.


--
Bo Berglund
Developer in Sweden


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

wkitty42
In reply to this post by Luca Olivetti
On 2/20/2011 08:46, Luca Olivetti wrote:

> Al 20/02/11 12:42, En/na Bo Berglund ha escrit:
>
>> I wonder if GetTickCount will get me a better value to milliseconds
>> than Now()?
>
> Not under linux:
>
> function GetTickCount: DWord;
> begin
>    Result := DWord(Trunc(Now * 24 * 60 * 60 * 1000));
> end;

i gotta ask... is that even accurate? what are those "ticks" that are being
counted? by the above, they surely do not appear to be the machine's actual
clock timer ticks... can those even be accessed in today's world or do we really
need to revert some things like this back to the DOS world???

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

wkitty42
In reply to this post by Bo Berglund
On 2/20/2011 16:04, Bo Berglund wrote:

> Now I have tested both the GetTickCount and Now() methods.
> I have synched my tests against a GPS receiver to get an accurate
> reference.
>
> Turns out that GetTickCount has a sawtooth-like overlaid timing noise
> signal which is about 15 ms.
>
> But using Now() I don't see this.
>
> In both cases I could detect a 12 ppm drift in the clock of mt PC.

of course, by now, you've seen the post that shows that GetTickCount uses now()
as the base with which to multiply by :? ;)

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Bo Berglund
In reply to this post by wkitty42
On Sun, 20 Feb 2011 22:16:25 -0500, waldo kitty
<[hidden email]> wrote:

>On 2/20/2011 08:46, Luca Olivetti wrote:
>> Al 20/02/11 12:42, En/na Bo Berglund ha escrit:
>>
>>> I wonder if GetTickCount will get me a better value to milliseconds
>>> than Now()?
>>
>> Not under linux:
>>
>> function GetTickCount: DWord;
>> begin
>>    Result := DWord(Trunc(Now * 24 * 60 * 60 * 1000));
>> end;
>
>i gotta ask... is that even accurate? what are those "ticks" that are being
>counted? by the above, they surely do not appear to be the machine's actual
>clock timer ticks... can those even be accessed in today's world or do we really
>need to revert some things like this back to the DOS world???

This is a Delphi wrapped API call in Windows that returns the number
of milliseconds since Windows started. I had the impression that they
were at least locked to the PC clock somehow and actually gave a
millisecond resolution, but now I believe that the "counter" is in
fact working in a different way than one would believe by the name.

When I run a test against a fairly accurate GPS time source I see that
there is an uncertainty of about 16 ms in the time given such that if
GetTickCount is executed at exactly 1 second intervals the last two
digits of the value is not the same as it should be.
Instead it slowly (over a period of 16 seconds) reduces by 16 ms and
then suddenly restores to a max value.
It is like a superimposed sawtooth with an amplitude of 16 ms.

The posted variation is apparently a Linux platform compatible version
that returns a millisecond value the same way as the Windows version
does, since there is no Windows GetTickCount API call in Linux.

I used this also on Windows in my tests and then the value does not
exhibit the sawtooth anymore. So I assume that Now() gets its time
from another source than the timer counter driving GetTickCount and
this is more accurate.


--
Bo Berglund
Developer in Sweden


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

José Mejuto
Hello Lazarus-List,

Monday, February 21, 2011, 7:23:54 AM, you wrote:

BB> When I run a test against a fairly accurate GPS time source I see that
BB> there is an uncertainty of about 16 ms in the time given such that if
BB> GetTickCount is executed at exactly 1 second intervals the last two
BB> digits of the value is not the same as it should be.
BB> Instead it slowly (over a period of 16 seconds) reduces by 16 ms and
BB> then suddenly restores to a max value.
BB> It is like a superimposed sawtooth with an amplitude of 16 ms.

Quote from MSDN:

"The resolution of the GetTickCount function is limited to the
resolution of the system timer, which is typically in the range of 10
milliseconds to 16 milliseconds. The resolution of the GetTickCount
function is not affected by adjustments made by the
GetSystemTimeAdjustment function."

--
Best regards,
 José


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Felipe Monteiro de Carvalho
http://wiki.lazarus.freepascal.org/EpikTimer


--
Felipe Monteiro de Carvalho

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Michael Van Canneyt

Felipe,

Please stop recommending this component.
EpikTimer is not a well-written component.

It's precision is not better than Now() unless you're on i386, Windows.
For all other platforms it's useless and introduces uncalled-for dependencies.

Michael.

On Mon, 21 Feb 2011, Felipe Monteiro de Carvalho wrote:

> http://wiki.lazarus.freepascal.org/EpikTimer
>
>
> --
> Felipe Monteiro de Carvalho
>
> --
> _______________________________________________
> Lazarus mailing list
> [hidden email]
> http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
>

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Luca Olivetti
In reply to this post by Bo Berglund
Al 21/02/11 07:23, En/na Bo Berglund ha escrit:

> The posted variation is apparently a Linux platform compatible version
> that returns a millisecond value the same way as the Windows version
> does, since there is no Windows GetTickCount API call in Linux.

The problem with the current implementation of GetTickCount under Linux is
that's it's not monotonic: I use it to measure elapsed time (usually short
spans, in the range from half a second to a few seconds), and, while under
Windows it's guaranteed to work (I don't mind the wrap-around after 24 days,
since the difference between two consecutive GetTickCount still gives a
positive difference representing the elapsed time), under Linux if somebody
adjusts the clock my timekeeping will fail (I have some checks in place
to fail gracefully, but there are still some corner cases).

Maybe a better way to implement a compatibility function would be to use
clock_get_time with CLOCK_MONOTONIC, though I don't know if it's accessible
from freepascal.

http://linux.die.net/man/3/clock_gettime

Bye
--
Luca Olivetti
Wetron Automatización S.A. http://www.wetron.es/
Tel. +34 93 5883004 (Ext.133)  Fax +34 93 5883007

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Sven Barth
In reply to this post by wkitty42
On 21.02.2011 04:23, waldo kitty wrote:

> On 2/20/2011 16:04, Bo Berglund wrote:
>> Now I have tested both the GetTickCount and Now() methods.
>> I have synched my tests against a GPS receiver to get an accurate
>> reference.
>>
>> Turns out that GetTickCount has a sawtooth-like overlaid timing noise
>> signal which is about 15 ms.
>>
>> But using Now() I don't see this.
>>
>> In both cases I could detect a 12 ppm drift in the clock of mt PC.
>
> of course, by now, you've seen the post that shows that GetTickCount
> uses now() as the base with which to multiply by :? ;)

That was the non-Windows implementation.

Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Bo Berglund
In reply to this post by Bo Berglund
On Mon, 21 Feb 2011 07:23:54 +0100, Bo Berglund
<[hidden email]> wrote:

>When I run a test against a fairly accurate GPS time source I see that
>there is an uncertainty of about 16 ms in the time given such that if
>GetTickCount is executed at exactly 1 second intervals the last two
>digits of the value is not the same as it should be.
>Instead it slowly (over a period of 16 seconds) reduces by 16 ms and
>then suddenly restores to a max value.
>It is like a superimposed sawtooth with an amplitude of 16 ms.
>
>The posted variation is apparently a Linux platform compatible version
>that returns a millisecond value the same way as the Windows version
>does, since there is no Windows GetTickCount API call in Linux.
>
>I used this also on Windows in my tests and then the value does not
>exhibit the sawtooth anymore. So I assume that Now() gets its time
>from another source than the timer counter driving GetTickCount and
>this is more accurate.

I should have added that instead of a sawtooth like noise component
using Frac(Now()) * 24*3600 to get the second since midnight gives
random noise in the seconds values of about 3-4 ms.
Another observation is that there seems to be no data smaller than ms.
If I format this value as a float with more decimals than 3 I always
only see zeroes.


--
Bo Berglund
Developer in Sweden


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Michael Van Canneyt


On Tue, 22 Feb 2011, Bo Berglund wrote:

> On Mon, 21 Feb 2011 07:23:54 +0100, Bo Berglund
> <[hidden email]> wrote:
>
>> When I run a test against a fairly accurate GPS time source I see that
>> there is an uncertainty of about 16 ms in the time given such that if
>> GetTickCount is executed at exactly 1 second intervals the last two
>> digits of the value is not the same as it should be.
>> Instead it slowly (over a period of 16 seconds) reduces by 16 ms and
>> then suddenly restores to a max value.
>> It is like a superimposed sawtooth with an amplitude of 16 ms.
>>
>> The posted variation is apparently a Linux platform compatible version
>> that returns a millisecond value the same way as the Windows version
>> does, since there is no Windows GetTickCount API call in Linux.
>>
>> I used this also on Windows in my tests and then the value does not
>> exhibit the sawtooth anymore. So I assume that Now() gets its time
>> from another source than the timer counter driving GetTickCount and
>> this is more accurate.
>
> I should have added that instead of a sawtooth like noise component
> using Frac(Now()) * 24*3600 to get the second since midnight gives
> random noise in the seconds values of about 3-4 ms.
> Another observation is that there seems to be no data smaller than ms.
> If I format this value as a float with more decimals than 3 I always
> only see zeroes.

That is logical, since TDateTime only is accurate to millisecond precision.

Michael.

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Michael Schnell
In reply to this post by Bo Berglund
On 02/22/2011 06:56 AM, Bo Berglund wrote:
> I should have added that instead of a sawtooth like noise component
> using Frac(Now()) * 24*3600 to get the second since midnight gives
> random noise in the seconds values of about 3-4 ms.
No wonder. In a non-realtime OS like Windows of Linux, you can't create
sound using a timer in a user land program.

-Michael

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Vincent Snijders
2011/2/22 Michael Schnell <[hidden email]>:
> On 02/22/2011 06:56 AM, Bo Berglund wrote:
>>
>> I should have added that instead of a sawtooth like noise component
>> using Frac(Now()) * 24*3600 to get the second since midnight gives
>> random noise in the seconds values of about 3-4 ms.
>
> No wonder. In a non-realtime OS like Windows of Linux, you can't create
> sound using a timer in a user land program.

In this case I wouldn't call "random noise" sound, since you cannot hear it. :-)

Vincent

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Bo Berglund
In reply to this post by Michael Van Canneyt
On Tue, 22 Feb 2011 08:50:33 +0100 (CET), Michael Van Canneyt
<[hidden email]> wrote:

>> I should have added that instead of a sawtooth like noise component
>> using Frac(Now()) * 24*3600 to get the second since midnight gives
>> random noise in the seconds values of about 3-4 ms.
>> Another observation is that there seems to be no data smaller than ms.
>> If I format this value as a float with more decimals than 3 I always
>> only see zeroes.
>
>That is logical, since TDateTime only is accurate to millisecond precision.
>

Granted that, but right now I am mostly interested in finding a way to
time an external event source such that I can measure the time between
events.

After googling a bit I have come up with the following, which is a
variation of a delay function that I created years ago in Delphi to
enable me to output pulses that are timed to milliseconds.
The delay is now converted to a time retrieval function:

function TForm1.GetMillisecondTime: Int64;
var
  Freq,
  Ts: Int64;
begin
  QueryPerformanceCounter(Ts);
  QueryPerformanceFrequency(Freq);
  if (Ts = 0) or (Freq = 0) then exit;
  Freq := Freq div 1000;
  Result := TS div Freq;
end;

When I try this in Lazarus I get an "Identifier not found" error (not
surprising).
What should I do in order to get this to compile?
Any suitable unit to add to the uses clause?

--
Bo Berglund
Developer in Sweden


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Portable way to get accurate timestamps?

Michael Van Canneyt


On Tue, 22 Feb 2011, Bo Berglund wrote:

> On Tue, 22 Feb 2011 08:50:33 +0100 (CET), Michael Van Canneyt
> <[hidden email]> wrote:
>
>>> I should have added that instead of a sawtooth like noise component
>>> using Frac(Now()) * 24*3600 to get the second since midnight gives
>>> random noise in the seconds values of about 3-4 ms.
>>> Another observation is that there seems to be no data smaller than ms.
>>> If I format this value as a float with more decimals than 3 I always
>>> only see zeroes.
>>
>> That is logical, since TDateTime only is accurate to millisecond precision.
>>
>
> Granted that, but right now I am mostly interested in finding a way to
> time an external event source such that I can measure the time between
> events.
>
> After googling a bit I have come up with the following, which is a
> variation of a delay function that I created years ago in Delphi to
> enable me to output pulses that are timed to milliseconds.
> The delay is now converted to a time retrieval function:
>
> function TForm1.GetMillisecondTime: Int64;
> var
>  Freq,
>  Ts: Int64;
> begin
>  QueryPerformanceCounter(Ts);
>  QueryPerformanceFrequency(Freq);
>  if (Ts = 0) or (Freq = 0) then exit;
>  Freq := Freq div 1000;
>  Result := TS div Freq;
> end;
>
> When I try this in Lazarus I get an "Identifier not found" error (not
> surprising).
> What should I do in order to get this to compile?
> Any suitable unit to add to the uses clause?

If you are on windows: add the windows unit.

If you are on another platform: these functions simply do not exist on other platforms.

Michael.

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
123