
Я использую много виртуальных машин VirtualBox с разными ОС на одном хосте Ubuntu Linux для разработки. Иногда мои скрипты ошибаются и начинают загружать 100% процессора виртуальной машины. А когда одна виртуальная машина загружает 100% процессора, я даже не могу использовать хост-систему - она медленная!
Затем мне нужно открыть top (очень медленно), увидеть, что процесс VirtualBox использует 240% CPU, затем открыть каждое окно VM, пока не найду VM, которая загружает CPU, и завершить процесс. Я не хочу завершать весь процесс VirtualBox, который использует много CPU.
Все мои виртуальные машины настроены на использование только одного ядра процессора с ограничением выполнения 100%. Мой процессор — AMD FX 8370 (8 ядер, 16 потоков), мой хост работает на SSD raid 10 с правильно выровненными файловыми системами. Я в среде хоста Windows? Конечно, нет! Так почему же я испытываю замедление?
Может быть, потому что все VirtualBox VM получают только первое ядро (как обычно делает Windows)? Как это проверить и как заставить каждую VM использовать каждое ядро? Может быть, есть еще какие-то догадки?
Может быть, этот вопрос звучит так: как назначить любое приложение определенному ядру в Linux?
решение1
У меня нет ответа на ваш вопрос, но, по крайней мере, я могу облегчить вашу боль.
Если вы запускаете каждую виртуальную машину из командной строки, например, так:
VBoxManage startvm Name_of_VM --type headless
то верхняя команда с опцией -c
отобразит также полную команду, которая запустила процесс. Таким образом, вы можете немедленно определить виновный процесс и убить его с опцией k
внутри top
нее (вам придется указать номер процесса, который вы хотите убить, который вы только что идентифицировали).
Хорошая вещь, это то, что, это работает, даже если вы запускаете все свои виртуальные машины из графического интерфейса, а не из CLI.
РЕДАКТИРОВАТЬ:
Если подумать, возможно, я знаю ответ на ваш вопрос. Я не уверен, что это действительно то, что вы ищете, в таком случае, пожалуйста, просто скажите мне об этом.
Утилита Linux для ограничения выполнения процесса на заранее указанное ядро — taskset
. Она должна быть у вас по умолчанию, если нет, проверьте пакет util-linux
. Вы можете отобразить процесссродство(то есть, список процессоров, на которых разрешено работать) с помощью
taskset -cp Process_ID
( p
флаг указывает, что далее следует номер процесса, флаг c
заменяет строку символов на шестнадцатеричное представление ядер ЦП, которое будет использоваться по умолчанию).
Вы можете назначить уже запущенный процесс для выполнения только на ядрах 0 и 1, например, с помощью
taskset -cp 0,1 Process_ID
или запустить новую программу только на ядре 0 с помощью:
taskset -c 0 VBoxManage startvm Name_of_VM --type headless
Два предостережения: во-первых, тот факт, что вы ограничили процесс запуском на одном ЦП, не означает, что это будет единственный процесс, запущенный на нем: все процессы, аффинитет которых включает этот ЦП, будут работать на нем в течение некоторой доли времени. Если вы хотите зарезервировать данный ЦП для исключительного использования процессом, который вы установили с помощью taskset
, вам придется использовать параметр isolcpus
, которыйизолирует данный ЦП от планировщика ядра. Просто добавьте параметр isolcpus=[cpu_number] в командную строку ядра Linux для загрузчика.
Также следует уведомить вас, что ограничение процесса одним ЦП не обязательно должно быть тем, total solution
о чем вы, кажется, думаете. ЦП используют периферийные устройства любого типа, и при определенных обстоятельствах они могут зависнуть, поскольку рассматриваемое периферийное устройство становится недоступным, что приводит к тому, что ЦП зацикливается на своих запросах, а шина и, возможно, также периферийное устройство перегружаются запросами. Пример? Я использую контроллер Sonos, работающий под управлением Wine; когда я активирую VPN, он отключается от своей домашней базы в Калифорнии и продолжает загружать мою систему сетевыми запросами. Это не имеет ничего общего с ограничением одним ЦП.
решение2
С помощью ответа MariusMatutiae мне наконец удалось написать скрипт "spreader", который распределяет все запущенные виртуальные машины virtualbox по разным ядрам. Более того, он делает то же самое с виртуальными машинами VMware.
Для использования этого скрипта все ваши виртуальные машины должны быть одноядерными (это можно задать в настройках). В противном случае вы можете исключить их, изменив grep regexp.
#!/bin/bash
#getting possible affinity lists
AFFINITY=($(taskset -cp 1 | sed 's/.*\([0-9]\)\+[-]\([0-9]\+\).*/\1 \2/'))
echo Detected min_cpu: ${AFFINITY[0]}, max_cpu: ${AFFINITY[1]}.
CURRENT_AFFINITY=${AFFINITY[1]};
ps -Af | grep -i "[V]irtualBox.*comment\|.*[.]vm[x]" | awk -F" " '{ print $2}' |
# Iterating backwards because I think that farther cpus are less loaded. Maybe I am wrong
while read pid
do
echo Setting $pid to cpu $CURRENT_AFFINITY
taskset -cp $CURRENT_AFFINITY $pid
#loop stuff
let CURRENT_AFFINITY=CURRENT_AFFINITY-1;
if [[ "$CURRENT_AFFINITY" -lt ${AFFINITY[0]} ]];
then
CURRENT_AFFINITY=${AFFINITY[1]};
fi
done
Если вы хотите, чтобы это работало только с виртуальными машинами VirutalBox, то удалите [V]irtualBox.*comment\|
из шаблона grep. Если вы хотите, чтобы это работало только с виртуальными машинами VMware, то удалите \|.*[.]vm[x]
из шаблона grep.
Сразу после применения этого скрипта вы можете увидеть некоторые задержки во всех виртуальных машинах в течение нескольких секунд. Затем все становится хорошо и работает так, как и ожидалось.
Теперь виртуалки не могут съесть мой процессор даже при перегрузке, а Firefox с удовольствием съедает его весь. Но это уже другая история... :/