Astrabit-ST / ModShot-Core

A fork of mkxp, forked for OneShot, forked for OneShot mods, (not to be confused with the ModShot server)
https://nowaffles.com
GNU General Public License v2.0
19 stars 9 forks source link

Unlock the GVL in Graphics.update #13

Closed rkevin-arch closed 3 years ago

rkevin-arch commented 3 years ago

Ruby has a global VM lock (GVL), which means the ruby interpreter can only run one thread at a time, as long as it is running ruby code. If one thread has the GVL, the other thread will wait to acquire the lock before it can run any ruby code. Any C/C++ code invoked by ruby will also hold the GVL, unless told otherwise. More about the GVL:: https://silverhammermba.github.io/emberb/c/#c-in-ruby-threads

The Graphics.update ruby function (mapped to the Graphics::update C++ function) is responsible of rendering a frame in Modshot. It's also responsible for limiting the FPS to 60. If the FPS goes higher than that, the FPS limiter will wait for a bit to render the frame. However, it is still holding the GVL this entire time. This means any multithreaded ruby code would not be able to execute during this waiting period, and the performance would be incredibly slow.

This PR unlocks the GVL during Graphics.update, so other ruby threads can have decent performance.

NOTE: I've went through the Graphics::update code and believe it doesn't need to lock the GVL (i.e. it doesn't call any ruby APIs and doesn't interact with anything in ruby). This is true to the best of my knowledge, but I'd like a second pair of eyes to verify this is true just in case. Otherwise, this may introduce weird race conditions that could cause crashes.