Reimplementing setTimeout to use condition variables #851
Replies: 5 comments 5 replies
-
I guess this still results in one blocked thread, which maybe is ok. It seems like another alternative would be to use platform specific timers (e.g. |
Beta Was this translation helpful? Give feedback.
-
@rgerd how is this implemented in react-native? I'd be concerned about us over-engineering a solution here. While it's bad that we're blocking the JS thread so substantially, the overhead with hopping from timer threads back to the JS thread may be equally bad. Sure, it may not stall the JS thread, but it may negatively affect other things. Certainly we shouldn't need a dedicated thread for this. What's an average number of pending callbacks in a BabylonNative app? If we're looking at something like <50 callbacks pending at once, it may make more sense to just provide a special hook to the JS dispatcher loop to drain the pending callbacks list linearly as the O(n) execution per-loop is still probably less involved than thread-hopping from the timer callback. |
Beta Was this translation helpful? Give feedback.
-
Isn't this what is already implemented before @rgerd's PR? I'm not 100% sure what you mean by this. |
Beta Was this translation helpful? Give feedback.
-
React Native implementation details: Appears to be a combination of a JavaScript polyfill plus native modules. The functions like NativeTiming has different implementations for iOS & Android:
|
Beta Was this translation helpful? Give feedback.
-
Sounds like the React Native implementation is preferable since it's basically the same as what we had before but it avoids churning through std::functions and adding a bunch of extra dispatch calls, it doesn't use any other threads, and it's a simple implementation. Spec implies that setTimeout callbacks will run at the next opportunity instead of right on time, so it feels like we could just check the list of timers after each blocking_tick call inside WorkQueue (or even onRender) and add the work to the queue for each expired timer. |
Beta Was this translation helpful? Give feedback.
-
I implemented @syntheticmagus's idea of using a condition variable and priority queue, and it works: #844
The PR currently has experience.js modified into a unit test, I'd revert this change before taking out of draft. Please feel free to review the rest of it if you have suggestions, or comment here if you think another approach would be better.
Anecdotally, on my surface laptop I'm seeing 13% CPU usage with the TimeoutDispatcher running a continuous 1 second ping, and 25% CPU usage with the original recursive wait call. The only drawback I've seen is that setTimeout isn't 100% accurate with the worker thread approach, usually adding about a 10ms delay. I tried increasing the priority of the worker thread with the native Win32 API to no avail. Seems like this is generally still in-line with the MDN spec, which implies that setTimeout calls will be placed on the queue and gotten to when the browser is finished with other important work. Babylon.JS mostly uses setTimeout with a delay of 0 to defer / asynchronize work, so I just threw in a check to optimize for that.
Beta Was this translation helpful? Give feedback.
All reactions