ondras / rot.js

ROguelike Toolkit in JavaScript. Cool dungeon-related stuff, interactive manual, documentation, tests!
https://ondras.github.io/rot.js/hp/
BSD 3-Clause "New" or "Revised" License
2.32k stars 254 forks source link

High cpu usage by Display module #179

Open Jon-Biz opened 4 years ago

Jon-Biz commented 4 years ago

I'm having a lot of fun with this, but ran into this performance issue.

I'm using the Display module to render a rectangular display, and getting 100% cpu usage from this line:

    /**
     * Timer tick: update dirty parts
     */
    _tick() {
        this._backend.schedule(this._tick);
        if (!this._dirty) {
            return;
        }

backend.schedule() is this line:

schedule(cb) { requestAnimationFrame(cb); }

It appears that, as long as there's nothing to do, it just executes and returns as fast requestAnimationaly possible. Adding a 2ms setTimeout to this._backend.schedule(this._tick) dropped chrome's cpu usage from 100% to 7%.

Implementing an optional rate limiter would trivial, but I wanted to make sure that I'm not using it wrong before submitting a PR?

ondras commented 4 years ago

Hi @Jon-Biz,

it is, generally speaking, browser's responsibility to throttle requestAnimationFrame freqency into suitable domain: https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

As far as I now, the typical frequency is 60fps, which corresponds to ~16ms delay between individual calls. It is weird that a manual +2ms delay would drop the CPU usage as much.

Instead of introducing additional delays, we might simply stop the whole loop and wait until the nearest draw operation. This would remove unnecessary tick/schedule calls that are currently a no-op.

However, I am quite interested in how you got into this, because an empty requestAnimationFrame loop shall not be observable with respect to CPU usage. Please:

Thanks!