I'm working on an app that uses p5.js for it's front end. It's a canvas that covers the whole screen and has a bunch of different components.
The app has grown to have many components that are rendered each frame, which, as you might expect, has a big impact on cpu usage.
I use an object oriented approach. That allows me to calculate all the required properties for rendering an element when they're constructed so a very small number of computations are done during draw(). The performance issues come clearly from the rendering, which sometimes has loops for things like the example above.
I am looking for ways of optimising the rendering. One idea was using graphic buffers for elements that need loops, e.g. grids and graphs (or shapes in p5.js), and for static elements (elements whose color, size, etc. rarely change).
Another option is to use the noLoop() and redraw() methods but that would make the implementation of several animations a nightmare.
Has anyone experienced performance issues (low fps, high cpu usage) using p5.js when there are a lot of elements being rendered?
Could these issues be worked around or the rendering be optimised somehow?
Will creating graphics buffers and rendering them via image() be faster than rendering normally? for example:
var canvas;
var buffer;
var w = 200,
h = 200;
var nX = 100,
nY = 100;
function setup() {
canvas = createCanvas(400, 400);
canvas.background(0);
buffer = makeGridBuffer(w, h, nX, nY);
}
function draw() {
image(buffer, 0, 0); // <- Will this be faster than
makeGrid(w, h, w, h, nX, nY); // <- this?
}
function makeGridBuffer(w, h, nLinesX, nLinesY) {
var pd = pixelDensity();
var b = createGraphics(w, h, w/2, h/2);
var v = null;
b.background(255);
b.stroke(255, 0, 0);
// Make vertical lines
for (var i = 0; i < nLinesX; i++) {
v = map(i, 0, nLinesX, 0, w);
b.line(v, 0, v, h);
}
// Make horizontal lines
for (i = 0; i < nLinesY; i++) {
v = map(i, 0, nLinesY, 0, w);
b.line(0, v, w, v);
}
return b;
}
function makeGrid(x, y, w, h, nLinesX, nLinesY) {
push();
translate(x, y);
fill(0, 255, 0);
stroke(0);
rect(0, 0, w, h);
var v = null;
// Make vertical lines
for (var i = 0; i < nLinesX; i++) {
v = map(i, 0, nLinesX, 0, w);
line(v, 0, v, h);
}
// Make horizontal lines
for (i = 0; i < nLinesY; i++) {
v = map(i, 0, nLinesY, 0, w);
line(0, v, w, v);
}
pop();
}
Pen here
Thank you all in advance!
Will creating graphics buffers and rendering them via image() be faster than rendering normally?
What happened when you tried? You went through all of that trouble creating an example, so why don't you just run it and see what happens?
For example, if I crank nX
and nY
up to 10000
each, and then comment out the image(buffer, 0, 0)
line, so that the program is manually creating the scene every frame, then I get an FPS of around 10. This shows the problem of the manual drawing slowing down the FPS.
But if I then comment out the makeGrid(w, h, w, h, nX, nY)
line so that only the image(buffer, 0, 0)
is being run, then I get an FPS of 60. This shows that creating the buffer ahead of time is better for your FPS.
Your example program draws two different things based on which line is run, but hopefully it makes intuitive sense: if you have a very complex scene, then it's better to pre-render it.
Here is a simple example that shows the difference in speed between drawing a bunch of stuff each frame vs using a buffer:
var buffer;
var circles = 10000;
function setup() {
createCanvas(400, 400);
buffer = createGraphics(width, height);
makeCircleBuffer();
}
function draw() {
if(mouseIsPressed){
image(buffer, 0, 0);
}
else{
drawCircles();
}
textSize(36);
text(frameRate(), 50, height/2);
}
function drawCircles(){
randomSeed(0);
for(var i = 0; i < circles; i++){
ellipse(random(width), random(height), 20, 20);
}
}
function makeCircleBuffer() {
randomSeed(1);
for(var i = 0; i < circles; i++){
buffer.ellipse(random(width), random(height), 20, 20);
}
}
Press the mouse to switch to a buffer approach, and notice how much faster it is.
That's going to be true no matter what animation framework you use. Switching to another framework isn't going to magically fix your problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With