FreeBasic's Timer

General FreeBASIC programming questions.
Post Reply
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: FreeBasic's Timer

Post by dodicat »

deltarho
Google Chrome used to alter the resolution, it doesn't seem to do so now.
I have tested a while back.
java runtime used to alter the resolution, but I don't have it just now, so I cannot test.
I don't have firefox.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

@fxm

That paragraph has been in timeBeginPeriod for a long time and should have been edited with Windows 10 or later.

With Windows 10 or later, suppose we have three processes using timer services, then the highest resolution requested from within that group will apply to that group. “For processes which have not called this function, Windows does not guarantee a higher resolution than the default system resolution.”

If no process uses timer services apart from your graphics program, then the rest of the system is unaffected.

Do you think that your graphics program on its own using timer services will reduce overall system performance? I seriously don't think so, and that is why Microsoft introduced the no global setting.

The Remarks section of timeBeginPeriod has always been badly written. I won't bore you, but there are other aspects of timeBeginPeriod changes in Windows 10 that have never been mentioned. I discovered them by experimenting.

What we have then is a choice between no 1000Hz timer and a threshold of 32ms with the option to change that scenario, or using the 1000Hz timer with a 3ms threshold with the option to change that scenario.

I strongly recommend the latter, as the user will get a very much reduced CPU load without having to do anything.
Last edited by deltarho[1859] on May 28, 2023 22:11, edited 1 time in total.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

But what is the compatibility of:
Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(Byval As Ulong = 1) As Long
_setTimer()

with older Windows ?
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

@dodicat

A few years ago, a person had one hell of a rant about web browsers and their messing with the timer resolution whether they needed to or not.

Sat in a park with our laptop running on battery will see the battery run down faster with a high timer resolution, he argued.

It follows that our battery will run down faster on Linux than Windows – 10ms versus 15.625ms.

The no global setting has helped in this respect, in addition to web browsers being better behaved.

Of course, there isn't much we can do about watching a film in the park, whether on Windows or Linux. :)

At home, a high timer resolution will suck more out of our A/C supply, but we are talking small amounts for one PC over a year. With every PC on the planet, it may add up to quite a lot.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

fxm wrote:But what is the compatibility of:
Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(Byval As Ulong = 1) As Long
_setTimer()
with older Windows ?
As I mentioned, timeBeginPeriod was introduced in Windows 2000.

With a default of 1000Hz timer and a threshold of 3ms for Windows, I very much doubt that anyone will change that.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

deltarho[1859] wrote: May 28, 2023 21:36 What we have then is a choice between no 1000Hz timer and a threshold of 32ms with the option to change that scenario (by "timeBeginPeriod" + procedure call with 3 ms as second parameter), or using the 1000Hz timer with a 3ms threshold with the option to change that scenario (by "timeEndPeriod" + procedure call with 32 ms as second parameter).

I strongly recommend the latter, as the user will get a very much reduced CPU load without having to do anything.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

For the life of me, I cannot see anyone in their right mind on Windows opting to choose a method which increases their CPU load with no change in the accuracy of the exercise.

At MSDN: "Call this function immediately before using timer services, and call the timeEndPeriod function immediately after you are finished using the timer services."

I ignored that on Windows 7 when I realized, on experimenting, that timeBeginPeriod(1) did not 'bite' until one clock tick had been executed – that is 15.625ms. That is why I called timeBeginPeriod(1) at the beginning of an application so that the 1ms resolution was available when needed. On Windows 10 it 'bites' immediately.

So, why didn't Microsoft mention the 15.625ms delay on Windows 7. The simple answer is: They did not know. :)
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

Therefore, the source to be included ('delay_regulate_framerate.bi') containing all declarations and procedure bodies:
delay_regulate_framerate.bi:

Code: Select all

'  delay_regulate_framerate.bi

#if defined(__FB_WIN32__)
Declare Sub delay(ByVal amount As Single, ByVal threshold As Ulong = 2 * 16)
Declare Function regulate(ByVal MyFps As Ulong, ByVal threshold As Ulong = 2 * 16) As Double
Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(ByVal As Ulong = 1) As Long
Declare Function _resetTimer Lib "winmm" Alias "timeEndPeriod"(ByVal As Ulong = 1) As Long
Declare Sub delayHR(ByVal amount As Single, ByVal threshold As Ulong = 2 * 1)
Declare Function regulateHR(ByVal MyFps As Ulong, ByVal threshold As Ulong = 2 * 1) As Double
Sub delayHR(ByVal amount As Single, ByVal threshold As Ulong)
    '' 'amount'  : requested temporisation to apply, in milliseconds
    '' 'thresold' : fixing threshold for fine-grain temporisation (by waiting loop), in milliseconds
    Dim As Double t1 = Timer
    Dim As Double t2
    Dim As Double t3 = t1 + amount / 1000
    If amount > threshold + 0.5 Then
        _setTimer()
        Sleep amount - threshold, 1
        _resetTimer()
    End If
    Do
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
        t2 = Timer
        If t2 < t1 Then t1 -= 24 * 60 * 60 : t3 -= 24 * 60 * 60
    Loop Until t2 >= t3
    #else
    Loop Until Timer >= t3
    #endif
End Sub
Function regulateHR(ByVal MyFps As Ulong, ByVal threshold As Ulong) As Double
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied delay (for debug), in milliseconds
    '' 'thresold' : fixing threshold for fine-grain temporisation (by waiting loop), in milliseconds
    Static As Double t1
    Dim As Single tf = 1 / MyFps
    Dim As Double t2 = Timer
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
    If t2 < t1 Then t1 -= 24 * 60 * 60
    #endif
    Dim As Single dt = (tf - (t2 - t1)) * 1000
    delayHR(dt, threshold)
    t1 = Timer
    Return dt
End Function
#elseif defined(__FB_LINUX__)
Declare Sub delay(ByVal amount As Single, ByVal threshold As Ulong = 2 * 10)
Declare Function regulate(ByVal MyFps As Ulong, ByVal threshold As Ulong = 2 * 10) As Double
#elseif defined(__FB_DOS__)
Declare Sub delay(ByVal amount As Single, ByVal threshold As Ulong = 2 * 55)
Declare Function regulate(ByVal MyFps As Ulong, ByVal threshold As Ulong = 2 * 55) As Double
#else
Declare Sub delay(ByVal amount As Single, ByVal threshold As Ulong = 2 * 16)
Declare Function regulate(ByVal MyFps As Ulong, ByVal Ulong As Single = 2 * 16) As Double
#endif

Declare Function framerate() As Ulong

'------------------------------------------------------------------------------

Sub delay(ByVal amount As Single, ByVal threshold As Ulong)
    '' 'amount'  : requested temporisation to apply, in milliseconds
    '' 'thresold' : fixing threshold for fine-grain temporisation (by waiting loop), in milliseconds
    Dim As Double t1 = Timer
    Dim As Double t2
    Dim As Double t3 = t1 + amount / 1000
    If amount > threshold + 0.5 Then Sleep amount - threshold, 1
    Do
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
        t2 = Timer
        If t2 < t1 Then t1 -= 24 * 60 * 60 : t3 -= 24 * 60 * 60
    Loop Until t2 >= t3
    #else
    Loop Until Timer >= t3
    #endif
End Sub

Function regulate(ByVal MyFps As Ulong, ByVal threshold As Ulong) As Double
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied delay (for debug), in milliseconds
    '' 'thresold' : fixing threshold for fine-grain temporisation (by waiting loop), in milliseconds
    Static As Double t1
    Dim As Single tf = 1 / MyFps
    Dim As Double t2 = Timer
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
    If t2 < t1 Then t1 -= 24 * 60 * 60
    #endif
    Dim As Single dt = (tf - (t2 - t1)) * 1000
    delay(dt, threshold)
    t1 = Timer
    Return dt
End Function

Function framerate() As Ulong
    '' function return : measured FPS value (for debug), in frames per second
    Static As Double t1
    Dim As Double t2 = Timer
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
    If t2 < t1 Then t1 -= 24 * 60 * 60
    #endif
    Dim As Ulong tf = 1 / (t2 - t1)
    t1 = t2
    Return tf
End Function

Example using 'delay()' procedure:

Code: Select all

#include "delay_regulate_framerate.bi"

Dim As Double t
Dim As Single t0 = 100

For N As Integer = 1 To 4
    Print "Requesred delay :"; t0; " ms"
    For I As Integer = 1 To 4
        t = Timer
        delay(t0)
        Print Using"  Measured delay : ###.### ms"; (Timer - t) * 1000
    Next I
    Print
    t0 /= 10
Next N

Sleep

Example using 'regulate()' procedure and 'framerate()' tooling procedure:

Code: Select all

#include "delay_regulate_framerate.bi"

Screen 12
Dim As Ulong FPS = 60
Do
    Static As Ulongint l
    Static As Single dt
    Screenlock
    Cls
    Color 11
    Print Using "Requested FPS : ###"; FPS
    Print
    Print Using "Applied delay : ###.### ms"; dt
    Print Using "Measured FPS  : ###"; framerate()
    Print
    Print
    Print
    Color 14
    Print "<+>      : Increase FPS"
    Print "<->      : Decrease FPS"
    Print "<Escape> : Quit"
    Line (0, 80)-(639, 96), 7, B
    Line (0, 80)-(l, 96), 7, BF
    Screenunlock
    l = (l + 1) Mod 640
    Dim As String s = Inkey
    Select Case s
    Case "+"
        If FPS < 100 Then FPS += 1
    Case "-"
        If FPS > 10 Then FPS -= 1
    Case Chr(27)
        Exit Do
    End Select
    dt = regulate(FPS)
Loop

Previous example, but forcing the low basic resolution (16 ms) for the Windows OS cycle period:

Code: Select all

#include "delay_regulate_framerate.bi"

#ifdef __FB_WIN32__
_resetTimer()
#endif

Screen 12
Dim As Ulong FPS = 60
Do
    Static As Ulongint l
    Static As Single dt
    Screenlock
    Cls
    Color 11
    Print Using "Requested FPS : ###"; FPS
    Print
    Print Using "Applied delay : ###.### ms"; dt
    Print Using "Measured FPS  : ###"; framerate()
    Print
    Print
    Print
    Color 14
    Print "<+>      : Increase FPS"
    Print "<->      : Decrease FPS"
    Print "<Escape> : Quit"
    Line (0, 80)-(639, 96), 7, B
    Line (0, 80)-(l, 96), 7, BF
    Screenunlock
    l = (l + 1) Mod 640
    Dim As String s = Inkey
    Select Case s
    Case "+"
        If FPS < 100 Then FPS += 1
    Case "-"
        If FPS > 10 Then FPS -= 1
    Case Chr(27)
        Exit Do
    End Select
    #ifdef  __FB_WIN32__
    dt = regulate(FPS, 32)
    #else
    dt = regulate(FPS)
    #endif
Loop
Last edited by fxm on May 29, 2023 11:52, edited 1 time in total.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

Image
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

hhr wrote:As I said before, you are dealing with a difficult subject.
On second thoughts, you may be right. :)
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

For those interested, I started writing the new documentation page:
- ProPgDelayRegulate → fxm [new page in progress 'Fine-grain procedure for waiting and in-loop procedure for regulating FPS']
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: FreeBasic's Timer

Post by speedfixer »

@deltarho[1859]:
Yours truly wrote:
Perhaps some comments from members would be helpful. Stand aside to avoid being crushed. :lol:

See what I mean? At PowerBASIC quite a few members would have responded by now.
Yeah, I hear crickets, also. And I am one of them. Please: always look at the view count. Many more people than just me are very interested in topics like this.
hhr popped in with what he could (and I think there are others with enough experience that could, also) but I think think most of us feel very comfortable that a couple of you are doing such a very good job of tackling topics that will improve look/feel/performance of FB.
This is lazy and selfish, perhaps.

But our respect and appreciation is not small.

And it is not possible to praise highly enough fxm's tenacity and attention to detail.
I may disagree with his firm hand and opinion, at times, but there is no denying his persistence, focus, and discipline has helped every one involved on just about every topic he has been entangled with.

@coderjeff:
There is no good place to add in user contributed source, and I don't think we want to convert user's fb code to C to put in the rtlib.

Why Not?
A good idea is a good idea - thrown out there for consideration by the group.
A contribution is a contribution: given in hopes that it will useful and used.

If that contribution is converted into a more system sustainable and efficient reference, even better!

david
hhr
Posts: 205
Joined: Nov 29, 2019 10:41

Re: FreeBasic's Timer

Post by hhr »

I have looked at 'mouse and maze' from BasicCoder2.
viewtopic.php?p=298935#p298935

In the first lines I set speed = 60.

I copied 'mouse and maze' into a second tab and replaced the function regulate of BasicCoder2 with the function regulate of fxm.
Then in the main loop at the end of the program 'sleep regulate(speed,fps),1' must be replaced by 'regulate(60,0)'.
Both programs jerk a bit, but otherwise work the same.

As intended, I then added the section with "timeBeginPeriod" to the program with regulate from fxm.
Thus the program with regulate of fxm runs more evenly.

If I insert the section also into the program of BasicCoder2, both programs run again equally.

So in the program of BasicCoder2 only the section with "timeBeginPeriod" is missing.

My point is that one must not be hasty. As much as I appreciate fxm's work, I have to say that the functions can perhaps be improved.
Copy and paste is completely sufficient. If it were built into FreeBasic, further development would be difficult.

Does anyone know how game programmers handle this problem?

Translated with the help from www.DeepL.com/Translator (free version)
Last edited by hhr on May 29, 2023 21:54, edited 1 time in total.
adeyblue
Posts: 299
Joined: Nov 07, 2019 20:08

Re: FreeBasic's Timer

Post by adeyblue »

speedfixer wrote: May 29, 2023 18:26 @coderjeff:
There is no good place to add in user contributed source, and I don't think we want to convert user's fb code to C to put in the rtlib.

Why Not?
Quite simply, nobody's put in the effort to make it happen. And when you consider nobody maintains the examples that are already shipped with freebasic, who do you think is going to maintain and document 2,000 other completely random pieces of code as they break and become obsolete? (2,000 being the number of codes linked in The Big Review topic in the source forum)

Lumping yet another thing at the feet of the people who seemingly already do everything is a bit of a rum do. But who else would do it? I certainly wouldn't
As I mentioned, timeBeginPeriod was introduced in Windows 2000.
Windows NT 3.1 from 1993, here's what the docs said then. You can get the whole NT3.1 documentation set here if you'd like.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

@hhr,

Using '0' as second parameter of 'regulate()' is the worst value for regulation accuracy.

For a Windows platform:
Without "timeBeginPeriod", use '32' instead.
With "timeBeginPeriod", use '3' instead.
Post Reply