vCPU vs. CPU física: o que muda na performance da sua VM

Diagrama de um núcleo de CPU física compartilhado entre várias vCPUs de diferentes máquinas virtuais

    Você aloca 4 vCPUs para sua VM. O benchmark não bate com o que você via em um servidor dedicado com 4 núcleos físicos. Isso não é bug de configuração.

    É a distância entre o que a vCPU promete e o que ela de fato entrega, sempre que o hipervisor divide o mesmo core entre múltiplos inquilinos. Esse artigo mostra onde essa distância aparece na prática: contenção de scheduler, steal time, e os cenários em que o gap importa.

    O que é uma vCPU, tecnicamente

    A abstração por trás do número

    Uma vCPU é uma abstração de software gerenciada pelo hipervisor (KVM, Xen, VMware ESXi). Na prática da nuvem moderna, uma vCPU geralmente corresponde a uma thread lógica de um núcleo físico (via Hyper-Threading ou SMT), e não a um núcleo dedicado inteiro.

    O scheduler do hipervisor agenda o tempo de execução dessa vCPU em cima das threads do hardware real, onde ela compete por ciclos de processamento e cache com as vCPUs de outras VMs do mesmo host. Rode sua aplicação no core da internet brasileira e você ainda está sujeita a essa mecânica.

    A proporção varia por provedor

    A proporção entre vCPUs e cores físicos varia por provedor e hipervisor. Alguns mapeiam uma vCPU para uma thread de hyper-threading; outros usam razões de overcommit de 2:1 ou 3:1 para cargas mistas. Nenhuma proporção é universal.

    Assumir 1 vCPU = 1 core físico é o erro de dimensionamento mais comum em quem migra de bare metal para cloud, e costuma aparecer só quando o tráfego aumenta e a latência fica inconsistente, sem nenhuma mudança de código.

    CPU física: sem camada intermediária

    CPU física é o núcleo real do processador. Sem scheduler de hipervisor decidindo quando sua thread roda: o sistema operacional agenda diretamente no hardware.

    Esse ganho de previsibilidade some quando a distância física até o servidor cresce. Por isso baixa latência de rede e baixo steal time resolvem problemas diferentes, mas se somam no resultado final que o usuário percebe.

    Onde a diferença aparece: steal time

    O que a métrica mede

    Steal time mede o percentual de tempo em que sua vCPU está pronta para executar, mas o hipervisor está ocupado rodando outra VM no mesmo core. Você pediu processamento e não recebeu.

    Em CPU física, steal time é zero por definição: não existe compartilhamento de núcleo, então não existe hipervisor decidindo prioridade.

    Números de referência

    %st acima de 10% por período sustentado (cerca de 20 minutos) indica contenção de host:

    • VPS levemente carregado: steal time costuma ficar em 0-2%.
    • Host sobrecarregado em pico: 10-30% não é incomum, o que significa que sua aplicação recebe apenas 70-90% da CPU que acredita estar rodando.

    O impacto varia por tipo de carga

    Em APIs e bancos de dados, steal time soma direto ao tempo de resposta: uma query de 10ms com 15% de steal passa a levar 11,5ms. Em batch jobs e processamento assíncrono, o mesmo steal time importa muito menos, porque o SLA ali é de throughput total, não de latência por requisição.

    Gastar em CPU dedicada para eliminar steal time de uma fila noturna raramente compensa; para uma API de checkout, costuma se pagar rápido.

    Ruído de vizinho: o que a pesquisa mostra

    O fenômeno e o estudo

    Noisy neighbor é quando outro tenant no mesmo host consome recursos de forma agressiva e degrada sua performance, mesmo com quotas de CPU configuradas no orquestrador.

    Um estudo de pesquisadores da UFES, UFC, UFMG, USP e Universidade do Minho, aceito para publicação na IEEE ICC 2026, quantificou esse efeito em um cluster Kubernetes controlado. Sob ruído combinado de CPU, memória, disco e rede:

    • O tenant limitado a CPU sofreu queda de 56,37% no uso de CPU efetivo.
    • O tenant limitado a disco perdeu 67,58% de performance de I/O.
    • A variação entre rodadas ficou abaixo de 5%, indicando degradação arquitetural determinística.

    Análise de causalidade de Granger confirmou influência unidirecional do tenant agressivo sobre as vítimas em 10 de 10 rodadas, com p-valor médio de 0,003. ResourceQuotas bem configuradas no Kubernetes não isolam hardware: contenção em cache de CPU ou controlador de memória escapa do orquestrador.

    O efeito colateral entre recursos

    Contenção em um recurso vaza para outro. Sob estresse de memória, o tenant limitado a CPU registrou aumento de 13,49% em I/O de disco, mesmo sem carga adicional de disco configurada. Sob ruído combinado, esse aumento chegou a 20,01%.

    Isso ocorre porque a falta de memória força o kernel a despejar páginas do page cache agressivamente ou a recorrer ao swap, multiplicando as leituras e escritas no disco. Quando a CPU é throttled, o processamento também se acumula em fila, e parte dela se manifesta como I/O em espera. Na prática: um pico inexplicável de I/O na sua VM pode ter origem em contenção de memória ou CPU em outro tenant, não em um gargalo real na sua camada de armazenamento.

    Assinaturas de degradação por recurso

    • Contenção de CPU desloca toda a curva de performance para baixo, de forma uniforme.
    • Contenção de disco tem outro padrão: os percentis baixos ficam estáveis, mas a cauda achata, com o percentil 95 de throughput caindo até 65% enquanto a mediana cai bem menos.

    A disputa por disco penaliza sobretudo picos, não a operação típica, o que torna esse gargalo mais difícil de perceber olhando só a média.

    O custo prático em provisionamento

    Os autores traduziram isso em recomendação de capacidade: workloads de CPU coexistindo com vizinhos de alto consumo pedem de 2 a 2,5 vezes mais provisionamento para manter o SLA original. Não é exagero de segurança, é o custo real de operar em multi-tenant sem isolamento de hardware garantido.

    Quando o gap importa de verdade

    Cargas latency-sensitive

    APIs, bancos transacionais, trading: steal time se traduz direto em p99 de latência. SLA sob 20ms com contenção intermitente de 10-15% já pode violar o contrato. Vale considerar CPU dedicada ou vCPU fixada (pinned).

    Cargas de throughput

    Batch, filas, workers: toleram melhor a variação, porque o que importa é o total processado, não a latência por unidade.

    Web servers com tráfego intermitente

    Se beneficiam da flexibilidade da vCPU, já que o scheduler realoca núcleos conforme picos de acesso. Se você está decidindo entre tipos de servidor virtual, mapeie primeiro se o tráfego é constante ou intermitente.

    Ambientes de dev e homologação

    Raramente exigem performance constante, então overcommit de vCPU é desejável para reduzir custo. Mais vCPUs significam mais “cérebros” trabalhando pelo mesmo objetivo, mas o ganho só vira performance real de infraestrutura cloud quando a aplicação de fato paraleliza a carga. Uma aplicação single-threaded não se beneficia de vCPUs adicionais, ganhe você 2 ou 16.

    Como diagnosticar contenção na sua VM

    Comandos de diagnóstico rápido e histórico

    Para monitorar a contenção em tempo real (snapshots pontuais), utilize:

    # Visão de CPU com steal time na última coluna
    
    iostat -c 1 30
    
    # Detalhamento por core, incluindo %st
    
    mpstat -P ALL 1 30

    O problema desses dois comandos é que eles capturam só um recorte de 30 segundos em tempo real. Para provar ao suporte do provedor um problema sustentado por 15-20 minutos, a ferramenta canônica no ecossistema Linux é o sar (pacote sysstat), que coleta e retém dados históricos:

    # Exibe métricas de CPU, incluindo %steal, do dia atual
    
    sar -u

    Se %st sustentado passa de 10% por 15-20 minutos — confirmado no histórico do sar — o problema é contenção de host, não código da aplicação. A ação é conversar com o provedor sobre migração de host ou migrar para CPU dedicada.

    Para monitoramento contínuo em vez de coletas pontuais, vale expor métricas nativas como node_cpu_seconds_total{mode=”steal”} (node exporter) ou usar perf, alimentando dashboards no Grafana. Snapshots via CLI ajudam a diagnosticar um incidente já em curso; um dashboard contínuo mostra o pico antes de virar chamado.

    Quando o gargalo é I/O, não CPU

    O sintoma é parecido, load average alto com pouco uso aparente de CPU, mas a causa é outra: threads presas em espera de disco. Vale checar iowait e o percentual de processos em estado D antes de assumir que o problema é CPU.

    Um exemplo real: uma VM com load average de 5.0 e top/iotop mostrando pouca atividade. iostat -x expõe %iowait elevado com algum %steal simultâneo. O Linux conta como load average tanto processos executáveis quanto em espera de I/O, então carga alta com pouco uso de CPU visível é leitura incompleta da métrica, não paradoxo. Migrar a VM para outro host costuma normalizar tudo de imediato.

    Evidência para abrir chamado

    Reuna, antes de abrir o chamado:

    • Saída de sar -u (ou iostat -c 1 30) mostrando %steal sustentado ao longo do período.
    • Saída de mpstat -P ALL 1 30 com detalhamento por core.
    • Contagem de threads em estado D via ps -eo state= | awk ‘$1==”D”{c++} END{print c+0}’.

    Steal time varia ao longo do dia. Um snapshot de 30 segundos em horário calmo não captura o pico das 14h — por isso o histórico do sar (ou uma série contínua no Grafana) pesa mais como evidência do que um recorte isolado. Vale automatizar essa coleta.

    Escolhendo o plano certo: vCPU não é o único fator

    Dimensionar uma VM não é só somar vCPUs. RAM, disco e a proporção de overcommit do provedor entram na equação. Para builds de Next.js e Nuxt.js SSR, a recomendação prática é de no mínimo 2 vCPUs e 4 GB de RAM, abaixo disso o build pode travar.

    A base dessa escolha é dupla: o perfil real da sua carga, medido em steal time e throughput, e a transparência do provedor sobre como ele lida com overcommit. Antes de migrar de plano, rode mpstat (ou sar) por uma hora em horário de pico e registre o %st médio. Sem esse número, qualquer upgrade é aposta, não diagnóstico.

    Um provedor sólido não esconde a proporção de alocação atrás de “vCPUs ilimitadas” genéricas: ele documenta a razão real de vCPU por core em cada plano.

    E se sua carga roda em containers?

    Para quem roda Kubernetes ou Docker Swarm em cima de VMs cloud, o overhead de virtualização não desaparece, ganha uma camada extra de complexidade. O Kubernetes não aloca vCPUs exclusivas para os pods; ele utiliza cgroups (CFS Quota) no kernel do Linux para limitar o tempo de uso da CPU, medido em millicores. Isso significa que a contenção ocorre em dois níveis simultâneos:

    • No node, entre pods disputando as vCPUs via CFS quota do kernel.
    • No host físico, entre VMs de tenants diferentes disputando os núcleos físicos no hipervisor.

    Isso explica por que um pod com resources.limits.cpu: “2” às vezes sofre throttling ou latência mesmo quando o cluster relata uso baixo de CPU: o throttling do CFS acontece no node, mas a causa raiz pode estar um nível abaixo, na disputa por hardware entre VMs. Monitorar só métricas do Kubernetes (kubectl top, Prometheus) não mostra steal time do host. Vale correlacionar as duas fontes antes de escalar horizontalmente.

    Fechando a conta

    Para quem constrói no Locaweb Cloud, dimensionar vCPU corretamente é o primeiro passo antes de escalar a aplicação. Se sua VM está sofrendo com steal time ou você precisa de mais previsibilidade, vale avaliar os planos de Locaweb Cloud com proporção de alocação transparente, ou o Servidor VPS para cargas com perfil mais estável. Para proteger o tráfego entre sua aplicação e os usuários finais, o Certificado SSL fecha a configuração de produção.

    FAQ – Perguntas frequentes sobre vCPU e CPU física

    Não. Na nuvem moderna, uma vCPU geralmente corresponde a uma thread lógica de um núcleo físico (via Hyper-Threading ou SMT), agendada pelo hipervisor e compartilhada entre múltiplas VMs. Um núcleo físico é hardware dedicado, sem camada de virtualização.

    É o percentual de tempo em que sua vCPU está pronta mas o hipervisor está ocupado com outra VM no mesmo core. Meça com iostat -c ou mpstat -P ALL para um recorte pontual, e com sar -u quando precisar de histórico para comprovar contenção sustentada. Acima de 10% sustentado por 15-20 minutos indica contenção relevante.

    Não necessariamente. Uma aplicação single-threaded não aproveita vCPUs adicionais além da primeira.

    Quando o steal time sustentado ultrapassa 10% e a aplicação é sensível a latência. Para batch ou throughput, overcommit costuma ser suficiente e mais econômico.

    Sim. Pesquisa de 2026 sobre Kubernetes multi-tenant mediu degradações de até 67% em I/O sob contenção combinada, com significância estatística confirmada por análise causal.

    O autor

    Maria Luiza Hattler

    Maria Luiza Hattler é Analista de Marketing Sênior na Locaweb. Há mais de 4 anos ela atua com SEO, criação de conteúdo e e-commerce, sempre de olho no que realmente faz diferença para atrair tráfego orgânico e gerar resultado para os negócios. No dia a dia, gosta de testar novas abordagens e acompanhar as mudanças constantes do mercado digital, unindo estratégia e criatividade em cada projeto. Fora do trabalho, é apaixonada por música e games, e adora recarregar as energias vendo bons filmes e séries.

    Mais de Maria Luiza Hattler