Pitchfork использует слишком много памяти?

Кто-нибудь ещё это видит? Форум по размеру и трафику довольно скромный. У нас запущено четыре рабочих процесса pitchfork, и похоже, что один из них обрабатывает подавляющее большинство входящих запросов и потребляет больше памяти, чем остальные. Сейчас активно используется swap, и если намеренно перезапустить pitchfork, это заметно снижается. Поэтому я делаю вывод, что в процессах pitchfork сейчас много «холодных» страниц, которые выгружены в swap.

Это после 20 дней работы на машине с 4 ГБ ОЗУ и 4 ГБ swap.

Было бы плохо, если бы swap закончился. Также было бы плохо, если бы весь этот swap начал возвращаться в память, что, возможно, произойдёт, когда pitchfork в конце концов выполнит сборку мусора (garbage collect).

Кто-нибудь ещё наблюдает что-то подобное? Пожалуйста, поделитесь конфигурацией вашего оборудования!

# ps aux | sort -n -k 4 | egrep pitchf\|MEM |tail
root     2167652  0.0  0.0   5912  1792 pts/0    S+   20:07   0:00 grep -E --color=auto pitchf|MEM
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1000       15094  0.0  0.2 497544 10988 ?        Sl   Jul28   0:17 pitchfork monitor - 
1000       15704  0.0  2.5 6799124 97836 ?       Sl   Jul28   1:00 pitchfork (gen:0) service - ready
1000       15097  0.0  4.8 6791252 189724 ?      Sl   Jul28   5:26 pitchfork (gen:0) mold - ready
1000       15959  0.0  8.1 6815508 319708 ?      Sl   Jul28  12:05 pitchfork (gen:0) worker[3] - requests: 6684, waiting
1000       15900  0.0  9.2 6864596 360696 ?      Sl   Jul28  17:43 pitchfork (gen:0) worker[2] - requests: 14756, waiting
1000       15795  0.1 10.3 6884756 405420 ?      Sl   Jul28  48:36 pitchfork (gen:0) worker[1] - requests: 97007, waiting
1000       15734  2.1 12.8 11299708 500120 ?     Sl   Jul28 637:50 pitchfork (gen:0) worker[0] - requests: 2229848, waiting

# free
               total        used        free      shared  buff/cache   available
Mem:         3904968     1874636       98840      678812     1931492     1160916
Swap:        4194288     1226600     2967688


# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 1226600 115820  65288 1866284    1    1    20    38    0    3  3  1 97  0  0
 0  0 1226600 113208  65296 1866296    0    0     0    14  411  478  1  1 98  0  0
 0  0 1226600 112956  65304 1866336    0    0     1    23  438  528  2  1 97  0  0
 0  0 1226600 112704  65308 1866360    0    0     1    31  518  603  5  1 94  0  0
 0  0 1226600 112704  65308 1866364    0    0     0    11  347  387  1  1 98  0  0

Вывод vmstat показывает, что сейчас нет никакого давления на память — отсутствует активность пейджинга. Меня беспокоит не то, что моя установка сейчас работает плохо, а то, что существует опасность.

cpu0

Если серьёзно, тот, кто выполняет всю работу, имеет всего на 100 МБ RSS больше среднего? Мне кажется, это нормально, или я что-то упускаю?

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

Да, различия в использовании RSS относительно невелики, но диапазон от 300 МБ до 500 МБ — это довольно большая разница в процентном отношении.

Ещё более показательным является использование swap. Прежде чем хвататься за вилы, я вижу:

# free
               total        used        free      shared  buff/cache   available
Mem:         3904968     1888140       77308      679004     1939520     1147220
Swap:        4194288     1226344     2967944

а после:

# free
               total        used        free      shared  buff/cache   available
Mem:         3904968     1486412     1422380      640744      996176     1587908
Swap:        4194288      309892     3884396

Похоже, что благодаря пересборке было освобождено 1300 МБ (разница между used и swap).

Я не уверен, что видел такое большое использование swap при работе с unicorn: отсюда и название темы.

Как я уже сказал, мне было бы интересно увидеть цифры с других инстансов.

Это нормальное явление, когда один процесс pitchfork берёт на себя основную нагрузку — другие процессы задействуются только тогда, когда первый занят. Также нормально, что потребление памяти со временем растёт. Хотя в конечном итоге оно должно выйти на плато, как только всё, включая кэши и ruby-JIT, будет «прогрето».

Вот график из одного из наших производственных кластеров за 7-дневный период. Он отслеживает процесс с максимальным потреблением памяти. Зелёные пунктирные линии указывают на деплой (то есть на перезапуск pitchfork с нуля):

Как видно, потребление памяти действительно растёт после первоначального запуска, но затем стабилизируется чуть ниже отметки в 1,4 ГБ. Этот кластер обслуживает сотни сайтов, поэтому, возможно, он не лучший ориентир с точки зрения конкретных цифр… но, надеюсь, визуализация роста окажется полезной.

Смотреть только на значения RSS для каждого процесса — значит не видеть полной картины. Pitchfork — это «форкающий веб-сервер». Он запускает «образцовый» (mold) процесс, а затем все воркеры создаются из него через механизм копирования при записи (copy-on-write). Поэтому, если RSS показывает 500 МБ для worker[0], примерно 200 МБ из них являются общими для образцового процесса и всех остальных воркеров.

В обозримом будущем мы надеемся включить функцию “reforking” в Pitchfork. Она периодически завершает работу воркеров и повторно форкает их из уже прогретого воркера, чтобы со временем они делили как можно больше памяти. Однако для этого нужно убедиться, что весь наш код совместим с таким подходом :crossed_fingers:

Полезная визуализация, спасибо. Я бы не сказал, что всё стабилизировалось, но темп роста не такой высокий, как раньше.

Периодический рефорк звучит как отличная идея для этого — если получится, пожалуйста, отметьте здесь, когда это будет реализовано.

Можете ли вы что-нибудь сказать о зелёных линиях? Меня интересует, когда (если вообще) питфорки выполняют сборку мусора, что это вызывает и каков эффект во время её выполнения.

Зелёные линии — это моменты, когда мы разворачиваем обновления. По сути, это: ./launcher rebuild app.

Ruby (и JS, который мы запускаем внутри процессов Ruby через MiniRacer/v8) постоянно выполняет сборку мусора во время работы и в ответ на сигналы от операционной системы. Поэтому я не думаю, что от какого-либо ручного вмешательства можно получить значительную пользу.

Спасибо. Мне было бы интересно посмотреть, как всё сложится в долгосрочной перспективе — на сервере, который обновляется относительно часто, это будет не так очевидно. В моём случае прошло 20 дней, а потом я решил использовать pitchfork для перезапуска, что дало мне кое-какую информацию, но также обнулило отсчёт.