Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] High CPU load #168

Open
jstiefel opened this issue Sep 29, 2021 · 5 comments
Open

[BUG] High CPU load #168

jstiefel opened this issue Sep 29, 2021 · 5 comments

Comments

@jstiefel
Copy link

Describe the bug
I'm having a very high CPU load when moving the joystick around. On a high level CPU, this works fine, but in my customer's browsers, the website starts to freeze. The joystick gets stuck for some seconds, other indicators updated over a websocket have a delay of several seconds. I can also simulate it by using CPU throttling when collecting Performance metrics in Chrome.

I first figured out that my event handler function just takes too long. Therefore, I set a timeout and removed innerHTML functions. This already resulted in a much better performance on my CPU. However, I'm still having freezes on lower power CPUs.

How does manager.on() work if an event listener function takes too long to execute? Are the events just queuing up or are the same event listeners processed asynchronously? I assume the event trigger is much faster than my event listener function. How is this taken into account? Is there some measure if the events in the queue have a large time offset?

My computations in the joystick event handler are not very complex (see below).

To Reproduce
Steps to reproduce the behavior:

I can't share the website or the source code. However, here's my joystick event listener:

function createJoystick() {
    if (manager == null) {
        joystickContainer = document.getElementById('joystick');
        var options = {
            zone: joystickContainer,
            position: { left: '50%', top: '50%'},
            mode: 'static',
            size: 200,
            color: '#0066ff',
            restJoystick: true
        };
        manager = nipplejs.create(options);
    }

    manager.on('move', function (evt, nipple) {
        if (publishImmediately2) {
            publishImmediately2 = false;

            var direction = nipple.angle.degree
            var distance = nipple.distance;
            var x_field = Math.cos(direction * pi/180)*distance/(100/max_field);
            var y_advancer = Math.sin(direction * pi/180)*distance/(100/max_adv_speed);

            publish(x_field, y_advancer);
            setTimeout(function () {
                publishImmediately2 = true;
            }, 50);
        }
    });

    manager.on('end', function () {
        // Reset:
        publish(0,0);
    });
}

In addition, there are some indicators and an image stream on the website, which are updated over a websocket.

Expected behavior

No freezes of joystick, no delay in image stream or other elements on the website, no browser crashes, real-time control.

Screenshots, Codepen or JSFiddle

image

Desktop (please complete the following information):

  • OS: different, Ubuntu 20.04 and Windows 10
  • Browser: different, Chrome and Firefox
  • Version: Chrome 94.0.4606.54, Firefox 92.0
@jstiefel jstiefel added the bug label Sep 29, 2021
@yoannmoinet yoannmoinet removed the bug label Sep 30, 2021
@yoannmoinet
Copy link
Owner

Hey, thanks for the detailed report 🙇
I'm not sure this is actually coming from the library.

Can you try and comment these lines from your event handler and confirm that it's still struggling :

            publish(x_field, y_advancer);
            setTimeout(function () {
                publishImmediately2 = true;
            }, 50);

I can't tell what's happening in the publish function here, and it could be very heavy.

Anyway, removed the bug label, as it's not determined yet.

@jstiefel
Copy link
Author

jstiefel commented Oct 5, 2021

I think it comes from the "end" event listener. If I output console log on the end event, I get hundreds of log messages and further processing is blocked until all these events are handled. I removed all the other functions to test.

manager.on('end', function () {
    // Reset:
    var x_field_incrementor = 0;
    var y_advancer_incrementor = 0;
    console.log("end");
});

I'm still wondering if there is something limiting the addEventListener(). I'm pretty sure that this operation is faster than the handling if a task is for example taking longer than 50 ms. How long would event start queuing up in this case?

@MCArth
Copy link
Contributor

MCArth commented May 8, 2022

I've experienced something similar where the joystick freezes, and I don't think it was my event handler taking too long - it occurred when my game was running at very low fps

Nipplejs is very good in terms of feature-set but upon profiling it seems there are other performance issues - e.g. taking 2-3ms because of what seems like reading a dom style after writing to the dom (forcing the browser to re-render)

@MCArth
Copy link
Contributor

MCArth commented May 8, 2022

this happens on 0.9.1: see the long handler (as well as the style recalculation/layout I have highlighted which costs another 2ms later on when the browser does it) I think the style recalculation/layout can be avoided using transform: translate instead of modifying top/etc

image

@yoannmoinet
Copy link
Owner

I think the style recalculation/layout can be avoided using transform: translate instead of modifying top/etc

Super good suggestion.

Back in the days I wanted to have full browser support and it was easier this way.

But I guess now, translate are way more supported than before.

If you feel up to the task @MCArth you can submit a PR for it.
Otherwise I'll do it once I have some time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants