VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Public support forum for peer to peer support with related to the Visual Objects and Vulcan.NET products
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Post by wriedmann »

Hi Karl-Heinz,

I'm using this function only for performance measurements, because it seemed more precise than other funtions.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Post by Karl-Heinz »

Hi Wolfgang,

Honestly: Even if it would be for performance measurements only, i would never ever use this GetTickCountLow() nonsense !

regards
Karl-Heinz
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Post by wriedmann »

Hi Karl-Heinz,

yes, now that I know its problems, I have replaced this function with the one from the Windows API.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
ic2
Posts: 1858
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Post by ic2 »

But we have to admit that the times of the desktop computers as the main IT instrument have finished....So we can be glad if Microsoft modernizes that world and that most of our program code is still working.


Hello Arne,

That depends. It's true that people do a lot of lookups and message reading & sending with mobile phones. Of course Pc's are much easier to use for that, with proper keyboards and easier access to stored data etc, but apparently many people prefer their phone for that because they always have it switched on and near them, also outside home. But none of the major functions most of us are programming for can be done without Pc's. In the past few years I've written only one smartphone + 1 tablet app for clients who paid me for that. Some other apps are in the Microsoft Store but I won't make (real) money with it. So I am not sure if Microsoft has done much here which improved the world (quite some modernizing in technology hasn't improved anything or even did the reverse).
Hmmm, we're getting a bit off topic so we should probably move it to chit-chat...

Dick
User avatar
Otto
Posts: 174
Joined: Wed Sep 30, 2015 6:22 pm

VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Post by Otto »

To whom this may concern:
If you want to use GetTickCount64() in VO (thanks to Robert):

Code: Select all

function T() as void strict
    local mystruct is myint64
    local f as float 
    mystruct.r8 := GetTickCount64()
    ?
    // in a float you could loose data, because e.g. float is signed.
    f := mystruct.ul.LowPart * 1.0 + mystruct.ul.HighPart * 0xFFFFFFFFU
    ? Str(f,-1,0)
    // the raw data, without loss.
    ? mystruct.ul.HighPart , mystruct.ul.LowPart

    return

function Start()
    ? "Hello World"
    do while true
        T()
        // the pause is not exact, so the interval is not exact either
        Sleep(100)
    end
    WAIT
    return nil

_dll function GetTickCount64() as real8 pascal:Kernel32.GetTickCount64
    // returns 8 bytes
    // _winULARGE_INTEGER

union myint64
    member r8 as real8
    member ul is _winULARGE_INTEGER
ic2
Posts: 1858
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Post by ic2 »

Hello Otto,

Thanks for this follow up message. However, I do not understand what I should do to use it.

We now have:

dwTicks := GetTickCountLow()

This is supposed to :
Get the number of 1/10000 seconds that have elapsed since Windows was started.

The sample program is a loop with a pause function.

How is this supposed to give that number of 1/10000 seconds?

Dick
User avatar
Otto
Posts: 174
Joined: Wed Sep 30, 2015 6:22 pm

VO 2.8: GetTickCountLow() does not seem to work correctly anymore

Post by Otto »

I used the loop to test what the effect on memory was and check what the interval between the calls is.
You can use the float interpretation of the memory block. As described in the formula.
you can use the upper and lower part of the numbers as dwords and work from there.
GetTickCountLow stops after 4 days (because than you'll run out off the counters range.

GetTickCount64 has more memory, and you'll probably won't live long enough to see running that out of range.
As noted by Microsoft: GetTickCount64 is in milliseconds, so 1/1000, and has resolution issues.
GetTickCount64 on Microsoft

GetTickCountLow() does have those as well. To bad we don't have the code of the runtime so we don't know what's in that concoction.

There are other options.
Personally I used the QueryPerformanceCounter and QueryPerformanceFrequency to get a higher resolution like in the following example of a stopwatch.
Calculations however cost time as well... so if you get a lot of data, converting the raw QueryPerformanceCounter data to fractions of seconds could be better done at the end of the process, when you are ready to report.

Code: Select all

class StopWatch3
    protect StartMoment_high as longint
    protect StartMoment_Low as dword
    protect Frequency as dword
    
    declare method Start
    declare method Stop
    
method Init() class StopWatch3
    // frequency added to make the recorded time comparable independend of the hardware etc.
    local frequency_high := GetQueryPerformanceFrequencyHigh() as longint
    self:Frequency := GetQueryPerformanceFrequencyLow()
    if frequency_high != 0
        _DebOut32(String2Psz("GetQueryPerformanceFrequencyHigh() != 0! (" + NTrim(frequency_high) + ")"))
    endif
    
    return self

method Start() as void strict class StopWatch3

    local start_high as longint
    local start_low as dword
    GetQueryPerformanceCounter(@start_high,@start_low)
    
    self:StartMoment_high := start_high
    self:StartMoment_Low := start_low
    
    return
    
method Stop() as real8 strict class StopWatch3
    //#l get the elapsed time upto now since the Start.
    
    local stop_high as longint
    local stop_low as dword
    local delta as dword
    
    GetQueryPerformanceCounter(@stop_high,@stop_low)
    delta := hldif(stop_high,stop_low,self:StartMoment_high,self:StartMoment_Low)
    return real8(delta)/Frequency 

function GetQueryPerformanceFrequencyHigh() as longint strict
    
    local lpFreqebcy is _WINLARGE_INTEGER
    QueryPerformanceFrequency(@lpFreqebcy)
    return lpFreqebcy.u.HighPart

function GetQueryPerformanceCounter(highPart ref longint , LowPart ref dword) as void strict
    local qpcValue is _WINLARGE_INTEGER
    QueryPerformanceCounter(@qpcValue)
    HighPart := qpcValue.u.HighPart
    LowPart := qpcValue.u.LowPart
    return 

function hldif(ah as longint,al as dword, bh as longint, bl as dword ) as dword strict
    //#l calculate a-b
    //#l assume a>b
    //#l assume that the difference is lower than dword_max
    
    local highPartDiff as longint

    highPartDiff := ah-bh

    do case
    case highPartDiff == 0
        do case
        case al==bl
            return 0u
        case al<bl
            // wtf?
            return maxdword
        otherwise
            return al-bl
        endcase
    case highPartDiff == 1
        if al>= bl
            // would be a overflow
            return maxdword
        else
            return al + (maxdword-bl)
        endif
    case highPartDiff < 0 
        // wtf?
        return maxdword
    case highPartDiff > 1
        // would be a overflow
        return maxdword
    endcase

    return 0
If you go into .NET, don't use this. There is a lot better stuff there.
Post Reply