Espalhe VMs do VirtualBox sobre núcleos

2

Estou usando muitas VMs do VirtualBox com sistema operacional diferente em um host do Ubuntu Linux para desenvolvimento. Às vezes, meus scripts ficam errados e começam a carregar 100% da CPU da VM. E quando uma VM carrega 100% cpu eu não consigo nem usar o sistema host - é lento!

Então eu tenho que abrir o topo (muito lentamente), ver que o processo do VirtualBox está usando 240% da CPU, abra todas as janelas da VM até encontrar a VM que carrega o processo de cpu e kill. Eu não quero matar todo o processo do VirtualBox que está usando muito cpu.

Todas as minhas VMs estão configuradas para usar apenas um núcleo de CPU, com limite de execução de 100%. Meu cpu é o AMD FX 8370 (8 núcleos, 16 threads), meu host é executado em SSD raid 10 com sistemas de arquivos alinhados corretamente. Eu estou no ambiente host do windows? Claro que não! Então, por que sinto lentidão?

Talvez porque todas as VMs do VirtualBox recebam somente o primeiro núcleo atribuído (como as janelas costumam fazer)? Como verificar isso e como fazer com que cada VM use cada núcleo? Talvez alguns outros palpites?

Talvez essa questão seja apenas: Como atribuir qualquer aplicativo a um núcleo específico no Linux?

    
por POMATu 01.10.2015 / 11:59

2 respostas

2

Eu não tenho uma resposta para sua pergunta, mas pelo menos posso aliviar sua dor.

Se você iniciar cada VM a partir da linha de comando, por exemplo, como

VBoxManage startvm Name_of_VM --type headless

o comando top com a opção -c exibirá também o comando completo que iniciou o processo. Desta forma, você pode identificar imediatamente o processo culpado, e matá-lo com a opção k dentro do próprio top (você terá que fornecer o número do processo que você quer matar, que você acabou de identificar).

O bom é , isso funciona mesmo se você iniciar todas as suas VMs a partir da GUI, não da CLI.

EDITAR:

Pensando bem, talvez eu saiba a resposta para sua pergunta. Eu não tenho certeza se isso é realmente o que você está procurando, neste caso pls apenas me diga isso.

O utilitário Linux para confinar a execução de um processo a um núcleo pré-especificado é taskset . Você deve tê-lo por padrão, se não verificar o pacote util-linux . Você pode exibir o processo afinidade ( isto é, , a lista de CPUs em que é permitido executar) por meio de

      taskset -cp Process_ID

(o sinal p especifica que o que segue é um número de processo, o c sinalizador substitui uma cadeia de caracteres pela representação hexadecimal dos núcleos da CPU que seria o padrão).

Você pode atribuir um processo já em execução para ser executado apenas nos núcleos 0 e 1, por exemplo, por meio de

     taskset -cp 0,1 Process_ID

ou inicie um novo programa no núcleo 0 somente por meio de:

      taskset -c 0 VBoxManage startvm Name_of_VM --type headless

Duas ressalvas: primeiro, o fato de você ter confinado o processo para rodar em uma única CPU não significa que será o único processo em execução: todos os processos cuja afinidade inclui essa CPU serão executados, por alguma fração da CPU. tempo, sobre ele. Se você quiser reservar uma determinada CPU para o uso exclusivo de um processo que você define com taskset , você terá que usar o parâmetro isolcpus que Isola a CPU dada pelo agendador do kernel . Basta adicionar o parâmetro isolcpus = [cpu_number] à linha de comando do kernel do Linux para o gerenciador de inicialização.

Além disso, você deve ser avisado que limitar um processo a uma única CPU não precisa ser o total solution que você parece pensar. As CPUs usam periféricos de qualquer tipo e, sob certas circunstâncias, podem ficar paralisados porque o periférico em questão fica indisponível, o que faz com que a CPU faça um loop em suas solicitações, e o barramento e talvez o periférico ficam sobrecarregados com as solicitações. Um exemplo? Eu uso o controlador Sonos em execução no Wine; quando eu ativo uma VPN, ela se desconecta de sua base na Califórnia e continua inundando meu sistema com solicitações de rede. Isso não tem nada a ver com o confinamento de uma única CPU.

    
por 01.10.2015 / 12:28
0

Com a ajuda da resposta da MariusMatutiae, finalmente consegui escrever o script "spreader" que espalha todas as VMs do virtualbox lançadas para diferentes núcleos. Além disso, também faz o mesmo com VMs VMware.

Para usar este script, todas as suas VMs devem ter um único núcleo (que pode ser definido nas configurações). Caso contrário, você pode excluí-los, modificando o greex regexp.

#!/bin/bash

#getting possible affinity lists
AFFINITY=($(taskset -cp 1 | sed 's/.*\([0-9]\)\+[-]\([0-9]\+\).*/ /'))

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

Se você quiser fazer com que funcione somente com VMs VirutalBox, remova [V]irtualBox.*comment\| do padrão grep. Se você quiser que funcione apenas com VMs VMware, remova \|.*[.]vm[x] do padrão grep.

Logo após a aplicação deste script, você pode ver alguns atrasos em todas as VMs por vários segundos. Então tudo fica bom e funciona como esperado.

Agora, as VMs não podem comer meu cpu, mesmo quando estão sobrecarregadas, e o firefox fica feliz em comer tudo. Mas isso é outra história ...: /

    
por 03.10.2015 / 23:24