Vai al contenuto
EuroVPSEuroVPS

Perché una VM più grande di un socket CPU è spesso più lenta

Perché una VM più grande di un socket CPU è spesso più lenta: accessi remoti alla memoria, coerenza delle cache, scheduling. Due regole e i comandi.

Di EuroVPS Engineering

5 min di lettura
Why a VM bigger than one CPU socket is often slower

Quando una macchina virtuale è lenta, il riflesso è darle più core. Su un server moderno a due socket c'è un punto in cui quel riflesso vi si ritorce contro, e la VM più grande gira più lenta di quella più piccola che ha sostituito. Il punto è la dimensione di un socket CPU, e il motivo si chiama NUMA.

Cos'è NUMA, in un paragrafo

Un server con due processori è in realtà due computer che condividono un ponte. Ogni socket ha i propri controller di memoria e il proprio banco di memoria collegato direttamente. Un core che legge memoria collegata al proprio socket la ottiene a velocità locale. Un core che legge memoria collegata all'altro socket deve attraversare l'interconnessione tra i socket, e quell'accesso è più lento. Questa disposizione è l'accesso non uniforme alla memoria: ogni core può raggiungere tutta la memoria, ma non allo stesso costo. Ogni socket con la sua memoria è un nodo NUMA.

Perché attraversare il confine costa più di quanto sembri

Un accesso remoto alla memoria richiede circa 1,7 volte il tempo di uno locale. Già da solo è una penalità grande per qualsiasi cosa tocchi spesso la memoria, cioè quasi tutto. E non è nemmeno l'intero conto:

  • Coerenza delle cache. I due socket devono mantenere coerenti le loro cache. Quando thread su entrambi i lati lavorano sugli stessi dati, le linee di cache rimbalzano attraverso l'interconnessione, e ogni rimbalzo è uno stallo.
  • Saturazione dell'interconnessione. Il collegamento tra i socket ha banda finita. Una VM trafficata distribuita su entrambi i socket se la contende con tutto il resto sull'host.
  • Scheduling. Una VM le cui vCPU non possono girare tutte insieme su un solo socket aspetta che l'hypervisor trovi spazio su entrambi, e i suoi thread finiscono dove c'è posto, spesso lontano dai loro dati.

Questi effetti si moltiplicano invece di sommarsi. Un carico di lavoro che scalerebbe bene dentro un socket può perdere una larga quota del suo throughput una volta distribuito su due, e i core in più che avete aggiunto pagano per il privilegio.

Leggete la topologia del vostro host

Prima di dimensionare qualsiasi cosa, guardate cosa ha davvero l'host:

lscpu | grep -E 'Socket|Core|Thread|NUMA'
numactl --hardware

Output tipico su un host a due socket:

Thread(s) per core:  2
Core(s) per socket:  18
Socket(s):           2
NUMA node(s):        2
NUMA node0 CPU(s):   0-17,36-53
NUMA node1 CPU(s):   18-35,54-71

I numeri che contano sono i core per socket e la memoria per nodo, che numactl --hardware stampa insieme a una tabella delle distanze. Le distanze mostrano quanto costa in più un accesso remoto rispetto a uno locale su questa macchina esatta.

Dimensionate sui core fisici, non sugli hyper-thread.

Le due regole di dimensionamento

Dalla topologia derivano due regole facili da enunciare e che vale la pena non infrangere mai:

  • Una VM non riceve mai più vCPU di quanti core fisici abbia un socket. Lasciate margine per l'hypervisor stesso, quindi su un socket a diciotto core un tetto sensato è un paio di core sotto.
  • Una VM non riceve mai più memoria di quanta ne serva un nodo NUMA. Altrimenti parte della sua memoria è remota per costruzione, qualunque cosa faccia lo scheduler.

Una VM che rispetta entrambe le regole può vivere interamente dentro un nodo, e un buon hypervisor ce la terrà.

Controllate dove vive davvero una VM in esecuzione

Su un host KVM potete vedere come la memoria di un guest è distribuita tra i nodi:

numastat -c qemu-kvm
virsh vcpuinfo <vm-name>
virsh numatune <vm-name>

Se numastat mostra una VM grande con memoria sostanziale su entrambi i nodi, sta pagando la penalità dell'accesso remoto su una quota del suo lavoro. Dentro un guest Linux, lscpu e numactl --hardware mostrano la topologia che l'hypervisor gli presenta.

Quando un socket davvero non basta

Alcuni carichi di lavoro hanno davvero bisogno di più di quanto un socket possa dare. Ci sono risposte migliori di un'unica VM gigante:

  • Scalate in orizzontale. Due VM che stanno ciascuna in un nodo, dietro un load balancer o come membri di un cluster, di solito battono una VM che si estende su entrambi.
  • Correggete prima il collo di bottiglia. Una VM che sembra aver bisogno di più core spesso sta aspettando lo storage, dei lock o un singolo thread occupato. Aggiungere core a un carico che non può usarli non cambia nulla, tranne la penalità NUMA.
  • Se deve essere grande, rendetela consapevole di NUMA. Presentate al guest una topologia virtuale che rispecchi l'host, due nodi virtuali corrispondenti ai due fisici, e vincolate ogni nodo virtuale al suo nodo fisico. Un sistema operativo e un'applicazione che conoscono NUMA possono allora tenere i thread vicino ai loro dati. I gestori KVM enterprise, OLVM tra questi, espongono il NUMA pinning per questo.

Più grande non è comunque linearmente più veloce

Anche dentro un socket, raddoppiare le vCPU raramente raddoppia il throughput. Parti di ogni carico di lavoro sono seriali, i lock si fanno più contesi man mano che i thread si moltiplicano, le cache sono condivise, e l'hypervisor fatica di più a schedulare una VM larga. Il raddoppio vale di solito una frazione del raddoppio, e oltre il confine del socket può diventare negativo. Il modo onesto di dimensionare è far girare il carico reale a due dimensioni e misurare. La VM più piccola vince più spesso di quanto la gente si aspetti.

Come lo facciamo noi

Sui nostri private cloud OLVM e su ogni altra piattaforma che gestiamo, entrambe le regole si applicano a ogni VM: mai più vCPU di quanti core abbia un socket fisico, mai più memoria di quanta ne serva un nodo NUMA, dimensionate sulla topologia reale dell'host. Dimensioniamo esattamente su ciò che il carico richiede invece di arrotondare per eccesso.

Se le vostre VM sono state dimensionate a intuito, o semplicemente sono cresciute una richiesta alla volta, saremo lieti di guardare la topologia e i numeri insieme a voi.

Parla con un ingegnere

Related (rows[1])

Correlati: Private cloud su KVM con OLVM · Ingegneria delle prestazioni e della capacità · Cloud dedicato su Apache CloudStack, secondo le vostre specifiche

Pubblicato il 10 settembre 2026.

Tutte le note dal campo