www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - getUTCtime() increases irregularly

reply david <tazz gmx.at> writes:
Hello,

I was just playing with a slow down class, when I noticed
getUTCtime() from std.date works a bit unexpected:

import std.stdio;
import std.date : getUTCtime;

int main(char[][] args)
{
	for (int i=0;i<500;i++)
		writefln(getUTCtime());
	return 0;
}

results in (shortened version, for obvious reasons):

1175692021281
1175692021281
1175692021281
1175692021281
1175692021281
1175692021281
1175692021281
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021296
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312
1175692021312

So, it increases as well in large increments
and also in irregular ones, namely
15 and 16 milliseconds.

Since I found nothing in the phobos docs,
how can I access the current time at a more
precise level?

david
Apr 04 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
david wrote:
 I was just playing with a slow down class, when I noticed
 getUTCtime() from std.date works a bit unexpected:
 
 import std.stdio;
 import std.date : getUTCtime;
 
 int main(char[][] args)
 {
     for (int i=0;i<500;i++)
         writefln(getUTCtime());
     return 0;
 }
 
 results in (shortened version, for obvious reasons):
 

 
 So, it increases as well in large increments
 and also in irregular ones, namely
 15 and 16 milliseconds.
 
 Since I found nothing in the phobos docs,
 how can I access the current time at a more
 precise level?

The precision of the clock is operating-system dependent AFAIK. (including the version of the OS and obviously the type of machine it's running on) D can't make it more accurate than the OS is willing to provide :(. (Your post header indicates you're running Windows) On Windows, there are (at least) two functions to get the current time: one returns it as a SYSTEMTIME structure, one as a FILETIME structure. It looks like std.date uses GetSystemTime; you could try to see if GetFileTime is more accurate. (no idea why it would be, but you could try...) Try this: --- import std.c.windows.windows : GetSystemTimeAsFileTime, FILETIME; import std.date; d_time currentFileTime() { FILETIME ft; GetSystemTimeAsFileTime(&ft); return std.date.FILETIME2D_time(ft); } --- (Coded with no access to a Windows computer, so completely untested. I just had the std.date source and pages referenced from http://msdn2.microsoft.com/en-us/library/ms725479.aspx to work with)
Apr 04 2007
parent reply david <tazz gmx.at> writes:
Frits van Bommel schrieb:
 david wrote:
 I was just playing with a slow down class, when I noticed
 getUTCtime() from std.date works a bit unexpected:

 import std.stdio;
 import std.date : getUTCtime;

 int main(char[][] args)
 {
     for (int i=0;i<500;i++)
         writefln(getUTCtime());
     return 0;
 }

 results in (shortened version, for obvious reasons):

 So, it increases as well in large increments
 and also in irregular ones, namely
 15 and 16 milliseconds.

 Since I found nothing in the phobos docs,
 how can I access the current time at a more
 precise level?

The precision of the clock is operating-system dependent AFAIK. (including the version of the OS and obviously the type of machine it's running on) D can't make it more accurate than the OS is willing to provide :(. (Your post header indicates you're running Windows) On Windows, there are (at least) two functions to get the current time: one returns it as a SYSTEMTIME structure, one as a FILETIME structure. It looks like std.date uses GetSystemTime; you could try to see if GetFileTime is more accurate. (no idea why it would be, but you could try...) Try this: --- import std.c.windows.windows : GetSystemTimeAsFileTime, FILETIME; import std.date; d_time currentFileTime() { FILETIME ft; GetSystemTimeAsFileTime(&ft); return std.date.FILETIME2D_time(ft); } --- (Coded with no access to a Windows computer, so completely untested. I just had the std.date source and pages referenced from http://msdn2.microsoft.com/en-us/library/ms725479.aspx to work with)

Thanks for the idea, but as you thought the precision is the same, d_time currentFileTime() { FILETIME ft; GetSystemTimeAsFileTime(&ft); return std.date.FILETIME2d_time(&ft); } yields the same result as getUTCtime(). (And for that matter, as a direct GetSystemTime().)
Apr 04 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
david wrote:
 Frits van Bommel schrieb:
 (Your post header indicates you're running Windows)
 On Windows, there are (at least) two functions to get the current 
 time: one returns it as a SYSTEMTIME structure, one as a FILETIME 
 structure. It looks like std.date uses GetSystemTime; you could try to 
 see if GetFileTime is more accurate. (no idea why it would be, but you 
 could try...)


 
 Thanks for the idea,
 but as you thought the precision is the same,
 d_time currentFileTime()
 {
     FILETIME ft;
     GetSystemTimeAsFileTime(&ft);
     return std.date.FILETIME2d_time(&ft);
 }
 yields the same result as getUTCtime().
 (And for that matter, as a direct GetSystemTime().)

Yeah, it's probably just because your Windows version didn't set whatever timer source it uses to >= 1000 ticks/second. Understandable, since short timer ticks probably have a negative effect on performance. I also wouldn't be surprised to find out that different versions of the same OS used differently sized timer ticks (getting shorter with more recent versions since CPUs keep getting faster and performance penalties may drop because of it). Or for that matter, if the size of a tick can be different on two machines running on the same version of the same OS if one machine doesn't have a particular (better) timer source in the hardware that the other does, or if the OS decides that a faster computer can handle shorter timer ticks...
Apr 04 2007
parent reply Sean Kelly <sean f4.ca> writes:
Frits van Bommel wrote:
 
 Yeah, it's probably just because your Windows version didn't set 
 whatever timer source it uses to >= 1000 ticks/second. Understandable, 
 since short timer ticks probably have a negative effect on performance.

Right. I think the Windows system clock has a resolution of around 10ms. However, I believe there are ways to obtain higher-resolution timing information, either using realtime features, the multimedia API, or by some other means. I couldn't name actual API calls offhand though. Sean
Apr 04 2007
next sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Sean Kelly wrote

 I believe there are ways to obtain higher-resolution timing
 information

What about this: import std.stdio; import internal.trace: QueryPerformanceCounter; int main(char[][] args) { long t; for (int i=0;i<500;i++){ QueryPerformanceCounter( &t); writefln(t); } return 0; } -manfred
Apr 05 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Manfred Nowak" <svv1999 hotmail.com> wrote in message 
news:ev2nlr$cfa$1 digitalmars.com...
 Sean Kelly wrote

 I believe there are ways to obtain higher-resolution timing
 information

What about this: import std.stdio; import internal.trace: QueryPerformanceCounter; int main(char[][] args) { long t; for (int i=0;i<500;i++){ QueryPerformanceCounter( &t); writefln(t); } return 0; } -manfred

std.perf.HighPerformanceCounter uses the same Windows API but will convert to seconds, milliseconds, and microseconds for you. It's cross-platform, too, using gettimeofday on *nix platforms. Unfortunately if David is looking to use this as a timestamp, i.e. in files, the value you get from QPC doesn't represent any useful amount of time IIRC. It's just a counter incremented by the processor from the time the computer starts.
Apr 05 2007
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Jarrett Billingsley wrote

 Unfortunately if David is looking to use this as a timestamp

In the OP it says: | playing with a slow down class -manfred
Apr 05 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Manfred Nowak" <svv1999 hotmail.com> wrote in message 
news:ev3jhs$28o4$1 digitalmars.com...
 Jarrett Billingsley wrote

 Unfortunately if David is looking to use this as a timestamp

In the OP it says: | playing with a slow down class -manfred

I... don't know what that is.
Apr 05 2007
parent reply david <tazz gmx.at> writes:
Jarrett Billingsley schrieb:
 "Manfred Nowak" <svv1999 hotmail.com> wrote in message 
 news:ev3jhs$28o4$1 digitalmars.com...
 Jarrett Billingsley wrote

 Unfortunately if David is looking to use this as a timestamp

| playing with a slow down class -manfred

I... don't know what that is.

Sorry, here's a draft of the class. I'm sure there is a proper name for its funtionality, I just don't know it. david import std.date : d_time, getUTCtime; // todo: perhaps check in syncCycle if startCycle has been called before at all (costs how much time?) /** * prevents a program from running too fast by mapping code to time intervals * note: timer increments are only in quantities of ~15 or ~16 milliseconds, * inbetween these intervals there is no increment $(BR) * therefore, the timing can be off ~15 or ~16 milliseconds */ /** Example: * Assures that after code A is finished at least 100 milliseconds have passed before code C is executed * --- * Sync sync = new Sync; * ... some code A ... * sync.startCycle(); * ... some code B ... * sync.syncCycle(100); * ... some code C ... * --- */ class Sync { d_time startTime; d_time passedTime; /// set the current time as the reference point void startCycle() { startTime = getUTCtime(); } /** wait until msecs milliseconds have passed * since startCycle() has been called last $(BR) * if msecs or more milliseconds have passed already, return immediately */ void syncCycle(d_time msecs) { passedTime = getUTCtime() - startTime; while (passedTime < msecs) // todo: replace passedTime by expression "getUTC... - startT..." passedTime = getUTCtime() - startTime; } }
Apr 07 2007
next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
david wrote:
 Jarrett Billingsley schrieb:
 "Manfred Nowak" <svv1999 hotmail.com> wrote in message 
 news:ev3jhs$28o4$1 digitalmars.com...
 Jarrett Billingsley wrote

 Unfortunately if David is looking to use this as a timestamp

| playing with a slow down class -manfred

I... don't know what that is.

Sorry, here's a draft of the class. I'm sure there is a proper name for its funtionality, I just don't know it. david import std.date : d_time, getUTCtime; // todo: perhaps check in syncCycle if startCycle has been called before at all (costs how much time?) /** * prevents a program from running too fast by mapping code to time intervals * note: timer increments are only in quantities of ~15 or ~16 milliseconds, * inbetween these intervals there is no increment $(BR) * therefore, the timing can be off ~15 or ~16 milliseconds */ /** Example: * Assures that after code A is finished at least 100 milliseconds have passed before code C is executed * --- * Sync sync = new Sync; * ... some code A ... * sync.startCycle(); * ... some code B ... * sync.syncCycle(100); * ... some code C ... * --- */ class Sync { d_time startTime; d_time passedTime; /// set the current time as the reference point void startCycle() { startTime = getUTCtime(); } /** wait until msecs milliseconds have passed * since startCycle() has been called last $(BR) * if msecs or more milliseconds have passed already, return immediately */ void syncCycle(d_time msecs) { passedTime = getUTCtime() - startTime; while (passedTime < msecs) // todo: replace passedTime by expression "getUTC... - startT..." passedTime = getUTCtime() - startTime; } }

Aka, you want it to lock the application to a certain "frame rate", aye? I'm really not sure what the technical term is either, so I usually just state the obvious descriptor: "frame rate lock". ;P In this case, perfect precision may not be neccessary anyhow... but I guess that all depends on what you are implementing with it. -- Chris Nicholson-Sauls
Apr 07 2007
prev sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"david" <tazz gmx.at> wrote in message news:ev9brv$jo0$1 digitalmars.com...
 Sorry, here's a draft of the class.
 I'm sure there is a proper name for its funtionality,
 I just don't know it.

 david


 import std.date : d_time, getUTCtime;

 // todo: perhaps check in syncCycle if startCycle has been called before 
 at all (costs how much time?)
 /**
  * prevents a program from running too fast by mapping code to time 
 intervals
  * note: timer increments are only in quantities of ~15 or ~16 
 milliseconds,
  * inbetween these intervals there is no increment $(BR)
  * therefore, the timing can be off ~15 or ~16 milliseconds
  */
 /** Example:
  * Assures that after code A is finished at least 100 milliseconds have 
 passed before code C is executed
  * ---
  * Sync sync = new Sync;
  * ... some code A ...
  * sync.startCycle();
  * ... some code B ...
  * sync.syncCycle(100);
  * ... some code C ...
  * ---
  */
 class Sync
 {
 d_time startTime;
 d_time passedTime;

 /// set the current time as the reference point
 void startCycle()
 {
 startTime = getUTCtime();
 }

 /** wait until msecs milliseconds have passed
 *  since startCycle() has been called last $(BR)
 *  if msecs or more milliseconds have passed already, return immediately
 */
 void syncCycle(d_time msecs)
 {
 passedTime = getUTCtime() - startTime;
 while (passedTime < msecs) // todo: replace passedTime by expression 
 "getUTC... - startT..."
 passedTime = getUTCtime() - startTime;
 }
 }

Ahhh, I guess this would be a "frame rate limiter", at least that's what I've heard it called a lot. Well hey, if getUTCtime() increases with exactly 16ms increments -- there you go, perfect 60FPS ;)
Apr 08 2007
prev sibling parent KlausO <oberhofer users.sf.net> writes:
Sean Kelly schrieb:
 Frits van Bommel wrote:
 Yeah, it's probably just because your Windows version didn't set 
 whatever timer source it uses to >= 1000 ticks/second. Understandable, 
 since short timer ticks probably have a negative effect on performance.

Right. I think the Windows system clock has a resolution of around 10ms. However, I believe there are ways to obtain higher-resolution timing information, either using realtime features, the multimedia API, or by some other means. I couldn't name actual API calls offhand though. Sean

You mean the timeXXX-API e.g. timeBeginPeriod timeEndPeriod timeGetSystemTime
Apr 05 2007