首页 > 解决方案 > 无法从内存中删除已创建但从未附加到页面的画布元素

问题描述

我正在创建一个这样的画布元素:

var canvas = document.createElement('canvas');

我使用这个canvas对象来获取上下文,并从那里使用上下文中的信息进行进一步的逻辑。

var context = canvas.getContext('2d');

...

// More logic

我从不将 canvas 元素附加到文档或任何其他元素,但使用 safari devtools -> Canvas 选项卡,我可以看到无论何时运行此代码,都会不断创建 canvas 元素。它们每个大约 200KB,在一个会话中可以创建成百上千个这样的画布元素。如果页面重新加载,它们将从内存中删除,并且不再出现在画布选项卡中。

但是,如果页面没有重新加载并且画布建立起来,您会看到性能下降。

那么,如果这些画布元素从未附加到页面,我该如何从内存中删除它们呢?

请参阅下面的画布选项卡图片(仅适用于 Safari,因为较新版本的 Chrome 和 Firefox 不支持它)。第一个画布对象是预期的,其他的我想删除。我正在使用 javascript 和 jquery。

在此处输入图像描述

标签: javascriptcanvas

解决方案


问题来自非常画布 dev-tool
它是保持对这些画布元素的引用并阻止垃圾收集器正常工作的罪魁祸首。

作为证明,尝试运行以下代码段,首先关闭开发工具,然后在“画布”选项卡上打开它。

var canvas, context;
for (let i=0; i<100; i++) {
  canvas = document.createElement( 'canvas' );
  canvas.width = canvas.height = 5000;
  context = canvas.getContext( '2d' );
}
console.log( 'done' );

当开发工具关闭时,它会在 Safari 上无缝运行。
在“完成”消息出现后打开它会显示页面上只有一个画布处于活动状态。

从我的 Safari 12.1.2 截取的屏幕截图显示了一个活动画布

但是,随着开发工具的打开,它会开始卡顿,直到控制台中出现一些消息。

“[警告] 总画布内存使用超过最大限制......”

在画布面板中,我们将在此消息弹出之前生成的所有内容都标记为活动状态。

从我的 Safari 12.1.2 截取的屏幕截图显示了几个活动画布


因此,为避免这种情况,请避免在此工具打开时创建太多画布。

请注意,根据这个答案,正如用户minimo最初提出的那样,在使用后设置画布的widthheight属性将最大限度地减少这个问题,这是非常有意义的,因为现在浏览器只有一个 0 x 0px 的缓冲区来保存在内存中。


推荐阅读