Я решил провести исследование ресурсоёмкости setTimeout, чтобы ответить на следующие вопросы:- Ощутимо ли много памяти требует setTimeout?
- Имеет ли смысл то, как назначается setTimeout: когда несколько их назначается одновременно или же назначение идёт поэтапно: следующий не ранее того, как отработал предыдущий?
- Очищает ли JS память от отработанных таймеров?
- Можно ли очистить память, используя clearTimeout по отработавшим таймерам?
Начнём:
1. Загружаем Chrome(19), запускаем консоль и встроенный диспетчер задач. Вкладка потребляет 14 084КБ.
2. Создадим рабочие функции.
Javascript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| function littleTest() {console.log(1)} // Просто функция для навешивания по таймеру.
function test(fn, loop) { // Функция навесит указанную функцию loop раз на setTimeout и вернёт каждый идентификатор таймера.
var result = [ ];
for (x = 0; x <= loop; x++) {
result.push(setTimeout(fn, 4000))
}
return result;
}
function detach(arr) { // Функция примет массив идентификаторов таймеров и очистит таймеры.
for(x = 0; x < arr.length; x++) {
clearTimeout(arr[x])
}
} |
|
И объявим их в консоли.
Ого! Браузер подоптимизировал память! Уже 13 288КБ.
3. ЗапускаемJavascript | 1
| var ids = test(littleTest, 100000); |
|
Смотрим память, как только браузер навесил все таймауты. 46 384КБ! Ого!
4. И смотрим память после отработки таймеров. 23 224КБ. Хм. Ну вот, отстрелил таймеры сборщик мусора, потребление снизилось в два раза от максимума. Но оно всё же значительно больше стартового. Какие-то обломки остались и не оптимизировались.
5. Попробуем очистить память по методу kalabuni. У нас есть все id всех таймеров. А очистим-ка мы их! Бесполезно. Наоборот, работа цикла отъела ещё небольшой кусочек памяти. 23 284КБ.
Выводы раз:- Использование большого количества таймеров приводит к увеличению потребления памяти, верно.
- Но очистку javascript производит самостоятельно, хотя и не идеально.
- clearTimeout по отработавшим таймерам бесполезен.
Посмотрим на последовательное назначение таймеров, т.е. когда таймер назначается только после того, как отработал предыдущий.
6. Загружаем Chrome(19), запускаем консоль и встроенный диспетчер задач. Вкладка потребляет 13 056КБ.
7. Запустим последовательно 100 000 таймеров.
Javascript | 1
2
3
4
5
6
| var n = 0;
function setHundredTimers() {
console.log(1);
if (n++ < 100000) setTimeout( setHundredTimers, 1 );
}
setHundredTimers(); |
|
И поснимаем скриншоты...
На двух тысячах, примерно на половине и в конце.
Выводы:- Есть небольшое потребление памяти, связанное с работой цикла. 13 920КБ потребляет вкладка.
- Почти в 10 раз меньше потребляется памяти, чем при одновременном назначении обработчиков.
- Нет растущих утечек памяти, можно оставлять комп на длительное время (более длительное, чем в предыдущем случае).
Итого: следует назначать следующий setTimeout не раньше, чем отработает предыдущий — так вы сбережёте и память и ресурсы процессора. |