Вопрос или проблема
Я хочу переместить резидентные/виртуальные данные процесса, получившего сигнал SIGSTOP
, из основной памяти в любое подходящее пространство подкачки. С возможностью восстановить процедуру до сигнала SIGCONT
, чтобы продолжить выполнение процесса.
В системе нет выделенного пространства подкачки, потому что обычно я не хочу, чтобы данные подкачивались. Поэтому предпочтительнее решение, которое записывает в выделенный файл в файловой системе по моему выбору. Возможно, “подкачка” здесь не совсем корректное слово, но если ничего не сработает, можно установить временное пространство подкачки.
Контекст: программа, которая требует для запуска и завершения и используется периодически, использует не только значительное количество времени процессора в бездействии, но также занимает 60-80% оперативной памяти системы. Команды STOP/CONT хорошо работают для прекращения простоя, и даже выдерживают приостановку системы без проблем, но во время остановки оперативная память системы фактически сокращается до 20-40%.
Использование обычного поведения подкачки в Linux a) требует наличия пространства подкачки, которое обычно не используется за пределами этого конкретного сценария и, что более важно, b) является ненадежным с точки зрения когда происходит подкачка чего. Неправильный процесс может быть выгружен или в момент, когда это неудобно. Вместо этого у меня есть SSD, который может более чем достаточно вместить резидентный набор процесса, даже виртуальный набор. И я хочу контролировать, когда или будет ли происходить подкачка.
Возможные подходы.
- Этот ответ на serverfault предлагает madvise, но нет четкого способа отменить процедуру, так как нет аналога
MADV_PAGEOUT
. - Установка конкретного файла в качестве пространства подкачки для процесса, по всей видимости, возможна согласно Иметь приватный файл подкачки на процесс.
В системе нет выделенного пространства подкачки, потому что обычно я не хочу, чтобы данные подкачивались. Поэтому предпочтительнее решение, которое записывает в выделенный файл в файловой системе по моему выбору. Возможно, “подкачка” здесь не совсем корректное слово, но если ничего не сработает, можно установить временное пространство подкачки.
Да, подкачка — это системная вещь 🙂 И, насколько мне известно, вы не можете заставить виртуальную память одного процесса быть выгруженной; приостановленный процесс, однако, будет довольно высоко в списке вещей для выгрузки, поэтому настройка временного пространства подкачки и повышение значения swappiness (sudo sysctl -w vm.swappiness=100
), а затем увеличение давления на память (например, с помощью yes | head -c 1G /tmp/tmpfile
, предполагая, что /tmp — это точка монтирования tmpfs) в наверняка выгрузит процесс.
Но, честно говоря, ваш случай использования звучит на 100% как CRIU, “Контрольная точка / Восстановление в пространстве пользователя”. Это зрелая технология, которая позволяет просто взять состояние программы, сохранить его на носителе и восстановить позже.
Естественно, это требует, чтобы ни одно из других объектов, с которыми взаимодействовала эта программа, не изменилось непредсказуемым образом (например, сетевые соединения могут разорваться в любой момент, однако большинство программ будет устойчивыми к этому, но ни одна программа не ожидает, что их файл базы данных изменится, пока они были “закатаны”).
Существует довольно простое и общее решение для этого, которое также предоставляет несколько дополнительных преимуществ в вашей ситуации: контейнеры.
Дополнительные преимущества будут заключаться в том, что вы сможете легко ограничить процент времени использования процессора, который может занимать программа, объем оперативной памяти и скорости ввода-вывода на диск и т.д.; среды выполнения контейнеров обычно помещают свои контейнеры в области cgroup, которые позволяют вам указывать такие ограничения.
Я использую podman
для контейнеров; podman
имеет встроенные функцию сохранения/восстановления на основе CRIU.
# запуск в фоновом режиме
podman run -d --name resourcehog debian:12 sh -c 'apt update; apt install -y stress -c8'
# сохранить состояние на диск, остановить выполнение
podman container checkpoint --create-image resourcehog-frozen-as-hell resourcehog
# позже, восстановить
podman container restore --name resourcehog-continuation resourcehog-frozen-as-hell
Вместо --create-image
вы также можете --export
в файл tar.gz (по моему опыту, это будет медленнее при экспорте), а затем --import
тот же файл при восстановлении.
Ответ или решение
Перемещение памяти остановленного процесса в файл подкачки: подробное руководство
В данной статье мы рассмотрим, как переместить память остановленного процесса в файл на диске, что может быть полезно для управления ресурсами системы. Этот процесс особенно актуален для приложений, которые занимают значительное количество оперативной памяти в режиме простоя, но не требуют активного использования CPU.
Проблема
Вы намерены переместить данные резидентной/виртуальной памяти SIGSTOP-процесса из основной памяти в файл подкачки на диске. Система по умолчанию не имеет выделенного пространства для подкачки, так как в большинстве случаев вы не хотите, чтобы процессы были выгружены из памяти. Поэтому предпочтительно использовать файл системы, который вы выберете, в качестве замены для файла подкачки. Стандартные механизмы подкачки Linux не всегда надежны в части управления, когда и какие процессы будут выгружены, что вызывает необходимость в более управляемом подходе.
Возможные решения
-
Использование CRIU (Checkpoint/Restore in Userspace)
CRIU позволяет сохранять состояние процесса на диск и восстанавливать его позднее. Это решение полностью соответствует вашим потребностям. При помощи CRIU вы можете не только сохраните состояние, но и управлять им без преждевременной выгрузки. Основным преимуществом CRIU является ону возможность работать с состоянием процесса без необходимости готовить уникальные настройки подкачки.
Пример использования CRIU вместе с контейнерами (например, Podman):
# Запуск процесса в фоновом режиме podman run -d --name resourcehog debian:12 sh -c 'apt update; apt install -y stress -c8' # Сохранение состояния и остановка процесса podman container checkpoint --create-image resourcehog-frozen-as-hell resourcehog # Позднее восстановить состояние podman container restore --name resourcehog-continuation resourcehog-frozen-as-hell
-
Использование временного файла подкачки
Если вы находитесь в ситуации, когда CRIU не может быть использован, вы можете создать временное пространство для подкачки. Для этого необходимо:
-
Создать файл в файловой системе:
dd if=/dev/zero of=/tmp/swapfile bs=1M count=1024 chmod 600 /tmp/swapfile mkswap /tmp/swapfile
-
Активировать файл подкачки:
swapon /tmp/swapfile
-
Настройка параметров подкачки:
sudo sysctl -w vm.swappiness=100
-
Увеличение нагрузки на память для вызова выгрузки:
yes | head -c 1G > /tmp/tmpfile
Данный подход заставит Linux подкачивать процессы, находящиеся в состоянии SIGSTOP.
-
-
Использование
madvise
и управление памятьюКак указано в одном из предложенных решений, можно использовать
madvise
с флагомMADV_DONTNEED
, чтобы попытаться высвободить память. Однако следует помнить, что данный метод имеет ограничения и не всегда может гарантировать желаемый результат по причине особенностей управления памятью в Linux.
Заключение
Данный подход обеспечивает гибкость в управлении памятью и минимизацию использования ресурсов для неактивных процессов. Использование CRIU и контейнеров предоставляет надежный способ сохранения и восстановления состояния процессов, в то время как организация временного файла подкачки — более ручное, но полезное решение в определенных ситуациях. Определив оптимальный метод для вашей среды, вы сможете значительно улучшить производительность вашей системы.