Словник для витоків пам' яті і збирання сміття
Вивчіть основний англійський словник для діагностики витоків пам’ яті і обговорення поведінки збирання сміття у мовах з керованою пам’ яттю.
Проблеми з пам’яттю є одними з найскладніших помилок, які потрібно чітко пояснити, частково тому, що словник спочатку справді заплутаний — «витік» в мові зі збиранням сміття не означає того, що означає в мові з ручним керуванням пам’яттю. Використання цього словника дуже допомагає під час написання повідомлення про інцидент, запитання друзям по команді дампів або пояснення неспеціалісту, чому використання пам’ яті службою постійно зростає.
Фундаментальні поняття
1. Витік пам’ яті
Пам’ ять, яку програма виділила, але більше не потребує, але не вдається звільнити, що призводить до безмежного зростання використання пам’ яті з часом.
** Використання: ** * “Пам’ ять цієї служби постійно зростає під час тривалого навантаження і ніколи не зменшується — це сильний сигнал про витік пам’ яті десь у шляху запиту.” *
2-й. Збірка сміття (GC)
Автоматичний процес, за допомогою якого час виконання з керованою пам’ яттю визначає і відновлює пам’ ять, яка більше не доступна для програми, вилучаючи необхідність вручну звільняти її.
** Використання: ** * “Навіть з обробкою збирання сміття для нас, ми все ще можемо витікати пам’ яті — це просто означає, що щось містить непередбачену посилання, а не сирий вказівник, який забувають.” *
3. доступність
Властивість об’ єкта, доступ до якого все ще можливий з кореневого посилання (наприклад, глобальної змінної або активного блоку стека), яку використовують збиральні програми сміття для визначення того, що можна збирати.
** Використання: ** * “Цей запис кешу технічно все ще доступний за допомогою статичної посилання, отже, збірник сміття правильно залишає його без уваги — проблема в тому, що нічого не вилучає його з кешу.” *
4-й. GC pause (Стоп-Світова пауза)
Період, протягом якого збірник сміття призупиняє деякі або всі виконання програми, щоб безпечно відновити пам’ ять, що може призвести до видимих піків затримки.
** Використання: ** * “Ми побачили 400- мілісекундну паузу GC прямо перед тим, як запит перевищив час очікування — сама пауза, а не логіка програми, ймовірно, є справжньою причиною повільної відповіді.” *
П’ятий
Область пам’ яті, де знаходяться динамічно розподілені об’ єкти програми, на відміну від стека, у якому зберігаються короткочасні дані локальної функції.
** Використання: ** *“Використання стека продовжує зростати протягом циклів GC замість повернення до базового рівня, що є найяснішою ознакою того, що ми насправді витікаємо, а не просто бачимо нормальне вилучення призначення.” *
Діагностичний словник
6. Звалище
Знімок усього, що було розподілено на купі у даний момент, використовується для аналізу того, що споживає пам’ ять, і відстеження неочікуваного збереження до його джерела.
** Використання: ** * “Чи можна отримати дамп стека наступного разу, коли використання пам’ яті перевищить поріг попередження? Це дозволить нам побачити, що саме накопичується, замість того, щоб здогадуватися»
7. Збережений розмір
Загальна кількість пам’ яті, яка буде звільнено, якщо певний об’ єкт буде знищено, включаючи всі об’ єкти, які він виключно підтримує у живому стані — ключова метричний показник для пошуку справжнього джерела витоку.
** Використання: ** * “Цей об’ єкт має невеликий розмір, але його збережений розмір величезний, оскільки це єдина річ, яка зберігає доступним весь кешований набір даних.” *
8-й. Dominator (у графі купівлі)
Об’ єкт, який знаходиться на кожному шляху від кореня до іншого об’ єкта, тобто зібрання домінанта також зробить недоступним домінуючий об’ єкт — використовується для відстеження ланцюгів зберігання назад до кореневої причини.
** Використання: ** * “Прослідкування ланцюга домінанта привело нас прямо назад до одного слухача подій, який ніколи не був вилучено, що підтримувало життя всього цього піддерева.” *
9. Утечка даних
Особливий шаблон у мовах зі збиранням сміття, де ненавмисне посилання — наприклад, запис у кеші, підписаний слухач або закінчення — зберігає об’ єкт доступним довгий час після того, як він дійсно потрібен.
** Використання: ** *“Це не помилка сирої пам’ яті — це витік посилання, де слухач події, зареєстрований під час завантаження сторінки, ніколи не буде вилучено, отже компонент, на який він посилається, ніколи не буде зібрано.” *
10. Переповнення пам’ яті
Швидкість, з якою об’ єкти з коротким терміном служби буде розподілено і згодом зібрано, що може призвести до збільшення витрат на швидкість через часті цикли GC навіть без жодних фактичних витоків.
Використання: “Ми не протікаємо тут - це втрата пам’яті від виділення нового об’єкта на запит в гарячому циклі, і це запускає GC набагато частіше, ніж потрібно.”
Звичайні причини
11. закриття захоплення
Ситуація, коли закривання ненавмисно зберігає посилання на великий об’ єкт з його обсягу, зберігаючи цей об’ єкт живим доти, доки само закривання буде доступним.
** Використання: ** * “Це закриття потребує лише одного поля з об’ єкта, що його закриває, але воно захоплює все, отже, весь об’ єкт залишається живим доки цей зворотній виклик буде зареєстровано.” *
12-й. Відокремлений вузол DOM
Елемент DOM, який було вилучено з видимої сторінки, але на який все ще посилається JavaScript, що заважає переглядачеві відновлювати пам’ ять, яку він займає.
** Використання: ** “Знімок купи показує тисячі відокремлених вузлів DOM — ми вилучили ці елементи зі сторінки, але ніколи не очищали посилання, які наш код все ще тримав до них.”
13. Утечка слухача
Витік пам’ яті, спричинений спеціально слухачами подій або підписками, які зареєстровано, але ніколи не анульовано, що зберігає об’ єкти, на які вони посилаються, живими назавжди.
** Використання: ** * “Кожного разу, коли цей модальний об’ єкт відкривається, він додає новий слухач до об’ єкта вікна, але ніколи не вилучає старого слухача при закритті — це витік слухача, який з’ являється при кожному відкритті.” *
14. Необмежений кеш
Кеш без правил вилучення або обмеження розміру, який буде зростати нескінченно і функціонально поводитиметься як витік пам’ яті, навіть якщо зберігання було технічно навмисним.
** Використання: ** “Технічно тут нічого не є багом — це необмежений кеш, якому ніколи не надавалося правила вигнання, тому він просто продовжує зростати, поки не вичерпається наявна пам’ ять.”
15. Гіпотеза покоління
Спостереження, що лежить в основі багатьох проектів збирання сміття, що більшість об’єктів помирають молодими, що виправдовує збирання недавно виділених об’єктів (молодше покоління) частіше, ніж старіших.
** Використання: ** * “Цей збірник налаштовано на гіпотезу покоління, отже більшість об’ єктів з коротким терміном запитів збираються дешевше у молодому поколінні, і лише довготривалі об’ єкти платять вартість просування.” *
Ключеві моменти
- Зрозумійте, що витік пам’ яті у мові збирання сміття є витоком посилання, а не забутим вилученням — щось ненавмисно зберігає об’ єкт доступним.
- Використовувати слова збережений розмір і домінант під час аналізу дампів купів, оскільки сам по собі невеликий розмір часто вводить у оману щодо того, куди насправді йде пам’ ять.
- Відрізняти справжню витоку (необмежене зростання з часом) від витоку пам’ яті (часте виділення і збирання без чистого зростання) перед тим, як запропонувати виправлення.
- Назвіть типові шаблони витоків — витоки слухачів, захоплення закриття, необмежені кеши, відокремлені вузли DOM — замість того, щоб описувати проблеми з пам’ яттю лише нечітко.
- Пояснити, що паузи GC є особливою причиною затримки, відмінною від логіки програми, коли повільний запит збігається з одним з них, оскільки виправлення (налаштування GC) цілком відрізняється від оптимізації на рівні програми.
На практиці: обговорення питань, пов’язаних з управлінням пам’яттю
Зрозуміти технічний жаргон важливо не тільки для * розуміння * проблеми, але і для ефективного її обговорення. Погляньмо правді в очі – навіть досвідчені розробники можуть спіткнутися, коли намагаються пояснити складну проблему, наприклад, витік пам’яті, комусь, хто менш знайомий з нюансами керованої пам’яті. Фраза має величезне значення. Просте твердження, наприклад, «застосунок витікає з пам’яті» може бути неправильно інтерпретовано як нечітка скарга, тоді як більш точний опис, який використовує словник, який ми будували, негайно прояснює ситуацію і направляє увагу на дії.
Розглянемо такий сценарій: ви переглядаєте запит на звантаження, надісланий колегою, Alex. PR вводить нову функцію, що включає складні перетворення даних в циклі. Під час перегляду ви зауважили, що використання пам’ яті програмою поступово збільшується з часом під час запуску тестового пакета. Ви коментуєте опис PR таким чином: “Alex, я бачу підвищене споживання пам’ яті під час цих тестів. В частности, я наблюдаю устойчивый рост в метрике heap_size. Можеш розслідувати потенційні проблеми в петлі, які можуть спричинити це? Можливо, ми можемо дослідити використання більш ефективної структури даних або оптимізацію логіки ітерацій, щоб зменшити кількість створених і збережених об’єктів. “Ця фраза використовує ключові терміни - “розмір_купи”, “постійне зростання”, “логіка ітерацій” - направляючи Алекса до конкретних областей для дослідження, а не просто заявивши, що є витік. Вона також формує її як можливість спільного вирішення проблем, яка часто більш продуктивна, ніж обвинувальна мова.
Інший приклад може з’ явитися у каналі Slack під час сеансу зневадження. Сара повідомляє: « Програма постійно зазнає аварій з помилкою « Не вистачає пам’ яті ». Корисна відповідь не була б просто « Це витік пам’ яті ». Замість цього розробник міг би сказати: « Добре, спробуйте визначити джерело. Чи можете ви поділитись трасуванням стека? Ми повинні перевірити, чи будь-які об’єкти утримуються довше, ніж це необхідно за допомогою логіки програми - особливо шукаючи довговічні посилання, що запобігають збирання сміття. “Цей підхід фокусується на тому, як розв’язати проблему і запрошує глибший аналіз основної причини, визнаючи, що збирання сміття не завжди миттєве.
Нарешті, під час написання PR- опису, що пояснює виправлення, важливо вказати * чому * зміна була внесена з точки зору керування пам’ яттю. « Цей рефакторинг зменшує кількість тимчасових об’ єктів, створених у межах функції process_data, мінімізуючи тиск на збиральника сміття і покращуючи загальну стабільність програми. » Це демонструє розуміння ширших системних наслідків, ніж просто виправлення вади.
Ось приклад використання valgrind для ілюстрації відстеження пам’ яті:
valgrind --leak-check=full ./my_application
За допомогою цієї команди буде виконано valgrind, потужний інструмент для виявлення помилок пам’ яті, з увімкненим параметром повної перевірки на витік. Після цього у виводі буде підсвічено всі потенційні проблеми, пов’ язані з виділенням місця, яке не було належним чином звільнено, що надає конкретні докази для підтримки діагностичних обговорень.