barotto / IBMulator

The IBM PS/1 emulator.
https://barotto.github.io/IBMulator
GNU General Public License v3.0
111 stars 4 forks source link

Unstable timings and stuttering if compiled with the current MSYS2/MinGW version #47

Closed barotto closed 4 years ago

barotto commented 5 years ago

If you compile the master branch with the current version of MSYS2/MinGW under Windows, the main/GUI thread will have unstable timings and lots of missed frames when the [program]:threads_sync option is enabled. You'll also notice that the mouse pointer has jerky movement.

The problem seems to have started with version git-7.0.0.5325 (06-Mar-2019) of the winpthreads library. The last known working version is winpthread-git-7.0.0.5273 (04-Dec-2018).

Release binary versions of IBMulator for Windows are compiled with an old MSYS2 environment using gcc 7.3.

At this point I'm not sure if IBMulator will require a reenginering of its threads synchronization mechanism (likely) or if this is a bug of winpthreads that will be eventually fixed (very unlikely).

barotto commented 4 years ago

This issue has been partially addressed in commit 4b2d20ace7f81b130cf224c81d3f787bff4279d9 Input stuttering under Windows is still present.

barotto commented 4 years ago

Upon further investigation I've determined that the problem is not input related. Frames are rendered by the VGA thread at a steady pace, but are not (some yet unknown reason) presented steadily by the GUI thread. This is a problem only under Windows (MinGW) and started with libwinpthreads version git-7.0.0.5325.

If compiled with previous versions of libwinpthreads, IBMulator presents VGA frames at a usually steady pace, but not always: there are moments that last a couple of seconds where the screen visibly stutters. Again this is a problem only under Windows (MinGW).

Under Linux frame pacing seems to be very stable with no measurable stuttering.

barotto commented 4 years ago

It turns out std::this_thread::sleep_for() under MinGW is completely unreliable.

Under Linux the minimum sleep time is ~54000ns with an extremely low variance, easy to compensate for. Under MinGW it goes from 0 to whatever without any consistency.

Stuttering is determined by the continuous time adjustments the VGA thread is forced to do in order to compensate the sleep_for() errors and maintain a steady average frame pacing.

I'm tempted to drop Windows support.

barotto commented 4 years ago

When I started working on this project years ago, I naively designed the system around the wrong assumption that Linux's behaviour and precision was the norm. Now I discover that Windows has a tick resolution of 64Hz/15.625ms.

Apparently libwinpthreads changed the way it put threads to sleep and now everything falls apart.

This is the price you pay when you've been out of the Windows world for the last 2 decades. Also not having experience of how to properly disign interactive and time-sensitive programs does not help. I keep reading that putting a thread to sleep is an anti-pattern but at this point I prefer to just work around the issue and hope for the best.