У меня есть веб-страница, которая быстро передает JSON с сервера и отображает его биты, примерно 10 раз в секунду. Одна часть представляет собой изображение PNG в кодировке base64. Я нашел несколько разных способов отображения изображения, но все они вызывают неограниченное использование памяти. Он поднимается с 50 МБ до 2 ГБ в течение нескольких минут. Происходит с Chrome, Safari и Firefox. Не пробовал IE.
Сначала я обнаружил использование памяти, просмотрев Activity Monitor.app - процесс Google Chrome Renderer постоянно потребляет память. Затем я посмотрел на инспектора ресурсов 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
содержимое
Я тут что-то не так делаю - изображения маленькие и выглядят как случайный шум. Этот метод использует контролируемый объем памяти (увеличивается до 100 МБ и останавливается), но он медленный, особенно в Safari (~ 50% загрузки ЦП там, 17% в Chrome). Идея возникла из этого аналогичного вопроса SO: Утечка URI данных в Safari (была: Утечка памяти с помощью 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);