Я пытаюсь установить жесткое ограничение на использование ЦП для команды dd. Я создал следующий файл модуля
[Unit]
Description=Virtual Distributed Ethernet
[Service]
ExecStart=/usr/bin/ddcommand
CPUQuota=10%
[Install]
WantedBy=multi-user.target
которые вызывают следующий простой скрипт
#!/bin/sh
dd if=/dev/zero of=/dev/null bs=1024k
Как я видел в этом руководстве, использование ЦП для моего dd
обслуживание не должно превышать 10%. Но когда я запускаю system-cgtop
команда использование составляет около 70-75%.
Есть идеи, что я делаю не так и как это исправить?
Когда я выполняю systemctl show dd
Я получаю следующие результаты относительно процессора
CPUShares=18446744073709551615
StartupCPUShares=18446744073709551615
CPUQuotaPerSecUSec=100ms
LimitCPU=18446744073709551615
Ваше решение правильное и действительно должно быть перспективным; используя systemd для управления настройками cgroup служб, например. CPUQota.
[Unit]
Description=Virtual Distributed Ethernet
[Service]
ExecStart=/usr/bin/ddcommand
CPUQuota=10%
[Install]
WantedBy=multi-user.target
Увидеть man systemd.resource-control
для получения более полезных настроек cgroup в systemd.
Однако есть два предостережения, которые я (и, возможно, несколько других) наткнулся на. Эти предостережения действительно трудно отследить, поскольку, похоже, не так много легко найти информацию об этом, что является основной причиной этого ответа.
В CPUQuota
настройка доступна только с systemd 213, см. https://github.com/systemd/systemd/blob/master/NEWS
* The CFS CPU quota cgroup attribute is now exposed for
services. The new CPUQuota= switch has been added for this
which takes a percentage value. Setting this will have the
result that a service may never get more CPU time than the
specified percentage, even if the machine is otherwise idle.
Это, например, проблема с Дебиан Джесси который поставляется только с systemd 208. В качестве альтернативы можно настроить cpu.cfs_period_us
и cpu.cfs_quota_us
вручную с помощью cgcreate
и cgset
из cgroup-bin пакет, например.
sudo cgcreate -g cpu:/cpulimited
sudo cgset -r cpu.cfs_period_us=50000 cpulimited
sudo cgset -r cpu.cfs_quota_us=10000 cpulimited
sudo cgexec -g cpu:cpulimited /usr/bin/ddcommand
Для настроек cpu.cfs_period_us
и cpu.cfs_quota_us
чтобы быть доступным, ядро должно быть скомпилировано с флагом конфигурации CONFIG_CFS_BANDWIDTH
. К сожалению, ядро 3.16.x для Дебиан Джесси не компилируется с этим флагом по умолчанию, см. это запрос функции.
Это будет доступно в Debian Stretch хотя. Также можно было использовать ядро из Джесси-Backports, у которого должен быть установлен флаг.
Надеюсь, этот ответ поможет нескольким людям с той же проблемой, что и я ...
PS: Простой способ проверить, работает ли квота ЦП в вашей среде:
$ apt-get install stress
$ systemd-run -p CPUQuota=25% --slice=stress -- stress -c <your cpu count>
и смотреть с top
или htop
нагрузка должна быть распределена (равномерно) по всем процессорам / ядрам, в сумме до 25%.
В качестве альтернативного инструмента можно использовать cpu-limit, который должен быть доступен в большинстве дистрибутивов, например.
$ apt-get install cpulimit
$ cpulimit -l 10 -P /usr/bin/ddcommand
Работает отправкой SIGSTOP
и SIGCONT
к прикрепленной команде, чтобы приостановить и возобновить ее работу.
AFAIK было сложно одновременно управлять несколькими отдельными / автономными процессами, например сгруппируйте их вместе, но для этого также может быть решение ...
У меня была аналогичная задача по ограничению использования ЦП, но вариант использования был совершенно другим. Он должен был нагружать набор регрессионных тестов на локальной машине, чтобы имитировать то, что он проходит на загруженном CI-сервере (что вызывает недетерминированное или нестабильное поведение тестов). Это сработало как шарм, в отличие от cpulimit
и stress
.
systemd-run -p CPUQuota="25%" --scope --uid=$USER --gid=$USER -- pytest ...
--scope
заставил его наследовать текущую среду оболочки и вывод команды на стандартный вывод, как обычно. Единственная разница в производительности была Запуск области как единицы run-uN.scope как первая строка.
Для запуска требуются права root, и у меня есть приглашение графического интерфейса от pkttyagent
. Вводить пароль каждый раз может быть неудобно, если вам нужно запускать команду несколько раз подряд, например, чтобы настроить CPUQuota
, поэтому добавив к указанной выше команде префикса sudo -E env PATH=$PATH
упростил бы задачу.
На всякий случай, потому что есть сообщения, что он не работал / не поддерживался в старых версиях.
$ uname -r
4.15.0-51-generic
$ systemd --version | head -n 1
systemd 229