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

Changing the FPS cap and manipulating pixels causes an permanent FPS drop whenever the cursor clicks/hovers on the page #6444

Open
3 of 17 tasks
motis1 opened this issue Sep 29, 2023 · 5 comments

Comments

@motis1
Copy link

motis1 commented Sep 29, 2023

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build Process
  • Unit Testing
  • Internalization
  • Friendly Errors
  • Other (specify if possible)

p5.js version

1.7.0

Web browser and version

Google Chrome: 117.0.5938.92 (Official Build) (64-bit) (cohort: Stable)

Operating System

Windows 10 Pro: 10.0.19045 Build 19045

Steps to reproduce this

Details

Changing the FPS cap and manipulating pixels causes a permanent drop in performance whenever the cursor clicks/hovers on the page.

It also appears that the FPS drop incurred by hovering over the page can only happen for a short period of time after the page has just loaded but clicking seems to work whenever during the lifetime of the page.

P.S. I accidentally created an empty issue whilst trying to create this one. If it could be deleted by someone who can it would be greatly appreciated.

Steps:

  1. Run the code snippet attached to this issue
  2. Hover/Click on the page/canvas and notice the drop in FPS.
  3. If you do not observe a drop in FPS, consider adjusting the SIZE constant so that there is enough load to make the baseline FPS below that of your monitors refresh rate.

Snippet:

const SIZE = 600;
const FRAME_RATE = 999;

function setup() {
    createCanvas(SIZE, SIZE);
    frameRate(FRAME_RATE);
}

function draw() {
    background(0);

    for (let y = 0; y < SIZE; y++) {
        for (let x = 0; x < SIZE; x++) {
            set(x, y, 0);
        }
    }

    updatePixels();

    fill(255);
    text(Math.round(frameRate()), 50, 50);
}
@davepagurek
Copy link
Contributor

Do you see a similar slowdown when using loadPixels(), updating the pixels[] array, then calling setPixels()? It's known that calling set() to update a grid of pixels will be slow, as it tries to update the canvas after each call rather than doing it all at once.

@motis1
Copy link
Author

motis1 commented Sep 30, 2023

Yes, it is possible to observe this problem using the pixels[] array along with loadPixels() and updatePixels() instead of the set() method.

Using the following code, it is possible to observe this problem using a simple graph using both the pixels[] and set().
For reasons unknown to me, this bug is not reproducible inside the p5.js editor.
For the best results run the JavaScript inside of a basic HTML page with p5.js included using a CDN.

const SIZE = 800;
const FRAME_RATE = 180;

let graphTicks = [];

function drawGraph() {
    noFill();
    stroke(255);
    beginShape();

    for (let i = 0; i < graphTicks.length; i++) {
        let x = (graphTicks[i].timestamp / frameCount) * SIZE;
        let y = SIZE - ((graphTicks[i].frameRate / FRAME_RATE) * SIZE);

        curveVertex(x, y);
    }

    endShape();
}

function useSetFunc() {
    for (let y = 0; y < SIZE; y++) {
        for (let x = 0; x < SIZE; x++) {
            set(x, y, 0);
        }
    }

    updatePixels();
}

function usePixelsArray() {
    loadPixels();

    for (let y = 0; y < SIZE; y++) {
        for (let x = 0; x < SIZE; x++) {
            let d = pixelDensity();
            for (let i = 0; i < d; i++) {
                for (let j = 0; j < d; j++) {
                    // loop over
                    index = 4 * ((y * d + j) * width * d + (x * d + i));
                    pixels[index] = 0;
                    pixels[index + 1] = 0;
                    pixels[index + 2] = 0;
                    pixels[index + 3] = 255;
                }
            }
        }
    }

    updatePixels();
}

function setup() {
    createCanvas(SIZE, SIZE);
    frameRate(FRAME_RATE);
}

function draw() {
    graphTicks.push({
        timestamp: frameCount,
        frameRate: frameRate()
    });

    background(0);

    // Uncomment one of the two functions
    // useSetFunc();
    usePixelsArray();

    drawGraph();

    fill(255);
    noStroke();
    text(Math.round(frameRate()), 50, 50);
}

@Vishal2002
Copy link
Contributor

Is this issue still open for contribution?

@rayyan21d
Copy link

rayyan21d commented Jan 18, 2024

I'm interested in contributing to this issue @motis1
Are there any helpful docs that would help me better understand this?

@davepagurek
Copy link
Contributor

Thanks @Vishal2002 for doing some profiling! It seems like there's not a new function being called after a click, but rather, the set() function just gets slower. Some additional notes from some more testing on my end:

  • The slowdown is less apparent on 1.9.0 than 1.7.0, but still present
  • I don't notice a slowdown in Firefox, just Chrome
  • I can personally reproduce this within the p5 editor

@rayyan21d the way we've been testing so far is with the browser profiler, where each draw call takes longer after clicking compared to before:
image

I wonder if this is a known thing in Chrome? Maybe some of you can help look up any existing Chrome/Chromium bug reports that sound similar?

Another way to investigate further: is it also faster on 1.9.0 compared to 1.7.0 for you? If so, you can try using git bisect to find a commit between then and now where the slowness gets better, just so we can get a sense of what affects it. It doesn't look like any significant changes happened between those versions to the set() or updatePixels() methods, just some indentation fixes.

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

No branches or pull requests

4 participants