love
love copied to clipboard
`love.timer.sleep(0.001)` locks game to 500fps rather than 1000fps
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?
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.
Here's the relevant SDL3 change. love will use the new API eventually, once SDL3 is released and stable. https://github.com/libsdl-org/SDL/pull/6232
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.
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.
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
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.
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.
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.
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.
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
.
just in case , i made a fork of love2d that remove love.timer.sleep(0.001) : https://github.com/quentin452/love-experiments
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. :)
does love.timer.sleep(0) yield at all?
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/
:)
like i want to optimize my game , when i see more FPS i am happy :D
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