Во время тестирования нашей библиотеки Javascript я считаю, что мы обнаружили серьезную утечку памяти в IE10 (v10.0.9200.16519 - Windows 8 64 бит). Реализация Javascript setInterval
.
Простой тестовый пример показал, что если переменная фиксируется в закрытии передаваемой функции как аргумент для последующего выполнения, она, похоже, никогда не становится подходящей для сбора мусора, то есть браузер, похоже, содержит ссылку на функции или, по крайней мере, замыкающих переменных.
Наш тестовый экземпляр выполняет функцию setInterval
только один раз, а затем очищает интервал таймера, то есть через некоторое время никакой код не запускается больше, и никакие переменные не доступны больше (насколько я могу видеть, что в этом коде не отображаются глобальные переменные, за исключением метода для запуска в onload
), тем не менее процесс занимает половину гигабайта памяти (в зависимости от количества итераций).
Интересно, что этого не происходит, если вместо этого использовать метод setTimeout
(а также проблема не существует в IE9 и текущих версиях Chrome, FF).
Проблему можно увидеть с помощью этой скрипты.
Запустите его в новом экземпляре IE10 в Windows 8 и откройте диспетчер задач, чтобы посмотреть использование памяти. Он быстро вырастет до 350 мегабайт и останется там после выполнения script.
Это важная часть проблемного кода:
// the function that when called multiple times will cause the leak in IE10
var eatMemory = function() {
var a = null; // the captured closure variable
var intervalId = setInterval(function() {
a = createBigArray(); // call a method that allocates a lot of memory
clearInterval(intervalId); // stop the interval timer
}, 100);
}
(Я знаю, что легко установить этот конкретный фрагмент кода, но это не главное - это всего лишь крошечный фрагмент кода, с которым мы столкнулись, что воспроизводит проблему. Реальный код фактически захватывает this
в закрытие и этот объект никогда не собирают мусор.)
Есть ли ошибка в нашем коде или есть способ использовать setInterval
, где переменная закрытия содержит ссылку на большой объект без запуска утечки памяти и без возврата к "рекурсивным" вызовам setTimeout
?
(Я также разместил вопрос в MSDN)
Обновление: Эта проблема также существует в IE10 в Windows 7, но не существует, если вы переключаетесь в режим стандартов IE9. Я отправил это в MS Connect и сообщит о достигнутом прогрессе.
Обновление: Microsoft приняла проблему и сообщила, что она исправлена в IE11 (версия для предварительного просмотра). Я сам это подтвердил (кто-нибудь?)
Обновление: IE 11 официально выпущен, и я больше не могу воспроизвести проблему с этой версией с моей системой (Win 8.1 Pro 64bit).