javascript内存泄漏与HTML5 getImageData [英] javascript memory leak with HTML5 getImageData

查看:839
本文介绍了javascript内存泄漏与HTML5 getImageData的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力为一个我创建的javascript游戏制作一些视觉效果,我注意到一个代码,我使用它调制我的sprite的颜色,使我的浏览器内存使用量增加

您可以在这里看到代码和内存泄漏: http://timzook.tk/javascript/test.html



此内存泄漏只发生在我的updateimage()函数中,当我从我的画布上下文每帧(通过setInterval)调用getImageData为了使一个新的ImageData对象重新着色。我会认为javascript的垃圾收集器会破坏旧的,但如果不是我不知道如何手动销毁它。



我的问题与这个非常相似:什么是泄漏的内存使用getImageData,javascript,HTML5 canvas 但是,我需要我的代码运行每个框架在函数调用setInterval,他的解决方案移动外面的setInterval函数对我来说不是一个选项,我不能留言,问他是否找到一些其他解决方法。



注意给人们测试它:由于这个例子使用getImageData,它不能在本地测试出来只是通过将其放在.html文件中,需要一个Web服务器。此外,它显然使用HTML5元素,所以一些浏览器将不能使用它。



编辑:* SOLVED * 解决方案下面固定它。我没有意识到你可以使用canvas元素,就像你可以在drawImage()中使用一个图像,我重新构建了我的代码,所以现在使用显着减少的内存。

解决方案

如果有人想看到它,我就把这个更改的代码上传到上面链接的页面。从您的调用泄漏到 getImageData()。您的问题的根源是这一行:



TempImg.src = ImgCanvas.toDataURL(image / png);



有效地,每次执行代码行时,浏览器下载另一个图像并将其存储在内存中。所以,你最终得到的是一个快速增长的缓存。您可以通过在Chrome中打开网站并检查开发人员工具的资源标签( ctrl + shift + i ),轻松验证这一点。



您可以通过制作 TempImgCanvas 并将图像数据存储在该画布上,而不是在每次调用 updateimage()循环。



我必须离开一段时间,但我可以在几个

编辑:我重新组织了一些事情位和消除您的缓存问题。你只需要做两个改变。第一个是用这个替换你的 updateimage()函数:

  function updateimage(){
var TempImgData = ImgContext.getImageData(0,0,ImgCanvas.width,ImgCanvas.height);
var NewData = TempImgData.data;
var OrigData = ImgData.data;

//更改图像颜色
var len = 4 * ImgData.width * ImgData.height-1;
for(var i = 0; i <= len; i + = 4){
NewData [i + 0] = OrigData [i + 0] * color.r;
NewData [i + 1] = OrigData [i + 1] * color.g;
NewData [i + 2] = OrigData [i + 2] * color.b;
NewData [i + 3] = OrigData [i + 3];
}

//将改变的图像放到画布上
ImgContext.putImageData(TempImgData,0,0);
}

第二个是更新 draw )如下:



drawImg(ImgCanvas,Positions [i] .x,Positions [i]。 y,Positions [i] .x + Positions [i] .y);



使用这个更新的代码,基本(白色)图像数据,并基于每次我们经过 updateimage()函数计算新值。当您调用 getImageData()时,您会在画布上收到图片数据的复制,因此如果您编辑画布或数据,一个保持不变。你已经抓取了原始的基础图片数据开始,所以使用它而不是每次我们更新时重新获取它是有意义的。



,你会注意到我修改了你的循环,稍微改变了图像颜色。通过获取要访问/修改的实际数据数组的句柄,您可以节省自己每次通过循环时都必须从父对象中解析数组位置。这种技术实际上导致了相当不错的性能提升。你的表现很好,但它不会伤害更高效,因为它很简单。


I've been working on trying to make some visual effects for a javascript game I'm creating, and I noticed a piece of code that I'm using to modulate the color of my sprites makes my browsers memory usage go up and up, seemingly without limit.

You can see the code and the memory leak here: http://timzook.tk/javascript/test.html

This memory leak only happens in my updateimage() function when I call getImageData from my canvas context every frame (via setInterval) in order to make a new ImageData object to recolor. I would have thought that javascript's garbage collector would be destroying the old one, but if not I have no idea how to destroy it manually. Any help figuring out why it does this or how to fix it would be appreciated.

My question is very similar to this one: What is leaking memory with this use of getImageData, javascript, HTML5 canvas However, I NEED my code to run every frame in the functioned called by setInterval, his solution of moving it outside the setInterval function isn't an option for me, and I can't leave a comment asking if he found some other method of solving it.

Note to people testing it out: Since this example uses getImageData, it can't be tested out locally just by throwing it in a .html file, a web server is required. Also it obviously uses HTML5 elements so some browsers won't work with it.

Edit: *SOLVED* Thanks, the solution below fixed it. I didn't realize that you could use a canvas element the same way as you could use an image in drawImage(), I restructured my code so it now uses significantly less memory. I uploaded this changed code to the page linked above, if anyone wants to see it.

解决方案

You aren't getting a memory leak from your calls to getImageData(). The source of your problem is this line:

TempImg.src = ImgCanvas.toDataURL("image/png");

Effectively, every time that line of code is executed the browser "downloads" another image and stores it in memory. So, what you actually end up with is a cache that is growing very quickly. You can easily verify this by opening the site in Chrome and checking the resources tab of the developer tools (ctrl+shift+i).

You can work around this by making a TempImgCanvas and storing your image data on that canvas instead of keeping an image object updated after every call to your updateimage() loop.

I have to step away for a while, but I can work up an example in a few hours when I get back, if you would like.


Edit: I restructured things a bit and eliminated your caching issue. You just have to make two changes. The first is replacing your updateimage() function with this one:

function updateimage() {    
    var TempImgData = ImgContext.getImageData(0, 0, ImgCanvas.width, ImgCanvas.height);
    var NewData = TempImgData.data;
    var OrigData = ImgData.data;

    //Change image color
    var len = 4*ImgData.width*ImgData.height-1;
    for(var i=0;i<=len;i+=4) {
        NewData[i+0] = OrigData[i+0] * color.r;
        NewData[i+1] = OrigData[i+1] * color.g;
        NewData[i+2] = OrigData[i+2] * color.b;
        NewData[i+3] = OrigData[i+3];
    }

    //Put changed image onto the canvas
    ImgContext.putImageData(TempImgData, 0, 0);
}

The second is updating the last line in draw() to read as follows:

drawImg(ImgCanvas, Positions[i].x, Positions[i].y, Positions[i].x+Positions[i].y);

Using this updated code, we simply refer to the original base (white) image data and calculate new values based on that every time we go through the updateimage() function. When you call getImageData() you receive a copy of the image data on the canvas, so if you edit the canvas or the data, the other one remains untouched. You were already grabbing the original base image data to begin with, so it made sense to just use that instead of having to re-acquire it every time we updated.

Also, you'll notice that I modified your loop that changes the image color slightly. By obtaining a handle to the actual data array that you want to access/modify, you save yourself having to resolve the array location from the parent object every time you go through the loop. This technique actually results in a pretty nice performance boost. Your performance was fine to start with, but it can't hurt to be more efficient since it's pretty straight-forward.

这篇关于javascript内存泄漏与HTML5 getImageData的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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