如何删除 JavaScript 画布渲染上下文的状态堆栈? [英] How to delete the state stack for a JavaScript canvas rendering context?

查看:29
本文介绍了如何删除 JavaScript 画布渲染上下文的状态堆栈?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在 JavaScript 中使用 <canvas>,并发现可能会造成非常糟糕的内存泄漏"(更像是内存爆炸).使用画布上下文时,您可以执行 context.save() 将绘图样式添加到状态堆栈"和 context.restore() 以去掉它.(请参阅有关 MDN 上呈现上下文的文档.)

I was recently working with <canvas> in JavaScript, and discovered the possibility to create a really bad "memory leak" (more like a memory explosion). When working with the canvas context, you have the ability to do context.save() to add the drawing styles to the "state stack" and context.restore() to remove it. (See the documentation for the rendering context on MDN.)

当你碰巧不断地保存到状态堆栈而不恢复时,就会出现问题.在 Chrome v50 和 Firefox v45 中,这似乎只会占用越来越多的私有内存,最终导致浏览器选项卡崩溃.(顺便说一句,JavaScript 内存在 Chrome 中不受影响,因此很难使用分析器/时间线工具对此进行调试.)

The problem occurs when you happen to continually save to the state stack without restoring. In Chrome v50 and Firefox v45 this seems to just take up more and more private memory, eventually crashing the browser tab. (Incidentally the JavaScript memory is unaffected in Chrome, so it's very hard to debug this with the profiler/timeline tools.)

我的问题:如何清除或删除画布上下文的状态堆栈?使用普通数组,您将能够检查长度,用 splice 修剪它或简单地重置为空 [],但我还没有看到用状态堆栈做任何这些的方法.

My question: How can you clear out or delete the state stack for a canvas context? With a normal array, you would be able to check on the length, trim it with splice or simply reset is back to empty [], but I haven't seen a way to do any of this with the state stack.

推荐答案

[I].. 发现了造成非常糟糕的内存泄漏"的可能性

[I].. discovered the possibility to create a really bad "memory leak"

这在技术上不是内存泄漏.泄漏将分配内存并释放指向它的指针,因此无法释放它.在这种情况下,指针被跟踪但内存未释放.

This is technically not a memory leak. A leak would be to allocate memory and loose the pointer to it so it could not be freed. In this case the pointer is tracked but the memory not released.

当你碰巧不断地保存到状态堆栈而不恢复时,就会出现问题.

The problem occurs when you happen to continually save to the state stack without restoring.

这在意料之中.分配内存而不释放它会累积分配的内存块.

That is to be expected. Allocating memory without freeing it will accumulate allocated memory blocks.

如何清除或删除画布上下文的状态堆栈?

How can you clear out or delete the state stack for a canvas context?

唯一的方法是要么恢复所有保存的状态,要么通过为画布元素设置一些大小来重置上下文(即canvas.width = canvas.width).

The only way is to either restore all saved states, or to reset the context by setting some size to the canvas element (ie. canvas.width = canvas.width).

调用 restore() 的次数比调用 save() 的次数还安全(在这种情况下,它只返回而不执行任何操作),因此理论上您可以运行它n 次迭代的循环.不过,后者更属于不良做法类别.

It's also safe to call restore() more times than save() (in which case it just returns without doing anything) so you could in theory run it through a loop of n number of iterations. This latter would be more in the bad practice category though.

但话虽如此:如果在假定相等的情况下保存和恢复的数量不匹配,通常表明代码中的其他地方存在问题.通过重置或在后期运行多个恢复来解决问题可能只会掩盖实际问题.

But with that being said: if there is a mismatch in numbers of save and restore when it's suppose to be equal, usually indicates a problem somewhere else in the code. Working around the problem with a reset or running multiple restores in post probably will only contribute to cover up the actual problem.

这是一个关于如何跟踪保存/恢复调用次数的示例 -

Here's an example on how to track the count of save/restore calls -

// NOTE: this code needs to run before a canvas context is created
CanvasRenderingContext2D.prototype.__save = CanvasRenderingContext2D.prototype.save;
CanvasRenderingContext2D.prototype.__restore = CanvasRenderingContext2D.prototype.restore;

// Our patch vectors
CanvasRenderingContext2D.prototype.__tracker = 0;
CanvasRenderingContext2D.prototype.save = function() {
  this.__tracker++;
  console.log("Track save:", this.__tracker);
  this.__save() 
}

CanvasRenderingContext2D.prototype.restore = function() {
  this.__tracker--;
  console.log("Track restore:", this.__tracker);
  this.__restore() 
}

// custom method to dump status
CanvasRenderingContext2D.prototype.trackstat = function() {
  if (this.__tracker)
    console.warn("Track stat:", this.__tracker);
  else
    console.log("Track stat: OK");
}

var ctx = document.createElement("canvas").getContext("2d");
ctx.save();                     // do a couple of save()s
ctx.save();
ctx.restore();                  // single restore()
ctx.trackstat();                // should report mismatch of 1
ctx.restore();                  // last restore()
ctx.trackstat();                // should report OK

这篇关于如何删除 JavaScript 画布渲染上下文的状态堆栈?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆