This may not be a bug in Babylonjs. I use the latest version of Chrome/Edge browser. When the rendering frame rate is below 50 fps, the combination of keyboard keys (such as simultaneously pressing six keys on the keyboard without releasing them) may cause instability in the timer task, although I do not listen for any keydown or keyup events on the page. Currently, only the latest version of Chrome/Edge for Windows has this issue, while Chrome/Edge for MacOS does not have this issue. In addition to timer tasks, this can also affect the onmessage of webworkers and websockets.
Older versions of Chrome/Edge have been verified to have no such issues.
Necessary conditions for triggering a bug:
Windows 10 system
The latest version of edge/chrome (111.0.5563.147)
The frame rate fps is lower than 50
Press 6 keyboard keys simultaneously without releasing them
You can experience this by observing the time interval for console printing as linked below
I’m reproducing (I have to increase the number of spheres created per second to decrease my framerate) but I don’t see anything different in the performance tab between frames where I don’t press keys and frames where I press keys, at least on the Babylon.js side. So it seems to have something to do with the browser itself.
You need to press more than five keyboard keys at the same time and keep them pressed. I have replicated this issue on several devices, but it may not really have anything to do with Babylonjs. I will copy it to Chrome.
I can’t quite reproduce this. I am using edge Version 111.0.1661.54 (Official build) (64-bit). Also tested on Chrome canary Version 114.0.5680.0 (Official Build) canary (64-bit)
The FPS varies, but that’s mainly because of the complex physics computations of the sphere-mesh collisions. Just like @Evgeni_Popov said, the render loop seems to be constant. we do register callbacks for keyboard events when you attach the camera to the canvas, but those callbacks are very simple, especially when you have no keyboard callbacks registered yourself. I’ll try in other browsers as well, but it seems to be browser-related?
Sorry,I may not have described the problem clearly. I don’t mean that keyboard events affect the value of fps. I mean that they affect the execution of timed tasks. The core part of the code for the playground above is this part:
The timestamp value printed by setInterval is between 50-200
The timestamp value printed by setInterval is greater than 10000 milliseconds
I totally get what you are saying This would have happened as well if our keyboard event mechanism took a long time to process many events at the same time.
I constantly checked the console output as well - i never got a value above 200.
yup it related to the chrome maybe, I have tried edge and firefox.
the performance on firefox is best and everything is fine.
I’v created an example with three.js since it was not any 3D webgl framework related.
here is the example:
I put a lag function in the animation loop create 1 million numbers
press 1 key and hold.
every thing works perfect fine in firefox 107 at 60FPS
while chrome and edge drop to 30FPS and got the issue described above.
when I increace the loop to 5 million .
the frame in firefox drop lower than 50 but the interval function still work.
it seems that interval function were pushed behind.
I read the chromium issue thread. I have a few questions regarding this statement:
There’s an inherent challenge around scheduling both render-loop style sites and interactive sites, and there may be an opportunity for better APIs/internal scheduling, but we need to make sure we ensure good responsiveness here. I’m going to close this as WAI because the behavior is intentional and any scheduling change is likely to regress responsiveness.
But I have a couple ideas for workarounds which I hope can work for your case:
- Do the non-render-loop work in a worker and use a SharedArrayBuffer for communication from between the worker and main thread. This option removes tasks from the main thread, using a synchronous communication channel (which you’ll need to synchronize). The render loop can check the shared state on whatever cadence is appropriate.
- Throttle the render task/frame rate if it can’t keep up. That you’re not seeing this on higher-end devices makes sense – as long as the render loop is fast enough, this isn’t a problem because it leaves time for other tasks. If you can detect that you can’t keep up, drop a frame to give time for other tasks to run.
You mentioned that with bjs scenes, the setInterval test doesn’t seem to get completely blocked by the keydown events, but it still does affect it right? How is the set interval function being less throttled in the case of a user input event with a bjs app?
I’m also having trouble understanding when the Blink scheduler triggers a re-render immediately after a user input event, does the re-render include the render process that bjs uses (request animation frame) as well? Or does it just re-draw the document elements excluding the canvas?
I’ve run a lot of samples and found that it doesn’t seem to affect the request animation frame, but it does affect addEventListener (non-UI interaction events), setTimeout, setInterval, postMessage, so it blocks messaging in iframes, webworkers, and websockets.
Whether to completely block task execution depends on the performance of the program, when the program performance is good enough, it will not encounter blocking, when the program performance affects the event queue, then the above listed event functions will be delayed because of the input event “cut the queue”, when the program performance is particularly lagging, will be because the input event continues to “cut the queue” resulting in the above listed events are completely blocked. At this point, you will not see setInterval executed.
When you say program, in this context are we referring to canvas rendering programs run by babylon.js? Are we talking about CPU side programs?
This type of blocking can be caused whenever performance is affected, whether it is GPU programs (e.g. shadows, post-processing, complex meshes, shaders) or CPU programs (rays, physics engines, AABB)