The solution you mean is no "how to use ElapsedMilliseconds" but different function and not multi-platform (as I wrote you could use gettimeofday() on linux). Using quads was suggested here as well. But there is nothing wrong with ElapsedMilliseconds (GetTickCount) as it is if you just know how to use it.MachineCode wrote:What? A real-world solution is posted in the other thread and uses quads for the difference
Be careful with ElapsedMilliseconds() in certain cases
Re: Be careful with ElapsedMilliseconds() in certain cases
Re: Be careful with ElapsedMilliseconds() in certain cases
So am I right in assuming that ElapsedMilliseconds() is now a Quad in PureBasic 5.50, and that it's more accurate than GetTickCount_() and should be used instead of GetTickCount_() for timing references? It will not return a negative after 49.7 days like GetTickCount_(), correct? If this is all correct, then I can go ahead and search/replace all my sources to use it. 

- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Re: Be careful with ElapsedMilliseconds() in certain cases
It returns a quad and uses QueryPerformanceCounter_(). Wrapping issues from before the change are no longer of concern.
MSDN wrote:QPC is typically the best method to use to time-stamp events and measure small time intervals that occur on the same system or virtual machine.
BERESHEIT
Re: Be careful with ElapsedMilliseconds() in certain cases
Thanks for confirming. So it's good for timing only, and no longer returns the system up-time, right?
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Re: Be careful with ElapsedMilliseconds() in certain cases
It's still system uptime but in a much higher-res api than GetTickCount. Be aware though, it is going to roll over on you as well - if you leave your system up for 290 years.
BERESHEIT
Re: Be careful with ElapsedMilliseconds() in certain cases
LOL!!!!!!!!!


netmaestro wrote:* Be aware though, it is going to roll over on you as well - if you leave your system up for 290 years.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Re: Be careful with ElapsedMilliseconds() in certain cases
Ah crap... I better code a different method instead, that is 290-year-proof.netmaestro wrote:it is going to roll over on you as well - if you leave your system up for 290 years.

Re: Be careful with ElapsedMilliseconds() in certain cases
For fun: This code check the time-base for the QueryPerformanceCounter, the base for ElapsedMilliseconds since years.
Need the inpout32.dll/inpoutx64.dll (for download see google)
Result on my PC:
Edit: Change GetSystemInfo to GetNativeSystemInfo and then check for 64-Bit-OS with 32-Bit-PB
__________________________________________________
IMG tags repaired
29.08.2016
RSBasic
Need the inpout32.dll/inpoutx64.dll (for download see google)
Result on my PC:
Code: Select all
;Test with Windows7/64, PureBasic 5.43 LTS (x64) / PureBasic 5.50 (x64), Windows XP (32-Bit) and PureBasic 5.50 (x86)
;Power Management Timer = PMT = 3.579545 MHz, color burst frequency used by NTSC
;Programmable Interval Timer = PIT = 1.193182 MHz, one third of the color burst frequency used by NTSC
;Need inpout32.dll/inpoutx64.dll (for download see google) in this directory
;x86 and x64, Ascii and Unicode
;"Helle" Klaus Helbing, Aug. 30, 2016
Freq.q
Start.q
Ende.q
RDTSC1.q
RDTSC2.q
Base_ClockI.q
TA.q
TE.q
HPET_Freq.d
Base_Clock.d
ITSC.l
MaxIDExt.l
HPET_Resolution.l
Value1.l
Value2.l
#PROCESSOR_ARCHITECTURE_AMD64 = $9
#HPET_Address = $FED00000 ;most, or check your Windows-Device-Manager
Prototype GetNativeSystemInfo(*lpSystemInfo.SYSTEM_INFO)
Procedure Is64bitOS()
Protected Kernel32, GetNativeSystemInfo.GetNativeSystemInfo
Protected Info.SYSTEM_INFO
Protected Result = #False
Kernel32 = OpenLibrary(#PB_Any, "Kernel32.dll")
If Kernel32
GetNativeSystemInfo = GetFunction(Kernel32, "GetNativeSystemInfo")
If GetNativeSystemInfo
GetNativeSystemInfo(@Info)
If Info\wProcessorArchitecture = #PROCESSOR_ARCHITECTURE_AMD64 ;x64
Result = #True
EndIf
EndIf
CloseLibrary(Kernel32)
EndIf
ProcedureReturn Result
EndProcedure
CPU$ = Space(48) ;96 Bytes in Unicode
S1.l ;for CPU-String x86/x64 and ASCI/Unicode
S2.l
S3.l
S4.l
Z.l
;CPU-String
While Z < 3
!mov eax,80000002h
!add eax,[v_Z]
!cpuid
!mov [v_S1],eax
!mov [v_S2],ebx
!mov [v_S3],ecx
!mov [v_S4],edx
PokeL(@CPU$ + (Z << 4), S1)
PokeL(@CPU$ + (Z << 4) + 4, S2)
PokeL(@CPU$ + (Z << 4) + 8, S3)
PokeL(@CPU$ + (Z << 4) + 12, S4)
Z + 1
Wend
Result$ = "CPU: " + PeekS(@CPU$, #PB_Any, #PB_Ascii) + #LFCR$
;Check CPU for Invariant TSC
ITSC$ = " Available"
!mov eax,80000000h ;check for max. Extended Level, Intel and AMD
!cpuid
!mov [v_MaxIDExt],eax ;max. ExtID, 8000000xh
If (MaxIDExt & $FFFFFFFF) < $80000007
ITSC$ = "Not available"
Else
!mov eax,80000007h
!cpuid
!and edx,100000000b ;Flag Invariant TSC
!mov [v_ITSC],edx
!jnz @f
ITSC$ = "Not available"
!@@:
EndIf
QueryPerformanceFrequency_(@Freq) ;const., determined during windows-system initialization and doesn't change while the windows-system is running.
Result$ + "QueryPerformanceFrequency (Hz): " + Str(Freq) + #LFCR$
Result$ + "Invariant Time Stamp Counter (ITSC): " + ITSC$ + #LFCR$
If Freq = 0
Result$ + "QueryPerformanceCounter: Not available. End."
Else
;Check for HPET (High Precision Event Timers)
;Check for 32- or 64-Bit-OS
If Is64bitOS()
If #PB_Compiler_Processor = #PB_Processor_x86
MessageRequester("Error!", "64-Bit-OS and 32-Bit-PB --> No Way! End.")
End
EndIf
DLLOK = OpenLibrary(0, "inpoutx64.dll") ;64-Bit-Version, for download see google
Else
DLLOK = OpenLibrary(0, "inpout32.dll") ;32-Bit-Version, for download see google
EndIf
If DLLOK
Prototype.i ProtoIO_0()
IO_IsOpen.ProtoIO_0 = GetFunction(0, "IsInpOutDriverOpen")
Prototype.i ProtoIO_2(physAddr.l, physVal.l)
IO_GetPhysLong.ProtoIO_2 = GetFunction(0, "GetPhysLong")
If IO_IsOpen()
IO_GetPhysLong(#HPET_Address + 4, @HPET_Resolution) ;read the Resolution in Femtoseconds (10^-15 Seconds), see HPET-Documentation
If HPET_Resolution
Result$ + "High Precision Event Timers (HPET): Available" + #LFCR$
Result$ + "Resolution HPET (ns): " + StrD(HPET_Resolution / 1e6, 6) + #LFCR$
HPET_Freq = 1e15 / HPET_Resolution
Result$ + "This gives the HPET-Frequency (Hz): " + Str(HPET_Freq) + #LFCR$
If ITSC
;for tests. SetThreadAffinityMask: MS says: No!
;hThread = GetCurrentThread_()
;Core = 4 ;CPU_2
;SetThreadAffinityMask_(hThread, Core)
;;hProcess = GetCurrentProcess_()
;;SetPriorityClass_(hProcess, #REALTIME_PRIORITY_CLASS) ;for hard!
;SetThreadPriority_(hThread, #THREAD_PRIORITY_TIME_CRITICAL)
While Value2 <= Value1
IO_GetPhysLong(#HPET_Address + $F0, @Value1) ;read only Low
!rdtsc
!mov dword[v_RDTSC1],eax
!mov dword[v_RDTSC1+4],edx
;Simple Time-Loop for Calibration
!mov ecx,0FFFFFFFFh ;any value for this test
!@@:
!dec ecx
!jnz @b
IO_GetPhysLong(#HPET_Address + $F0, @Value2) ;read only Low
!rdtsc
!mov dword[v_RDTSC2],eax
!mov dword[v_RDTSC2+4],edx
Wend
Base_Clock = (RDTSC2 - RDTSC1) / ((Value2 - Value1) / HPET_Freq)
Result$ + "This gives the CPU-Base-Clock (Hz): " + StrD(Base_Clock, 0) + #LFCR$
Base_ClockI = Base_Clock
Result$ + "CPU-Base-Clock >> 10: " + Str(Base_ClockI >> 10) + #LFCR$
Result$ + "QueryPerformanceFrequency << 10: " + Str(Freq << 10) + #LFCR$
Result$ + "Info Resolution QPC (ns): " + StrD(1e9 / Freq, 6) + #LFCR$
Result$ + "QueryPerformance Base: " + "Invariant Time Stamp Counter (ITSC)" + #LFCR$
Result$ + "Test with QPC and ITSC:" + #LFCR$
TA = ElapsedMilliseconds()
QueryPerformanceCounter_(@Start)
!rdtsc
!mov dword[v_RDTSC1],eax
!mov dword[v_RDTSC1+4],edx
Delay(1234) ;or any code
TE = ElapsedMilliseconds()
QueryPerformanceCounter_(@Ende)
!rdtsc
!mov dword[v_RDTSC2],eax
!mov dword[v_RDTSC2+4],edx
Result$ + "QueryPerformanceCounter_Start: " + Str(Start) + #LFCR$
Result$ + "RDTSC_Start: " + Str(RDTSC1) + #LFCR$
Result$ + "RDTSC_Start >> 10: " + Str(RDTSC1 >> 10) + #LFCR$
Result$ + "After Delay(any value) or any code:" + #LFCR$
Result$ + "QueryPerformanceCounter_End: " + Str(Ende) + #LFCR$
Result$ + "RDTSC_End: " + Str(RDTSC2) + #LFCR$
Result$ + "RDTSC_End >> 10: " + Str(RDTSC2 >> 10) + #LFCR$
Result$ + "QPC_End - QPC_Start: " + Str(Ende - Start) + #LFCR$
Result$ + "RDTSC_End - RDTSC_Start: " + Str(RDTSC2 - RDTSC1) + #LFCR$
Result$ + "(RDTSC_End - RDTSC_Start) >> 10: " + Str((RDTSC2 - RDTSC1) >> 10) + #LFCR$
Result$ + "Elapsed Time QPC (ms): " + StrD((((Ende - Start) / Freq) * 1000), 6) + #LFCR$
Result$ + "Elapsed Time RDTSC (ms): " + StrD((((RDTSC2 - RDTSC1) / Base_Clock) * 1000), 6) + #LFCR$
Result$ + "ElapsedMilliseconds PB (ms): " + Str(TE - TA) + #LFCR$
Result$ + "Overflow signed QPC (PB-Quad) on this PC in: " + Str((9223372036854775807 / Base_ClockI) / (60*60*24*365)) + " Years" ;Start ignored, or calculate precise... :-)
Else
Result$ + "QueryPerformance Base: " + "High Precision Event Timers (HPET)" + #LFCR$
EndIf
Else
Result$ + "High Precision Event Timers (HPET): Not available" + #LFCR$
If Freq > 3579540 And Freq < 3579550 ;3579545 Hz
QP$ = "Power Management Timer (PMT)"
ElseIf Freq > 1193180 And Freq < 1193185 ;1193182 Hz
QP$ = "Programmable Interval Timer (PIT)"
Else
QP$ = "Not detected"
EndIf
Result$ + "QueryPerformance Base: " + QP$ + #LFCR$
EndIf
Else
MessageRequester("Error!", "Can not open inpoutxx.dll! End.")
End
EndIf
Else
MessageRequester("Error!", "Can not open inpoutxx.dll! End.")
End
EndIf
EndIf
If IsLibrary(0)
CloseLibrary(0)
EndIf
MessageRequester("QueryPerformanceCounter-Test", Result$)
__________________________________________________
IMG tags repaired
29.08.2016
RSBasic
Last edited by Helle on Tue Aug 30, 2016 10:58 am, edited 1 time in total.
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Re: Be careful with ElapsedMilliseconds() in certain cases
Looks very good but I'm getting an IMA on line 91: If IO_IsOpen(). Win 7 x64, PB 5.50 x86. I have both versions of the inpout.dll in System32 along with the .sys driver file.
BERESHEIT
Re: Be careful with ElapsedMilliseconds() in certain cases
See changed code above. 64-Bit-OS and (with) 32-Bit-PB --> No Way! For hardware-accesses is this not a good idea...