Identifying the Problem
I was busy editing a library for lua bindings to rtmidi. I wanted to fix MinGW-GCC and LLVM/Clang compilation compability. When I was done making the edits and compiling the bindings, I noticed a weird timing issue caused by std::this_thread::sleep_for()
when compared to MSVC.
I understand that there are bound to be some scheduling differences between different compilers, but in the following examples you can hear large timing issues:
- MIDI playback using MSVC compiled bindings
- MIDI playback using GCC compiled bindings
I have narrowed it down that this is the piece of code in question:
lua_pushliteral(L, "sleep");
lua_pushcfunction(L, [] (lua_State *L) {
auto s = std::chrono::duration<lua_Number>(luaL_checknumber(L, 1));
std::this_thread::sleep_for(s);
return 0;
});
lua_rawset(L, -3);
Obviously it's about these two lines:
auto s = std::chrono::duration<lua_Number>(luaL_checknumber(L, 1));
std::this_thread::sleep_for(s);
The average waiting time that is passed to sleep_for()
is around 0.01s, with some calls here and there between 0.002s - 0.005s.
Troubleshooting
First off I have checked whether the problem was present with my current version of GCC (9.2.0) by using a different version and even using LLVM/Clang. Both GCC 8.1.0 and LLVM/Clang 9.0.0 yield the same results.
At this point I can conclude there is some weird scheduling going on with the winpthreads runtime, since they depend on it and MSVC does not.
After that I tried to switch out the code with the Windows Sleep()
call. I had to multiply by 1000 to adjust for the correct timing.
Sleep(luaL_checknumber(L, 1) * 1000);
As I expected, the timing issue is not present here; this indeed confirms that winpthreads is the culprit here.
Obviously I do not want to make calls to Windows Sleep()
and keep using sleep_for()
.
The Questions
So based on what I gathered I have the following questions:
- Is winpthread indeed the culprit? Am I perhaps missing some compiler defines that would solve the problem?
- If winpthreads is indeed the culprit, why are the timing differences so big?
- If there is no compiler define 'fix', what would you recommend to do tackle the problem?
To partially answer the third question (if it may come to it), I was thinking of doing something like:
#ifdef _WIN32 && MINGW
#include <windows.h>
#endif
...
#ifdef _WIN32 && MINGW
Sleep(luaL_checknumber(L, 1) * 1000);
#elif _WIN32 && MSVC
auto s = std::chrono::duration<lua_Number>(luaL_checknumber(L, 1));
std::this_thread::sleep_for(s);
#endif
Of course the problem arises that Window's Sleep()
call is less precise (or so I've read).
Aucun commentaire:
Enregistrer un commentaire