
Проблеми пошуку витоку пам'яті у веб-додатку за допомогою Chrome DevTools
Браузер Google Chrome поставляється з чудовими інструментами для розробника, вони ж є в Яндекс.Браузері, новій Опері, і в інших браузерах, заснованих на базі Chromium.
Серед них є приголомшливі інструменти для роботи з пам'яттю, ознайомитися з якими можна в статті користувача Panya - «Як знаходити і усувати витоки пам'яті на прикладі Яндекс.Пошти».
Javascript зберігає об'єкт в пам'яті до тих пір, поки на нього є хоч одне посилання. Як тільки ви видаляєте всі посилання на об'єкт, він знищується збирачем сміття.
Щоб видалити об'єкт, потрібно видалити всі посилання на нього.
Це здається дуже простим, але є кілька досить несподіваних «місць» де можуть зберігатися посилання на об'єкти, тим самим затримуючи їх видалення, і створюючи витік пам'яті.
1. Консольний висновок.
Якщо в процесі роботи програми в консоль виводиться зневаджувальна інформація, то перш ніж заміряти пам'ять, консоль варто очистити.
Це не обов'язково призведе до зменшення споживання пам'яті, але на своїй практиці я вже зустрічався з випадками, коли очищення консолі звільняло об'єкти з пам'яті.
2. Увімкнені експериментальні функції переглядача.
У моєму випадку це були «JavaScript frameworks debugging» і «Support asynchronous call stacks», яка вже вийшла з експериментальних.
До тих пір, поки вони були включені, частина об'єктів в пам'яті не видалялося збирачем сміття, хоча в самому додатку посилань на них не було.
Коли я зняв галочки, проблеми зникли.
До речі, в додатку, який я розробляю, рендеряться складні шаблони на AngularJS, і з увімкненими експериментальними функціями рендер тривав близько 10 секунд, а з відключеними - всього 3.
Як справи йдуть з іншими експериментальними функціями, сказати не можу, але раджу на час пошуку витоків пам'яті все відключати.
3. Розширення переглядача.
У моєму випадку це був Batarang. Це інструмент для зневаджування програм, побудованих на AngularJS, і він у себе всередині зберігає посилання на scope програми, що створювало витік пам'яті.
Після того, як я відключив розширення, пам'ять стала звільнятися.
Плагінів, що впливають на роботу з пам'яттю може бути безліч. За посиланням, яке я дав на початку статті, рекомендується відключати взагалі всі плагіни, що, як я вважаю, є правильною порадою.
4. Функція «Record Heap Allocations».
Ця функція потрібна для того, щоб визначити, в який момент скільки пам'яті відкладається додатком, і що конкретно в який момент відкладається. Це дуже корисна річ, але в роботі цієї функції є деякі особливості.
Перше - функція показує не тільки скільки пам'яті відкладається, але і скільки звільняється («вільна» пам'ять стає світло-сірою), при цьому показувати може не завжди точно.
Для того, щоб зрозуміти, в який момент скільки пам'яті використовується, варто використовувати Timeline.
Для тесту я повторював багато разів одну дію в додатку, і дивився, що відбувається з пам'яттю.
Record Heap Allocations показував, що пам'ять очищалася не повністю, і після кожної дії залишалося трохи зайнятої пам'яті, в той час, як Timeline показував, що все очищається добре, і ніяких витоків немає.
Друге - не варто використовувати Record Heap Allocations і Timeline одночасно.
Якщо одночасно включити Record Heap Allocations і Timeline, то Timeline буде показувати, що пам'ять тече, тобто використовується у все більшому і більшому обсязі.
Якщо ж включити один тільки Timeline, то пам'ять текти не буде, що призводить до висновку, що Record Heap Allocations утримує посилання на об'єкти, а тому непридатний для відстеження «звільнення» пам'яті.
Ув'язнення
У статті я навів 4 приклади місць, де можуть бути збережені посилання на об'єкти, що перешкоджають їх видаленню збирачем сміття.
Природно, це не всі проблемні місця, а лише тільки ті, з якими зіткнувся особисто я.
Щось із цього, можливо, вже виправлено, а щось, можливо, буде виправлено в майбутньому.
Важливо розуміти, що крім найбільш розроблюваного програми посилання можуть бути збережені і в інших місцях, і це слід враховувати при пошуку витоків пам'яті.