Застосунок, що з'їдав 41 МБ на секунду, зупинено
Зупинила застосунок, що заповнював пам'ять зі швидкістю 41 МБ за секунду — зафіксовані 111 ГБ стиснених сторінок на машині з 36 ГБ, — обмеживши кожен потік подій, запровадивши підписку за типом події та ліміт частоти журналювання, що скоротило 610 996 рядків журналу до 1 411.
Роботу виконано: вересень 2026

Фото: TobiasD / Pixabay 
Фото: ronymichaud / Pixabay
41 MB на секунду зростання пам'яті — зупинено
Ситуація. Застосунок заповнював пам’ять, доки операційна система примусово його не завершувала. Під час зафіксованого інциденту обсяг стиснутих сторінок сягнув 111 ГБ на машині з 36 ГБ і зростав приблизно на 41 МБ за секунду, а файл журналу за один короткий сеанс містив 610 996 рядків. Машина в такому стані не просто повільна — нею неможливо користуватися: примусове завершення настає вже після того, як через підкачування решта програм на робочому столі перестала відповідати.
Завдання. Причину зростання треба було знайти, а не вгадувати, і для кожного необмеженого шляху задати межу, бо одна обмежена черга поруч із трьома необмеженими — це не виправлення.
Дія. Причин було три, і вони множили одна одну — саме тому все відбувалося так швидко. Потік подій із ядра споживався без жодних обмежень, тож події надходили швидше, ніж інтерфейс встигав їх застосовувати, і необроблені події накопичувалися, а не відкидалися. Кожен підписник отримував кожну подію й фільтрував її вже після отримання, тож вартість однієї події множилася на кількість слухачів, а фільтрування в кожному слухачі виділяло пам’ять. А журналювання не мало жодного ліміту, тож кожна подія породжувала рядки журналу, — саме цей чинник і давав лавиноподібний ефект, бо обсяг журналювання зростав пропорційно до масштабу самої проблеми. Виправлення стосувалося всіх трьох причин: обмежені буфери з явно визначеною поведінкою на випадок заповнення; підписка за типом події, щоб слухач прокидався лише для потрібних йому подій; і ліміт частоти журналювання, який згортає повтори, а не записує кожен. Регресійний тест генерує події з високою частотою й перевіряє, що споживання пам’яті не перевищує верхньої межі, тож обмеження — це властивість збірки, а не коментар.
Результат. Під тривалим навантаженням споживання пам’яті лишається на одному рівні, а той самий сеанс, що давав 610 996 рядків журналу, тепер дає 1 411. Чесно варто зазначити, що ліміт частоти журналювання відкидає інформацію: коли тепер щось швидко йде не так, запис про це навмисно неповний, і це свідомий компроміс, бо альтернатива — машина, яка зупиняється.
Попередня робота: Побудувала нативний клієнт для macOS на Swift 6. Читати далі: Перейшла на сувору паралельність Swift 6 поверх C. Або перегляньте повне портфоліо.
Клієнтам ми розповідаємо це як Застосунок, що з'їдав 41 МБ на секунду, зупинено — подивитися разом з іншими кейсами.
Одна частина довшого переліку — і він увесь на цьому сайті.
Кожен запис написано однаково: ситуація, завдання, що ми зробили і що змінилося.

