Форму видно без профайлера. Сайт отвечает, за день один процесс растёт, сервер его убивает, кто-то поднимает заново, снова тихо, рост начинается сначала. Вместе с инцидентом приезжает предложение купить память или переписать тот сервис, который как раз был запущен. Оба тратят деньги до того, как названо действие, которое память не отпускает.

Я гонялся за этим на долгоживущих процессах, рядом с медленными запросами, и это не одна находка. Запрос может тормозить и память отдавать. Процесс может быть быстрым и всё равно оставлять себе по чуть-чуть после каждой задачи, пока коробка не кончится. Память покупать разумно, когда процесс возвращается к обычному размеру, а то, что осталось, — честная работа. Это отсрочка, когда сайт сейчас держится на рестарте.

1. Три факта, которые схлопнули в «надо больше RAM»

Имя процесса. Рестарт ли вернул сайт. Сколько длилась тишина. Разведите их. Процесс, который час растёт и потом убит, — не тот же инцидент, что один тяжёлый запрос, который пришёл и ушёл. Рестарт, после которого тихо до обеда, — это набор. Рестарт, после которого ничего не меняется, — другой баг, и память его тоже не объяснит.

Пишите процесс, не «сервер». PHP-запрос, который умирает в конце работы, память обычно отдаёт, поэтому симптом прячется в том, что живёт дальше: процесс очереди, процесс на Node, планировщик, всё, что запустили и забыли. Не знаете, в кого стреляет убийца, — соберётесь купить память на всю машину из-за одного невоспитанного жильца. Смотреть надо на копии. На боевом сайте вы узнаете размер в момент, когда процесс уже мёртв, и узнаете это при клиентах. Копии с правдоподобным объёмом хватает. Пустая база прячет и тяжёлое чтение, и утечку: держать нечего. Единственная живая копия — прод: скажите это вслух и снимите восстановление до эксперимента. Эксперимент — не покупка.

2. Одно действие двадцать раз, и три размера

Возьмите одно действие. Экран, которым пользуются, или одну задачу воркера. Размер до, прогон, пик, размер снова, когда действие кончилось и процесс стоит. Повторите двадцать раз. Вам нужна ступенька, не график, которым можно впечатлить.

Размер вырос на время действия и спустился, когда действие кончилось: действие тяжёлое. Оно держало большой набор и отпустило. Это всё ещё может быть проблемой и причиной, почему один запрос умирает, но это не утечка. Чинка — перестать держать весь набор: чтение уже, поток, лимит. Больше памяти даст большему набору пройти один раз и оставит форму на месте. Размер шагнул вверх и остался после того, как работа кончилась: что-то это держит. Двадцать повторов делают лестницу очевидной. Кеш, который только вставляет. Список на процессе, который дописывает и никогда не выкидывает. Клиент, буфер или строка лога, которые остались на долгоживущем объекте. Рестарт «чинит» это тем, что выбрасывает лестницу. Двадцать первый повтор строит первую ступеньку заново.

Неделя метрик для этого не нужна. Нужны база, пик и «после» на одном действии, повторённом. Размер гуляет без связи с действием — вы взяли не то действие или не тот процесс. Это находка. Поправьте имя в заметке. Не усредняйте это в рекомендацию купить железо.

3. Где лестница обычно живёт

Обычный PHP-запрос плохо подходит для ночной утечки: запрос кончился, память ушла с ним. Сначала процессы, которые переживают запрос, потом день на одном контроллере. Воркеры очереди и процессы на Node — обычные жильцы. Их же ставят, когда пытаются сделать медленный клик «быстрым на ощупь», и так лестница появляется рядом с починкой.

Запрос всё ещё может быть тяжёлым действием. Классика — цикл, который затягивает строки в процесс, по запросу на строку или одним огромным списком, и держит их, пока не собран ответ. Это видно и во времени, и в размере. Читайте это сначала как проблему запроса. Как группировать slow log и почему цикл легко недосчитать: slow log до того, как резать сервис. Не пересказывайте эту работу как покупку памяти. Если после ответа размер вернулся, утечки нет. Есть чтение, которое держит слишком много, и следующий инструмент — лог.

Размер не вернулся — оставайтесь на долгоживущем процессе. Воркер, который кладёт результат «на следующий раз» в словарь без потолка, выглядит здоровым на двадцатом запросе и мёртвым на двадцатитысячном. Процесс на Node, который тащит буфер, сокет или растущий массив через задачи, делает то же. Когда работу вообще стоит уводить из запроса и когда повтор не должен повторить побочный эффект — отдельное решение, оно в заметке когда процесс на Node стоит рядом с Laravel. Очередь не прощает словарь, который ничего не забывает. Она даёт ему процесс, в котором жить.

4. Чего лишняя память не покупает

Она не называет действие. Она отодвигает убийство. На тихом продукте это неделю выглядит как лекарство, пока лестница не упрётся в новый потолок. На более живом — до завтрашнего вечера. В обоих случаях вы поменяли часы, не ступеньку.

Она не оправдывает переписывание сервиса. Лестница часто — маленькое удержание в процессе, который вы как раз хотели оставить: кеш, клиент, которого открывают на задачу и не закрывают, массив, в который дописывают ради отчёта, который никто не читает. Новый сервис, который копирует эти объекты, копирует лестницу. Режьте сервис, когда причина — граница выкладки. Не потому, что процесс умер, а имя в юнит-файле было неловким. И она не заменяет копию. Добавить память на боевой машине и смотреть на клиентов, пока гадаете, — способ встретить следующее убийство посреди гадания. Снимите восстановление. Повторите действие. Запишите три числа. Потом решайте, больше ли оставшийся размер, после того как процесс отдал что мог, чем машине стоит держать. Только этот остаток — честный аргумент за коробку побольше.

5. Порядок на следующий раз, когда «лечит» рестарт

Назовите процесс, в который стреляют. Подтвердите, что сайт вернул именно рестарт, и запишите, сколько длилась тишина. Поднимите копию с живыми строками. Возьмите одно действие. Размер до, пик и после, двадцать раз. Спадает — это тяжёлое чтение, идите в запросы. Шагает и остаётся — ищите объект, который переживает действие: кеш без потолка, клиент на каждую задачу, массив, который только растёт. Почините. Те же двадцать замерьте снова. И только потом говорите о размере машины.

Заметку держите рядом с инцидентом, словами, по которым дежурный пройдёт ночью. «Перезапусти» превращает это в ритуал. Три числа превращают это в изменение. Если действие — экран, на котором человек ждёт, экрану всё ещё нужны свои секунды. Память, которая возвращается, может быть медленным ответом. Это две строки одной заметки, не одна покупка.

Когда звать второй взгляд

Назвать процесс и прогнать двадцать повторов можно без второго человека. Зовите, когда размер остаётся и не видно, кто держит, когда лестница сидит в воркере, который страшно рестартить, потому что он же шлёт почту или списывает деньги, или когда единственная среда — прод, а копии ещё нет.

Такую работу я беру: понять, отдаёт ли процесс память, на системе, которая у вас уже крутится, и поменять удержание до того, как кто-то изменит размер коробки. Услуги — такая работа со скоростью на проде. Проекты держат результат рядом с операцией, а не раздувают один инцидент в рассказ про всю платформу. Если нужен второй взгляд, напишите в LinkedIn имя процесса, действие, которое повторяли, и вернулся ли размер вниз. Пароли оставьте у себя.