Заменить память остановленного процесса на файл обмена

Вопрос или проблема

Я хочу переместить резидентные/виртуальные данные процесса, получившего сигнал SIGSTOP, из основной памяти в любое подходящее пространство подкачки. С возможностью восстановить процедуру до сигнала SIGCONT, чтобы продолжить выполнение процесса.

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

Контекст: программа, которая требует для запуска и завершения и используется периодически, использует не только значительное количество времени процессора в бездействии, но также занимает 60-80% оперативной памяти системы. Команды STOP/CONT хорошо работают для прекращения простоя, и даже выдерживают приостановку системы без проблем, но во время остановки оперативная память системы фактически сокращается до 20-40%.

Использование обычного поведения подкачки в Linux a) требует наличия пространства подкачки, которое обычно не используется за пределами этого конкретного сценария и, что более важно, b) является ненадежным с точки зрения когда происходит подкачка чего. Неправильный процесс может быть выгружен или в момент, когда это неудобно. Вместо этого у меня есть SSD, который может более чем достаточно вместить резидентный набор процесса, даже виртуальный набор. И я хочу контролировать, когда или будет ли происходить подкачка.


Возможные подходы.

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

Да, подкачка — это системная вещь 🙂 И, насколько мне известно, вы не можете заставить виртуальную память одного процесса быть выгруженной; приостановленный процесс, однако, будет довольно высоко в списке вещей для выгрузки, поэтому настройка временного пространства подкачки и повышение значения 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 не всегда надежны в части управления, когда и какие процессы будут выгружены, что вызывает необходимость в более управляемом подходе.

Возможные решения

  1. Использование 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
  2. Использование временного файла подкачки

    Если вы находитесь в ситуации, когда 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.

  3. Использование madvise и управление памятью

    Как указано в одном из предложенных решений, можно использовать madvise с флагом MADV_DONTNEED, чтобы попытаться высвободить память. Однако следует помнить, что данный метод имеет ограничения и не всегда может гарантировать желаемый результат по причине особенностей управления памятью в Linux.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...