Skip to content

Issue #1644: Fix performance issue with zooming - #2102

Open
blayzen-w wants to merge 1 commit into
paperjs:developfrom
carstickers:zoom-performance-issues
Open

Issue #1644: Fix performance issue with zooming#2102
blayzen-w wants to merge 1 commit into
paperjs:developfrom
carstickers:zoom-performance-issues

Conversation

@blayzen-w

Copy link
Copy Markdown

Description

Zooming can have poor performance and result in crashing the browser, breaking the canvas, and very high memory usage.

This is happening because Item.draw is requesting a canvas at extreme sizes when using indirect drawing, where something must be drawn to a separate canvas first and then composited back onto the main canvas.

paper.js/src/item/Item.js

Lines 4451 to 4470 in 92775f5

var bounds = this.getStrokeBounds(viewMatrix);
if (!bounds.width || !bounds.height) {
// Item won't be drawn so its global matrix need to be removed
// from the stack (#1561).
matrices.pop();
return;
}
// Store previous offset and save the main context, so we can
// draw onto it later.
prevOffset = param.offset;
// Floor the offset and ceil the size, so we don't cut off any
// antialiased pixels when drawing onto the temporary canvas.
itemOffset = param.offset = bounds.getTopLeft().floor();
// Set ctx to the context of the temporary canvas, so we draw onto
// it, instead of the mainCtx.
mainCtx = ctx;
ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)
.multiply(pixelRatio));
if (pixelRatio !== 1)
ctx.scale(pixelRatio, pixelRatio);

The bounds from getStrokeBounds can be upwards of 25,000+ by 25,000+ at high zoom levels, and that is directly used with CanvasProvider.getContext to get a canvas of that size.

canvas.width = width;
canvas.height = height;

As soon as the canvas width/height is set, the browser will try to allocate resources for a canvas of that size.

In Chrome you can see the browser memory go from 500mb to 3800mb. The frame time will drop from 1ms to 403ms+. Often this will cause a some kind of crash that will break the canvas. This can cause rendering artifacts and require the page to be reloaded.

This fix will use the current canvas size and transform for the indirect rendering. This will limit the unbounded resource allocation and fix it to the size of the visible canvas. This results in a nearly 400x performance increase at high zoom levels.

Related issues

Checklist

  • New tests added or existing tests modified to cover all changes
  • Code conforms with the JSHint rules (yarn run jshint passes)

I believe the existing tests should cover the change since its part of the core rendering function. But if its doesn't and this PR gains traction I can add something.

Let me know if you can think of any problems with this change and I can look into them. I'll also use this in prod for a while and report back after a few weeks.

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

Successfully merging this pull request may close these issues.

1 participant