У меня есть веб-страница, которая быстро передает JSON с сервера и отображает его бит примерно 10 раз/секунду. Одна часть представляет собой PNG-изображение с кодировкой base64. Я нашел несколько разных способов отображения изображения, но все они вызывают неограниченное использование памяти. Он поднимается с 50 мб до 2 гб за считанные минуты. Случается с Chrome, Safari и Firefox. Не пробовал IE.
Сначала я обнаружил использование памяти, посмотрев на Activity Monitor.app - процесс Google Chrome Renderer постоянно ест память. Затем я просмотрел инспектор ресурсов Chrome (View
> Developer
> Developer Tools
, Resources
), и я увидел, что он кэширует изображения. Каждый раз, когда я менял img src
или создавал новое изображение() и устанавливал его src
, Chrome кэшировал его. Я могу только представить, что другие браузеры делают то же самое.
Есть ли способ контролировать это кеширование? Могу ли я отключить его или сделать что-то скрытое, чтобы этого не произошло?
Изменить: я хотел бы использовать эту технику в Safari/Mobile Safari. Кроме того, я открыт для других методов быстрого обновления изображения, если у кого есть какие-либо идеи.
Вот методы, которые я пробовал. Каждый из них находится в функции, которая вызывается при завершении AJAX.
Метод 1 - Непосредственно установите атрибут src
в теге img
Fast. Отображает красиво. Утечки, как сумасшедшие.
$('#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)
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);