MacroTimersQPC.inc

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
St_W
Posts: 1483
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: MacroTimersQPC.inc

Postby St_W » Jan 21, 2017 11:18

MrSwiss wrote:[...] for sure, using some strange data types here: Large_Integer (looks like a custom Type), ULongLong (looks like C/C++) etc.

These are Windows Datatypes; see: https://msdn.microsoft.com/en-us/librar ... 83751.aspx

There's nothing wrong with using them in a Windows program using the Win32-API. Actually it's probably even preferable to comply with the documentation and prevent type errors, e.g. the actual type could change on other systems (if there's e.g. something like Win32 on non-x86 architecture).

MrSwiss wrote:I still don't like the .inc stuff on FB, simply because the IDE I'm using (FBEdit) is either not
*highlighting* correctly, or disallows me, to open an .inc from within (after recognizing it).
While .bi is the default for FreeBasic there's nothing wrong with .inc for include; basically a matter of personal preference, which shouldn't be dictated to others having a different opinion. (I'm using FBedit too and also ran into the highlighting issue, though)

@deltarho[1859]: In the code there are "$" suffixes. Are those intentional? The compiler doesn't complain about the syntax, but I guess these should be removed as FB doesn't have type suffixes.

Code: Select all

SetDecimalPlaces$(k)

Thank you for sharing this. I really like that PowerBasic programmers are now considering FreeBasic and do provide very useful, professional quality contributions.
deltarho[1859]
Posts: 2253
Joined: Jan 02, 2017 0:34
Location: UK

Re: MacroTimersQPC.inc

Postby deltarho[1859] » Jan 21, 2017 15:16

@St_W

In the code there are "$" suffixes. Are those intentional?


There are fives instances of SetDecimalPlaces and two of them end with '$'. I don't use suffixes unless I am compelled to. I use my own type of Hungarian Notation - prefixing with an 's' for string for example. I've just checked my own source code in WinFBE and there are the same two offenders. I wondered whether the autocomplete had thrown a 'wobbly' but it doesn't appear so.

I find this so spooky I will need to have a lie down in a darkened room.

I really like that PowerBasic programmers are now considering FreeBasic


My first post was only a couple of weeks ago and I am slowly reading the Help index one item at a time; although coding is getting in the way. <smile> Every now and again I think "Wow, it does what?". Some of the commands are unbelievably powerful.

Thank you for sharing this.


My pleasure and thanks for thanking me.
adele
Posts: 47
Joined: Jun 13, 2015 19:33

Re: MacroTimersQPC.inc

Postby adele » Jan 21, 2017 15:32

[commit][/commit]@deltarho[1859]
Excellent code. But even better is the documentation. Thank you.

But, to stay in "Tips & Tricks":

@MrSwiss
You wrote: "[] don't like the .inc [] because [] (FBEdit) is either not *highlighting* []..."

Trick & Try: enter ".bas.bi.inc." in (FBedit menu) -> optionen->code editor, at "3 o´clock" (== vertical middle / right half )


@deltarho[1859]
Readability: Just cosmetics. I needed it, because in my Virtual Machine I had a deviation of about 0.7 percent just timing the "sleep 500", and up to 17.0 (!!!) percent in your ' TimerUsage.BAS ' . I didn´t want to believe this.
On the real machine, this normalized. But I needed to know what the numbers want to tell me...

Code: Select all

' Cosmetics :)
Print sPerformanceCounterFrequency

StartTimer(0)
  Sleep (500,1)
StopTimer(0)
Print "Slept 500 ms..."
Print sTimeTaken(0, 3, False)
Print

StartTImer(0)
  Sleep (100,1)
Print "Slept 100 ms..." 
StopTimer(0)
Print sTimeTaken(0, -1, False) ' No formatting
Print

' Cosmetics_ENDs :)


Usability: I trust in your code and agree with you that the granularity is by far enough to perform serious profiling/tuning of algorithms/functions.


st_w wrote: "Thank you [..] (who) provide very useful, professional quality contributions."

I repeat:
very useful, professional quality contribution
(..cannot find better words...)

Have a nice day. And thank you once again.

Adele
MrSwiss
Posts: 3359
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: MacroTimersQPC.inc

Postby MrSwiss » Jan 21, 2017 18:42

@adele,

thanks for your Tip. I've already done that, but it only solves the highlighting issue.
The second one, I'm referring to "opening the file from within (the IDE)", this is a option, I've
discovered "by chance": if you have a #Include "DateTime.bi" (for arguments sake only) and
highlight it (without the double quotes, but including the extension), then click the file open
Icon, the .bi is instantly opened in the Editor. This is "not working" except with .bi/.bas.
Probably "hard coded" somewhere ... similar to the "file open" dialog.

@St_W,

don't know where you're getting those funny ideas of yours, from:
St_W wrote:... basically a matter of personal preference, which shouldn't be dictated to others having a different opinion. (I'm using FBedit too and also ran into the highlighting issue, though)
This is exactly what I did: stating my own personal opinion. You seem to be, the dictating one, here.
deltarho[1859]
Posts: 2253
Joined: Jan 02, 2017 0:34
Location: UK

Re: MacroTimersQPC.inc

Postby deltarho[1859] » Jan 22, 2017 22:40

Here is another macro to add to the above although it doesn't time an interval but creates one.

A simple analogy of the method employed is to consider amplification in a Hi-Fi system. We could have a powerful Class B amplifier which doesn't sound too good but didn't cost much. On the other hand, we could have a powerful Class A amplifier which sounds great but both our bank manager and partner would like a word with us at our earliest opportunity.

A hybrid, however, would use the Class B amplifier to get us within a neighbourhood of our desired sound and then use a very much less powerful Class A amplifier to fine tune resulting in a sound close to the more powerful Class A amplifier at a very much smaller combined cost.

With a millisecond timer linked to Sleep if we think only of resolution, neglecting access time, then a request for a five millisecond Sleep would see a delay of, roughly, five to six milliseconds. In general, a request for n milliseconds would see a delay of, roughly, n to n+1 milliseconds. A request for n-1 milliseconds would see a delay of, roughly, n-1 to n milliseconds.

The first part of the method does just that: It requests a Sleep of n-1 milliseconds. This is our Class B amplifier.

We then enter a loop polling QueryPerformanceCounter until we reach n milliseconds. This is our Class A amplifier.

In practice the time in the loop will vary between, roughly, no time at all or one millisecond for any value of n and we will never know at what point the cross-over occurred but that doesn't concern us - all that we are interested in is hitting n milliseconds in good time. Whilst in the loop we will have CPU activity but since we are in there for only one millisecond at most then I cannot see this being an issue.

If we do multiple tests it is bad practice to have them done 'back to back' - it is better to insert a 'breathing space' between tests and, preferably a random one.

Here is the macro.

Code: Select all

#Macro VeryHiResSleep( n ) ' n >= 1
  Scope
    Dim As ULongInt Target, Now
    QueryPerformanceCounter Cast( Large_Integer Ptr, @Now )
    Target = Now + n*liFreq/1000
    Sleep ( n-1, 1 ) ' Class B amplifier
    Do
      QueryPerformanceCounter Cast( Large_Integer Ptr, @Now ) ' Class A amplifier
    Loop Until Now >= Target
  End Scope
#EndMacro


We need Sleep linked to a one millisecond timer and this can be done easily via the StartHiResClock macro in the opening post. This should be executed well before employing VeryHiResSleep() as it incurs a delay itself before the change in resolution occurs. The best place would be at the beginning of a console application or in WM_InitDialog.

Here is the test code using the macro timers in the opening post.

Code: Select all

StartHiResClock
'...
'...
'...
Dim as Long n = 10
For i = 1 To 20
  StartTimer(0)
    VeryHiResSleep( n )
  StopTimer(0)
  Print sTimetaken(0,3,0);
  If i mod 5 = 0 THEN Print
  Sleep( Rnd*100+50,1) ' Have a random breather
Next


This is what I get:

Code: Select all

10.003ms 10.008ms 10.036ms 10.008ms 10.002ms
10.002ms 10.003ms 10.073ms 10.052ms 10.003ms
10.021ms 10.005ms 10.003ms 10.003ms 10.002ms
10.003ms 10.002ms 10.002ms 10.04ms  10.004ms

Requesting 10 milliseconds from just Sleep linked to a millisecond timer would see a worst case overshoot of up to, roughly, one millisecond or, to put that another way, 1000 microseconds. The worst case overshoot in the above table is 73 microseconds.

So, it would seem that VeryHiResSleep() is putting us in a very different place.

The worst case overshoot, for some reason, reduces for higher delay requests and are quite remarkable for a delay of 100 milliseconds although it is debatable whether we should be using VeryHiResSleep() for such a 'large' delay.

We should expect a delay of two milliseconds, for example, to give very volatile results but this is not the case. Here is a typical two millisecond delay output.

Code: Select all

2.002ms 2.023ms 2.008ms 2.003ms 2.008ms
2.002ms 2.003ms 2.002ms 2.003ms 2.007ms
2.024ms 2.002ms 2.002ms 2.002ms 2.003ms
2.002ms 2.003ms 2.015ms 2.005ms 2.002ms


It is worth noting that Sleep(0,1) behaves as Microsoft's Sleep at MSDN so with a one millisecond request of VeryHiResSleep() we find ourselves in the performance counter loop pretty quickly. In this case we simply get a millisecond burst of CPU activity.

For me this post is of only academic interest as I have no use for it, <smile>, a standard Sleep linked to a millisecond timer does me just fine. Whilst mentioning that I still find many folk at different forums requesting 5 or 10 milliseconds from their compiler's Sleep ticking over at the Windows default of 64Hz ie a period of 15.625ms. That regime has no idea what 5 or 10 milliseconds is and they could end up with 15 or 16 milliseconds.

Have fun.
deltarho[1859]
Posts: 2253
Joined: Jan 02, 2017 0:34
Location: UK

Re: MacroTimersQPC.inc

Postby deltarho[1859] » Jan 24, 2017 18:21

A request for n-1 milliseconds would see a delay of, roughly, n-1 to n milliseconds.


Occasionally, we overshoot n milliseconds so there is no need to poll QueryPerformanceCounter. We can test if an overshoot has occurred but this would incur a greater overshoot.

A solution is to use Sleep( n-2,1 ). Occasionally, we would overshoot n-1 but we would never overshoot n. This will limit us to requests of n >= 2 and a possible CPU burst of about two milliseconds.

Tests have shown a worst case overshoot of three microseconds.

If it is important to be this precise then go for Sleep( n-2, 1 ). If the occasional 'spike' of 70 microseconds or so is acceptable then stay with Sleep( n-1, 1 )

Return to “Tips and Tricks”

Who is online

Users browsing this forum: MSN [Bot] and 3 guests