Without digging into the code, my rough guess is that it's firing a paint event more often than
requestAnimationFrame, so there's a queue of pending events building up.
Not entirely sure - but I don't think there should be a problem keeping a steady 60FPS even with a bunch of bouncing balls
Could be the canvas API too. Maybe a bit later I'll make a fork and tinker around...
One thing that comes to mind is that on the web there's really no benefit to painting at anything other than
requestAnimationFrame. Of course you might have updates more often than that, or there might not be any updates.
This actually points to one of the most elegant things about FRP imho - you can have different "timers" at different frequencies and compose them to get something else. E.g. the internal bounce logic can run at 200 FPS (or continuously, which is awesome) but you can get a stream of events that snapshots that when it's time to paint, so there's no missed physics and you're not thrashing the paint queue.
Not sure if any of that's the issue here - happy to take a look later if you haven't already solved it by then