Recent

Author Topic: Free Pascal GetTickCount  (Read 8153 times)

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Free Pascal GetTickCount
« on: August 17, 2017, 07:24:50 pm »
Hi

In Linux GetTickCount64 depends on clockgettime that returns a monotonic measure of time instances. Please, can you confirm if windows and mac (maybe others) implements monotonic time as well?

I would really appreciate if you copy and paste the implementation of GetTickCount64 of your actual system here (pointing it to the source?).

Best
Be mindful and excellent with each other.
https://github.com/cpicanco/

Mick

  • Jr. Member
  • **
  • Posts: 51
Re: Free Pascal GetTickCount
« Reply #1 on: August 17, 2017, 07:45:59 pm »
Hi, I'm not sure if this is what you are asking for, but on Windows the implementations for both GetTickCount and GetTickCount64 just use WinAPI calls to kernel32.dll (sysutilh.inc, line 28 and 29 in interface section, the implementation in lines 623 and 637). This info is taken from my Lazarus 1.6.2 (FPC 3.0.0 SVN rev. 53354).
In case if you need to have some details of the actual implementation, I'd suggest to look at MSDN pages:
https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms724408(v=vs.85).aspx
https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms724411(v=vs.85).aspx
« Last Edit: August 17, 2017, 07:47:59 pm by Mick »

RAW

  • Hero Member
  • *****
  • Posts: 868
Re: Free Pascal GetTickCount
« Reply #2 on: August 17, 2017, 07:48:02 pm »
Works nice...  :)
Code: Pascal  [Select][+][-]
  1. Procedure TForm1.FormClick(Sender: TObject);
  2.   Var
  3.    cStart, cStop: Cardinal;
  4.  Begin
  5.   cStart:= GetTickCount64;
  6.    Sleep(1000);
  7.   cStop:= GetTickCount64-cStart;
  8.   ShowMessage(IntToStr(cStop));
  9.  End;

//GetTickCount64 requires Windows Vista/Windows Server 2008 or higher
Do you mean this...
Code: Pascal  [Select][+][-]
  1. {$IFNDEF WINCE}
  2. type
  3.   TGetTickCount64 = function : QWord; stdcall;
  4.  
  5. var
  6.   WinGetTickCount64: TGetTickCount64 = Nil;
  7. {$ENDIF}
  8.  
  9. function GetTickCount64: QWord;
  10. {$IFNDEF WINCE}
  11. var
  12.   lib: THandle;
  13. {$ENDIF}
  14. begin
  15. {$IFNDEF WINCE}
  16.   { on Vista and newer there is a GetTickCount64 implementation }
  17.   if Win32MajorVersion >= 6 then begin
  18.     if not Assigned(WinGetTickCount64) then begin
  19.       lib := LoadLibrary('kernel32.dll');
  20.       WinGetTickCount64 := TGetTickCount64(
  21.                              GetProcAddress(lib, 'GetTickCount64'));
  22.     end;
  23.     Result := WinGetTickCount64();
  24.   end else
  25. {$ENDIF}
  26.     Result := Windows.GetTickCount;
  27. end;
Windows 7 Pro (x64 Sp1) & Windows XP Pro (x86 Sp3).

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: Free Pascal GetTickCount
« Reply #3 on: August 17, 2017, 07:49:55 pm »
In Linux GetTickCount64 depends on clockgettime that returns a monotonic measure of time instances. Please, can you confirm if windows and mac (maybe others) implements monotonic time as well?

I would really appreciate if you copy and paste the implementation of GetTickCount64 of your actual system here (pointing it to the source?).

On Windows, GetTickCount64() (and its predecessor, GetTickCount()) is an OS function, not an RTL function.  And yes, they are monotonic, counting milliseconds elapsed since OS startup.

Do note that on *nix systems, clock_gettime(CLOCK_MONOTONIC) does not account for system suspension, though.  The timer stops counting, and then starts again when the system is resumed.  GetTickCount/64() on Windows does not stop counting during system suspension.
« Last Edit: August 17, 2017, 08:08:14 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Free Pascal GetTickCount
« Reply #4 on: August 17, 2017, 08:00:48 pm »
Ok, I have found the windows docs that mention the word "monotonic":

https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx

Down there.
Be mindful and excellent with each other.
https://github.com/cpicanco/

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: Free Pascal GetTickCount
« Reply #5 on: August 17, 2017, 08:06:03 pm »
Code: Pascal  [Select][+][-]
  1. {$IFNDEF WINCE}
  2. type
  3.   TGetTickCount64 = function : QWord; stdcall;
  4.  
  5. var
  6.   WinGetTickCount64: TGetTickCount64 = Nil;
  7. {$ENDIF}
  8.  
  9. function GetTickCount64: QWord;
  10. {$IFNDEF WINCE}
  11. var
  12.   lib: THandle;
  13. {$ENDIF}
  14. begin
  15. {$IFNDEF WINCE}
  16.   { on Vista and newer there is a GetTickCount64 implementation }
  17.   if Win32MajorVersion >= 6 then begin
  18.     if not Assigned(WinGetTickCount64) then begin
  19.       lib := LoadLibrary('kernel32.dll');
  20.       WinGetTickCount64 := TGetTickCount64(
  21.                              GetProcAddress(lib, 'GetTickCount64'));
  22.     end;
  23.     Result := WinGetTickCount64();
  24.   end else
  25. {$ENDIF}
  26.     Result := Windows.GetTickCount;
  27. end;

It is usually better to not rely on OS version checking like that (especially since Win32MajorVersion is just a variable in memory and subject to memory corruption).  It is better to just check if the function actually exists, and if not then fallback to the older function

Also, the code should be using GetModuleHandle() instead of LoadLibrary(), since kernel32.dll is guaranteed to already be in memory, so LoadLibrary() would just increment its reference count, which is not necessary.

Code: Pascal  [Select][+][-]
  1. {$IFNDEF WINCE}
  2. type
  3.   TGetTickCount64 = function : QWord; stdcall;
  4.  
  5. var
  6.   WinGetTickCount64: TGetTickCount64 = Nil;
  7.  
  8. function GetTickCount64_Fallback: QWord; stdcall;
  9. begin
  10.   Result := Windows.GetTickCount;
  11. end;
  12. {$ENDIF}
  13.  
  14. function GetTickCount64: QWord;
  15. begin
  16. {$IFNDEF WINCE}
  17.   { on Vista and newer there is a GetTickCount64 implementation }
  18.   if not Assigned(WinGetTickCount64) then begin
  19.     WinGetTickCount64 := TGetTickCount64(GetProcAddress(GetModuleHandle('kernel32.dll'), 'GetTickCount64'));
  20.     if WinGetTickCount64 = nil then
  21.       WinGetTickCount64 := @GetTickCount64_Fallback;
  22.   end;
  23.   Result := WinGetTickCount64();
  24. {$ELSE}
  25.   Result := Windows.GetTickCount;
  26. {$ENDIF}
  27. end;

Indy does something similar, but in a slightly different way:

Code: Pascal  [Select][+][-]
  1. {$IFDEF WINDOWS}
  2. type
  3.   TGetTickCount64Func = function: UInt64; stdcall;
  4.  
  5. var
  6.   GetTickCount64: TGetTickCount64Func = nil;
  7.  
  8. function Impl_GetTickCount64: UInt64; stdcall;
  9. {$IFDEF USE_INLINE}inline;{$ENDIF}
  10. begin
  11.   // TODO: implement some kind of accumulator so the Result
  12.   // keeps growing even when GetTickCount() wraps back to 0
  13.   Result := UInt64(Windows.GetTickCount);
  14. end;
  15.  
  16. function Stub_GetTickCount64: UInt64; stdcall;
  17.  
  18.   function GetImpl: Pointer;
  19.   begin
  20.     Result := GetProcAddress(GetModuleHandle('KERNEL32'), 'GetTickCount64'); {do not localize}
  21.     if Result = nil then begin
  22.       Result := @Impl_GetTickCount64;
  23.     end;
  24.   end;
  25.  
  26. begin
  27.   @GetTickCount64 := GetImpl();
  28.   Result := GetTickCount64();
  29. end;
  30. {$ENDIF}
  31.  
  32. ...
  33.  
  34. initialization
  35.   ...
  36.   {$IFDEF WINDOWS}
  37.   GetTickCount64 := Stub_GetTickCount64;
  38.   {$ENDIF}
  39.   ...
  40. [code]
« Last Edit: August 17, 2017, 08:11:07 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Free Pascal GetTickCount
« Reply #6 on: August 17, 2017, 08:06:54 pm »
Maybe they are overkill, for me, miliseconds would be ok, but they need to be monotonic (do not jump from some custom startting point). Right now I am doing some math to convert to miliseconds.

Edit:

I was talking about clockgettime
« Last Edit: August 18, 2017, 02:59:28 am by cpicanco »
Be mindful and excellent with each other.
https://github.com/cpicanco/

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: Free Pascal GetTickCount
« Reply #7 on: August 17, 2017, 08:09:51 pm »
Ok, I have found the windows docs that mention the word "monotonic":

https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx

That article refers to high-performance timers, which are known to be inaccurate on modern multi-core/hyper-threaded CPUs.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Free Pascal GetTickCount
« Reply #8 on: August 17, 2017, 08:13:08 pm »
I am trying to find some simple and cross-platform solution that implements monotonic time. I am writing training code and the base of the functionality depends on monotonic timestamps. Right now I am on linux, and it is pretty straight forward.

Ok, I have found the windows docs that mention the word "monotonic":

https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx

That article refers to high-performance timers, which are known to be inaccurate on modern multi-core/hyper-threaded CPUs.

Do you known if multi-core machines breaks linux implementation of monotonic time? (clockgettime)
« Last Edit: August 17, 2017, 08:16:33 pm by cpicanco »
Be mindful and excellent with each other.
https://github.com/cpicanco/

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Free Pascal GetTickCount
« Reply #9 on: August 17, 2017, 08:17:29 pm »
GetTickCount64 is listed as a "performance counter".

Edit.:

No no. It does not use the QPC, sorry about that.

« Last Edit: August 17, 2017, 08:22:20 pm by cpicanco »
Be mindful and excellent with each other.
https://github.com/cpicanco/

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Free Pascal GetTickCount
« Reply #10 on: August 17, 2017, 08:28:06 pm »
Quote
Do note that on *nix systems, clock_gettime(CLOCK_MONOTONIC) does not account for system suspension, though.  The timer stops counting, and then starts again when the system is resumed.  GetTickCount/64() on Windows does not stop counting during system suspension.

I am aware of that and thank you for your reminder!
Be mindful and excellent with each other.
https://github.com/cpicanco/

RAW

  • Hero Member
  • *****
  • Posts: 868
Re: Free Pascal GetTickCount
« Reply #11 on: August 18, 2017, 12:07:12 am »
@Remy
Thanks for the info...
I copy & paste it from Lazarus 1.6.4...  :)
Windows 7 Pro (x64 Sp1) & Windows XP Pro (x86 Sp3).

cpicanco

  • Hero Member
  • *****
  • Posts: 618
  • Behavioral Scientist and Programmer
    • Portfolio
Re: Free Pascal GetTickCount
« Reply #12 on: August 18, 2017, 03:01:45 am »
Of course, it is not possible to copy and paste windows implemention. It is private. Black box. Regardless of the results...
« Last Edit: August 18, 2017, 03:04:52 am by cpicanco »
Be mindful and excellent with each other.
https://github.com/cpicanco/

 

TinyPortal © 2005-2018