Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

love.timer.sleep(0.001) locks game to 500fps rather than 1000fps #1970

Open
expikr opened this issue Sep 13, 2023 · 16 comments
Open

love.timer.sleep(0.001) locks game to 500fps rather than 1000fps #1970

expikr opened this issue Sep 13, 2023 · 16 comments
Labels
library dependency Related to a library used by LÖVE SDL3 Features and changes that depend on upgrading from SDL2 to SDL3 Windows

Comments

@expikr
Copy link

expikr commented Sep 13, 2023

The default love.run yields via love.timer.sleep(0.001) to reduce CPU usage.

I'm just curious why the result is a stable 500fps rather than 1000fps?

@slime73
Copy link
Member

slime73 commented Sep 13, 2023

The duration of sleep is ultimately up to what the OS scheduler decides. Recent Windows updates changed its standard OS sleep function to have a minimum possible duration of 2ms apparently, instead of 1ms.

Microsoft also introduced a new sleep function recently which can theoretically have shorter durations (although I'm not sure how short exactly, in practice). love calls into SDL2's sleep function which doesn't use that new API, although SDL3 exposes a new function which does.

@slime73
Copy link
Member

slime73 commented Sep 13, 2023

Here's the relevant SDL3 change. love will use the new API eventually, once SDL3 is released and stable. libsdl-org/SDL#6232

@xchiptune
Copy link

Had the same issue a few days ago actually, I wanted a 8000hz thread to poll input at 8000hz (those new 8khz mouses) but love.timer.sleep couldn't wait less than 1ms.

My solution was love2d uses LuaJIT, so you have access to C functions too through ffi.cdef, and nanosleep worked like a charm.

I'm guessing this is also a solution love2d could make use of natively.

@slime73
Copy link
Member

slime73 commented Sep 18, 2023

Just a heads up, love.event.pump is not safe to call on non-main threads. Multiple events within a single frame won't be missed if it's called once per frame though.

@expikr
Copy link
Author

expikr commented Sep 20, 2023

Unless you are explicitly capturing timestamps at 8000hz, there is precisely zero benefit to do anything other than pumping events at the start of frame. Subtick input processing can easily be implemented by processing the pumped events individually and emit events when a change happens (as opposed to lumping them into a "current frame state")

If you need to capture precise timestamps at 8000Hz, you should be rolling your own message loop with user32.GetMessage in a blocking thread dedicated to listening for WM_INPUT and call kernel32.QueryPerformaneCounter as the first thing after GetMessage unblocks.

SDL (and by extension Love) is completely unsuitable for precise message timestamping because they uses PeekMessage -- which polls rather than blocks -- for both SDL_PollEvent and SDL_WaitEvent

@xchiptune
Copy link

xchiptune commented Sep 20, 2023

Well I'd love to talk more about my project but the specifics of that aren't relevant here. It was just anecdotal and the main point was there is an easy way to perform more granular sleeps on Love2D.

And I'm on Linux, Windows doesn't have nanosleep.

I believe on Windows your options are extremely limited. The only way to perform sub 1ms sleeps without using busy-waits is waitable timer objects. Any modules you use on C or C++ is either using waitable timer objects or a busy loop with QueryPerformaneCounter under the hood. Waitable timer objects poses it's own issues since they aren't as fast as busy-waits or regular sleeps despite the higher precision.

So you're left with choosing between the cpu intensive busy wait, or the slower waitable timer object.

@expikr
Copy link
Author

expikr commented Sep 21, 2023

On windows, GetMessage() blocks the thread until there is a message that satisfies the specified filter. In other words, it is the lowest possible latency method to timestamp when a message is received by the process, far more accurate than any busy-wait loops could possible get you.

@xchiptune
Copy link

xchiptune commented Sep 23, 2023

Did you forget the topic of this issue? You started this issue raising question about the resolution of love.timer.sleep()

Inputs and GetMessage() are not relevant to this issue.

@MikuAuahDark
Copy link
Contributor

Ultimately there's not much we can do here I guess. You can always redefine your own love.run with the love.timer.sleep call removed.

@expikr
Copy link
Author

expikr commented Sep 23, 2023

Did you forget the topic of this issue? You started this issue raising question about the resolution of love.timer.sleep()

Inputs and GetMessage() are not relevant to this issue.

It's in response to your use case of wanting to sample 8000Hz inputs. I'm saying that using Love2D for that premise is wrong to begin with, you should be rolling your own input thread with GetMessage.

@slime73 slime73 added the library dependency Related to a library used by LÖVE label Oct 21, 2023
@slime73 slime73 added the SDL3 Features and changes that depend on upgrading from SDL2 to SDL3 label Feb 9, 2024
@quentin452
Copy link

just in case , i made a fork of love2d that remove love.timer.sleep(0.001) : https://github.com/quentin452/love-experiments

@slime73
Copy link
Member

slime73 commented Feb 23, 2024

You don't need to fork love to do that, you can customize love.run already.

However, an extra 1-2ms per frame is not a drastic improvement in most situations. Don't be fooled by the big FPS numbers, they aren't linear. :)

@expikr
Copy link
Author

expikr commented Mar 3, 2024

does love.timer.sleep(0) yield at all?

@slime73
Copy link
Member

slime73 commented Mar 4, 2024

It can, however the behaviour is pretty dependent on outside factors. Here's an article talking about it on Windows: https://randomascii.wordpress.com/2012/06/05/in-praise-of-idleness/

@quentin452
Copy link

:)

like i want to optimize my game , when i see more FPS i am happy :D

@Keyslam
Copy link

Keyslam commented Mar 8, 2024

Then look up how many watts your PC is consuming running at full speed, and see the costs of electricity to be less happy :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
library dependency Related to a library used by LÖVE SDL3 Features and changes that depend on upgrading from SDL2 to SDL3 Windows
Projects
None yet
Development

No branches or pull requests

6 participants