我有一个网页可以快速从服务器流式传输 JSON 并显示它的一部分,大约 10 次/秒。一部分是 base64 编码的 PNG 图像。我找到了几种不同的显示图像的方法,但所有这些方法都会导致无限的内存使用。它在几分钟内从 50mb 上升到 2gb。发生在 Chrome、Safari 和 Firefox 上。没试过IE。
我首先通过查看 Activity Monitor.app 发现了内存使用情况——Google Chrome 渲染器进程不断消耗内存。然后,我查看了 Chrome 的资源检查器 ( View
> Developer
> Developer Tools
, Resources
),我看到它正在缓存图像。每次我更改img src
或创建一个新的 Image() 并设置它src
时,Chrome 都会缓存它。我只能想象其他浏览器也在做同样的事情。
有没有办法控制这种缓存?我可以把它关掉,或者做一些偷偷摸摸的事情让它永远不会发生吗?
编辑:我希望能够在 Safari/Mobile Safari 中使用该技术。此外,如果有人有任何想法,我愿意接受其他快速刷新图像的方法。
以下是我尝试过的方法。每个都驻留在一个函数中,该函数在 AJAX 完成时被调用。
方法 1 - 直接在标签上设置src
属性img
快速地。显示很好。像疯了一样泄漏。
$('#placeholder_img').attr('src', 'data:image/png;base64,' + imgString);
方法 2 - 替换img
为canvas
, 并使用drawImage
显示正常,但仍然泄漏。
var canvas = document.getElementById("placeholder_canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "data:image/png;base64," + imgString;
方法 3 - 转换为二进制并替换canvas
内容
我在这里做错了——图像显示很小,看起来像随机噪音。此方法使用受控的内存量(增长到 100mb 并停止),但速度很慢,尤其是在 Safari 中(那里的 CPU 使用率约为 50%,Chrome 中为 17%)。这个想法来自这个类似的 SO 问题:Data URI leak in Safari (was: Memory Leak with HTML5 canvas)
var img = atob(imgString);
var binimg = [];
for(var i = 0; i < img.length; i++) {
binimg.push(img.charCodeAt(i));
}
var bytearray = new Uint8Array(binimg);
// Grab the existing image from canvas
var ctx = document.getElementById("placeholder_canvas").getContext("2d");
var width = ctx.canvas.width,
height = ctx.canvas.height;
var imgdata = ctx.getImageData(0, 0, width, height);
// Overwrite it with new data
for(var i = 8, len = imgdata.data.length; i < len; i++) {
imgdata.data[i-8] = bytearray[i];
}
// Write it back
ctx.putImageData(imgdata, 0, 0);