Safari 中的数据 URI 泄漏(原为:HTML5 画布内存泄漏) [英] Data URI leak in Safari (was: Memory Leak with HTML5 canvas)

查看:23
本文介绍了Safari 中的数据 URI 泄漏(原为:HTML5 画布内存泄漏)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个网页,它通过 Websocket 接收 base64 编码的位图,然后将它们绘制到画布上.它完美地工作.除了浏览器(无论是 Firefox、Chrome 还是 Safari)的内存使用量随着每个图像的增加而增加,并且永远不会下降.因此,我的代码中一定存在内存泄漏或其他一些错误.如果我注释掉对 context.drawImage 的调用,则不会发生内存泄漏(但当然永远不会绘制图像).以下是我网页的片段.任何帮助表示赞赏.谢谢!

I have created a webpage that receives base64 encoded bitmaps over a Websocket and then draws them to a canvas. It works perfectly. Except, the browser's (whether Firefox, Chrome, or Safari) memory usage increases with each image and never goes down. So, there must be a memory leak in my code or some other bug. If I comment out the call to context.drawImage, the memory leak does not occur (but then of course the image is never drawn). Below are snippets from my webpage. Any help is appreciated. Thanks!

// global variables
var canvas;
var context;

...

ws.onmessage = function(evt)
{
    var received_msg = evt.data;
    var display_image = new Image();
    display_image.onload = function ()
    {
        context.drawImage(this, 0, 0);
    }
    display_image.src = 'data:image/bmp;base64,'+received_msg;
}

...

canvas=document.getElementById('ImageCanvas');
context=canvas.getContext('2d');

...

<canvas id="ImageCanvas" width="430" height="330"></canvas>

<小时>

更新 12/19/2011


UPDATE 12/19/2011

我可以通过使用 createElement/appendChild 和 removeChild 每 100 张左右动态创建/销毁画布来解决这个问题.之后,我在使用 Firefox 和 Chrome 时不再出现内存问题.

I can work around this problem by dynamically creating/destroying the canvas every 100 images or so with createElement/appendChild and removeChild. After that, I have no more memory problems with Firefox and Chrome.

然而,Safari 仍然存在内存使用问题,但我认为这是一个不同的问题,与 Canvas 无关.在 Safari 中反复更改图像的src"似乎存在问题,好像它永远不会释放此内存.

However, Safari still has a memory usage problem, but I think it is a different problem, unrelated to Canvas. There seems to be an issue with repeatedly changing the "src" of the image in Safari, as if it will never free this memory.

display_image.src = 'data:image/bmp;base64,'+received_msg;  

这与以下站点中描述的问题相同:http://waldheinz.de/2010/06/webkit-leaks-data-uris/

This is the same problem described on the following site: http://waldheinz.de/2010/06/webkit-leaks-data-uris/

更新 12/21/2011

UPDATE 12/21/2011

我希望通过将我收到的 base64 字符串转换为 blob(使用我在本网站上找到的dataURItoBlob"函数)并返回带有 window.URL.createObjectURL 的 URL 来解决这个 Safari 问题,设置我的图像src 到这个 URL,然后通过调用 window.URL.revokeObjectURL 释放内存.我让这一切正常工作,Chrome 和 Firefox 正确显示图像.不幸的是,Safari 似乎不支持 BlobBuilder,因此它不是我可以使用的解决方案.这很奇怪,因为包括 O'Reilly 编程 HTML5 应用程序"一书在内的许多地方都指出 Safari/WebKit Nightly Builds 支持 BlobBuilder.我从 http://nightly.webkit.org/ 下载了最新的 Windows nightly build 并运行了 WebKit.exe 但是BlobBuilder 和 WebKitBlobBuilder 仍未定义.

I was hoping to get around this Safari problem by converting my received base64 string to a blob (with a "dataURItoBlob" function that I found on this site) and back to a URL with window.URL.createObjectURL, setting my image src to this URL, and then later freeing the memory by calling window.URL.revokeObjectURL. I got this all working, and Chrome and Firefox display the images correctly. Unfortunately, Safari does not appear to have support for BlobBuilder, so it is not a solution I can use. This is strange, since many places including the O'Reilly "Programming HTML5 Applications" book state that BlobBuilder is supported in Safari/WebKit Nightly Builds. I downloaded the latest Windows nightly build from http://nightly.webkit.org/ and ran WebKit.exe but BlobBuilder and WebKitBlobBuilder are still undefined.

更新 01/03/2012

UPDATE 01/03/2012

好的,我最终通过使用 atob() 解码 base64 编码的数据 URI 字符串,然后创建像素数据数组并使用 putImageData 将其写入画布来解决此问题(请参阅 http://beej.us/blog/2010/02/html5s-canvas-part-ii-pixel-操纵/).这样做(而不是不断修改图像的src"并在 onload 函数中调用 drawImage),我不再在 Safari 或任何浏览器中看到内存泄漏.

Ok, I finally fixed this by decoding the base64-encoded data URI string with atob() and then creating a pixel data array and writing it to the canvas with putImageData (see http://beej.us/blog/2010/02/html5s-canvas-part-ii-pixel-manipulation/). Doing it this way (as opposed to constantly modifying an image's "src" and calling drawImage in the onload function), I no longer see a memory leak in Safari or any browser.

推荐答案

没有实际工作代码,我们只能推测原因.

Without actual working code we can only speculate as to why.

如果您一遍又一遍地发送相同的图像,则每次都在制作新图像.这不好.你会想要做这样的事情:

If you're sending the same image over and over you're making a new image every time. This is bad. You'd want to do something like this:

var images = {}; // a map of all the images

ws.onmessage = function(evt)
{
    var received_msg = evt.data;
    var display_image;
    var src = 'data:image/bmp;base64,'+received_msg;
    // We've got two distinct scenarios here for images coming over the line:
    if (images[src] !== undefined) {
      // Image has come over before and therefore already been created,
      // so don't make a new one!
      display_image = images[src];
      display_image.onload = function () {
          context.drawImage(this, 0, 0);
      }
    } else {
      // Never before seen image, make a new Image()
      display_image = new Image();
      display_image.onload = function () {
          context.drawImage(this, 0, 0);
      }
      display_image.src = src;
      images[src] = display_image; // save it for reuse
    }
}

有更有效的方法来编写它(例如,我正在复制加载代码,并且我没有检查图像是否已经完成).不过,我会把这些部分留给你,你懂的.

There are more efficient ways to write that (I'm duplicating onload code for instance, and I am not checking to see if an image is already complete). I'll leave those parts up to you though, you get the idea.

这篇关于Safari 中的数据 URI 泄漏(原为:HTML5 画布内存泄漏)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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