Le VM Hyper‑V su Windows Server 2022 possono sembrare “lente” dopo un upgrade dell’hardware. In molti casi non è un bug: è la conseguenza della combinazione tra core scheduler e Hyper‑Threading. Ecco come riconoscerlo, misurarlo e risolverlo con azioni concrete.
Scenario e sintomi
Un ambiente è stato aggiornato da Windows Server 2016 a Windows Server 2022 e migrato su host nuovi con CPU Intel Xeon Gold di 4ª generazione. Dopo la migrazione, alcune VM mostrano una perdita di prestazioni marcata nei benchmark (Cinebench) e nei carichi reali CPU‑bound: fino a ~80% più lente rispetto all’host fisico e decisamente sotto le attese rispetto all’upgrade hardware.
Gli allarmi del monitoraggio evidenziano CPU wait for dispatch e tempi di attesa/ready elevati, nonostante un basso livello di over‑commit complessivo. Inoltre, nei guest Windows Server 2016 compare ancora la stringa “10.0.14393
” per i componenti di integrazione, sollevando dubbi su possibili driver obsoleti.
Il cuore del problema: SMT esposto dal core scheduler
A partire da Windows Server 2019, Hyper‑V adotta per impostazione predefinita il core scheduler, progettato per migliorare isolamento e sicurezza dei carichi multi‑tenant. Se l’host ha SMT (Hyper‑Threading) = 2, il core scheduler tende a mappare i vCPU in thread “fratelli” sullo stesso core, esponendo ai guest una topologia 2‑thread per core.
Topologia vista dal guest (configurazione predefinita con SMT=2)
VM con 4 vCPU → 2 core × 2 thread (2c/4t)
VM con 8 vCPU → 4 core × 2 thread (4c/8t)
Questo comporta due effetti pratici:
- Prestazioni per core “percepite” più basse in carichi CPU‑bound che scalano meglio su core pieni che su thread SMT. La VM con 4 vCPU “2c/4t” può risultare più lenta della stessa VM “4c/4t”.
- Licensing per core: in scenari in cui si licenzia “per core” nel guest (es. SQL Server), l’efficienza per licenza può ridursi perché due thread SMT non equivalgono a due core fisici in termini di throughput.
Perché crescono “CPU wait for dispatch” e i tempi di ready
Con il core scheduler attivo e SMT esposto, Hyper‑V può assegnare a un vCPU un solo thread del core fisico. Il thread gemello resta inutilizzato o assegnato ad altri vCPU con vincoli di co‑schedulazione. Se il carico nel guest richiede core pieni (e non beneficia di SMT), il risultato è un aumento dei tempi di attesa per l’accesso a core effettivi, che si manifesta come CPU Wait for Dispatch anche in assenza di over‑commit severo.
Falsi sospetti: Integration Services “vecchi”
Da Windows Server 2016 in poi, i Servizi di integrazione Hyper‑V sono incorporati nel sistema operativo e si aggiornano tramite Windows Update. La stringa di versione visualizzata nel registro (ad esempio 10.0.14393
per guest 2016) è normale e non richiede ISO o dischi d’installazione manuali. Gli scarti prestazionali di cui sopra non dipendono dai componenti di integrazione.
Verifiche rapide: cosa controllare subito
- SMT attivo sull’host
Get-CimInstance -ClassName Win32_Processor | Select-Object Name, NumberOfCores, NumberOfLogicalProcessors
SeNumberOfLogicalProcessors = 2 × NumberOfCores
l’Hyper‑Threading è attivo. - Scheduler Hyper‑V
In Windows Server 2019/2022 il core scheduler è predefinito. Se in passato hai personalizzato il tipo di scheduler, verificane lo stato conbcdedit /enum {current}
cercando la voce hypervisorschedulertype. - Versione di configurazione VM
Get-VM | Format-Table Name, Version
Per poter controllare i thread per core nel guest è richiesta VM version ≥ 9.0. Se inferiore:# Necessita VM spenta. Operazione non reversibile. Update-VMVersion -Name "<NomeVM>"
- Thread per core esposti al guest
Get-VMProcessor -VMName "<NomeVM>" | Format-List Count, HwThreadCountPerCore
HwThreadCountPerCore = 0
: segue l’host (con SMT=2 → guest vede 2 thread per core).HwThreadCountPerCore = 1
: il guest vede 1 thread per core (topologia “4c/4t” con 4 vCPU).
- Piano energetico su host e guest
powercfg /L powercfg /S SCHEME_MIN # "Prestazioni elevate"
- Contatori di performance (PerfMon o VM Insights)
- Hyper‑V Hypervisor Virtual Processor → CPU Wait Time Per Dispatch, % Guest Run Time, % Total Run Time.
- Hyper‑V Hypervisor Logical Processor → % Total Run Time, % Guest Run Time, % Hypervisor Run Time.
- Correla i picchi di Wait for Dispatch con l’attività delle VM più rumorose.
Conseguenze sui benchmark e su carichi reali
Benchmark come Cinebench accentuano la differenza tra thread SMT e core pieni. In topologie “2c/4t” il punteggio multi‑core può restare ben al di sotto dell’host fisico e talvolta anche di configurazioni “4c/4t” con meno vCPU ma core “pieni”. In carichi reali (es. query OLTP CPU‑bound o engine .NET con alto parallelismo) la sensazione è di “CPU sempre al 50–60% ma richieste lente”: i thread SMT tengono occupati i vCPU senza restituire il throughput atteso.
Soluzioni pratiche e percorso decisionale
La buona notizia: non c’è un bug di Windows Server 2022. La perdita è architetturale e configurabile. Le opzioni seguenti sono ordinate dalla meno invasiva alla più drastica.
Obiettivo | Azione consigliata | Note |
---|---|---|
Far vedere al guest 4 core reali (4c/4t) anziché 2c/4t | In PowerShell sul nodo Hyper‑V:Set-VMProcessor -VMName "<NomeVM>" -HwThreadCountPerCore 1 | Forza 1 thread per core al guest. Disponibile con VM version ≥ 9.0. Riavvio VM consigliato. |
Verificare/aggiornare la versione di configurazione VM | Get-VM | ft Name, Version Update-VMVersion -Name "<NomeVM>" # VM spenta | Necessario per gestire HwThreadCountPerCore . Operazione non reversibile; verifica compatibilità dei cluster. |
Ripristinare prestazioni “equivalenti” al vecchio host | Imposta HwThreadCountPerCore 1 oppure raddoppia i vCPU (es. 4→8) mantenendo SMT esposto. | Dopo la modifica, ripeti i benchmark: tipicamente il divario scende a pochi punti percentuali rispetto al bare‑metal. |
Uniformità di latenza su carichi sensibili | Valuta il classic scheduler:bcdedit /set hypervisorschedulertype Classic Restart-Computer | Può migliorare la latenza in ambienti non multi‑tenant. Riduce però l’isolamento di sicurezza garantito dal core scheduler. |
Eliminare del tutto l’effetto SMT | Disabilita Hyper‑Threading nel BIOS degli host. | Soluzione drastica: riduce il parallelismo disponibile a tutte le VM ma semplifica licenze “per core” e prevedibilità. |
Procedura consigliata passo‑passo
- Pianifica una finestra di manutenzione per le VM critiche. Esegui snapshot/checkpoint o assicurati di avere backup recenti.
- Allinea la versione delle VM: spegni le VM con versione < 9.0 e lancia
Update-VMVersion
. Verifica la compatibilità con i nodi del cluster. - Imposta i thread per core: per le VM CPU‑bound o licenziate “per core”, esegui
Set-VMProcessor -HwThreadCountPerCore 1
. Riavvia la VM. - Riesegui i benchmark (Cinebench, workload sintetici interni) e confronta con l’host fisico. Se necessario, raddoppia i vCPU mantenendo
-HwThreadCountPerCore 1
per massimizzare la resa per core. - Ottimizza il piano energetico su host e guest a “Prestazioni elevate” e verifica che il frequency scaling non limiti le frequenze turbo.
- Monitora con PerfMon/VM Insights: punta a CPU Wait for Dispatch stabile e riduci i vCPU se i ready/wait superano il 10–15% in idle.
- Documenta la topologia finale dei guest (es. “8 vCPU → 8c/8t” o “4 vCPU → 4c/4t”) per allineare team Ops e team Licensing.
Buone pratiche complementari
- vNUMA: se una VM supera la capienza di un singolo NUMA node (per vCPU o per RAM), assicurati che la topologia vNUMA sia coerente con l’hardware per evitare cross‑node penalty.
- Storage NVMe/SSD e queue depth adeguata: i test CPU‑bound possono diventare I/O‑bound in fretta; mantieni la latenza bassa per non “sprecare” cicli CPU in attesa.
- Driver, UEFI/BIOS e micro‑code sempre aggiornati: mitigazioni di sicurezza e micro‑ottimizzazioni firmware impattano scheduling e boost.
- Consolidamento ragionato: evita di concentrare troppi vCPU “caldi” sullo stesso socket/NUMA; distribuisci i carichi rumorosi.
- Affinità CPU (solo quando necessario): Hyper‑V consente hard‑affinity per casi speciali; usala con parsimonia, preferendo il tuning di topologia.
Domande frequenti
Serve aggiornare manualmente i Servizi di integrazione nei guest?
No. Da Windows Server 2016 sono in‑box e si aggiornano via Windows Update. La stringa “10.0.14393” nei guest 2016 è normale.
Posso impostare HwThreadCountPerCore
senza downtime?
La modifica è supportata su VM version ≥ 9.0. Pianifica comunque un riavvio del guest per garantire che il sistema operativo rilevi la nuova topologia CPU in modo pulito.
Meglio forzare 1 thread per core o disabilitare l’HT sul server?
Forzare HwThreadCountPerCore = 1
è più flessibile: puoi applicarlo solo alle VM sensibili o licenziate “per core”. Disabilitare HT nel BIOS impatta tutte le VM e riduce l’headroom complessivo dell’host.
Il classic scheduler è più veloce?
Dipende. In ambienti non multi‑tenant e latenza‑sensibili può offrire un profilo di prestazioni più prevedibile. In ambienti condivisi, il core scheduler resta preferibile per ragioni di isolamento e mitigazione di vulnerabilità basate su SMT.
Come interpreto “CPU Wait for Dispatch”?
È il tempo che un vCPU attende prima di essere eseguito su un processore logico. Valori elevati e stabili suggeriscono contention o topologia inefficiente (es. troppi vCPU mappati come thread SMT). Riduci i vCPU, forza 1 thread per core o ridistribuisci il carico per abbassarlo.
Esempi pratici: prima/dopo
Scenario | Topologia (guest) | Intervento | Esito atteso |
---|---|---|---|
VM SQL con 4 vCPU | 2c/4t (predefinito con SMT) | HwThreadCountPerCore = 1 | Throughput per core ↑, latenza più stabile; licensing “per core” più efficiente. |
VM app con 8 vCPU | 4c/8t (predefinito con SMT) | Resta SMT esposto ma raddoppia vCPU se serve throughput | Multi‑thread throughput ↑, senza toccare scheduler; consumo host ↑. |
Farm web multi‑tenant | Misto | Core scheduler, HwThreadCountPerCore selettivo | Buon compromesso tra sicurezza, prevedibilità e densità. |
Checklist operativa
- [ ] Verifica SMT sui nodi e piano energetico “Prestazioni elevate”.
- [ ] Aggrega metriche: CPU Wait for Dispatch, % Guest Run Time, latenza app.
- [ ] Aggiorna VM a versioni ≥ 9.0 (downtime pianificato).
- [ ] Applica
-HwThreadCountPerCore 1
alle VM CPU‑bound o licenziate “per core”. - [ ] Ricalibra i vCPU (riduci se idle ad alto ready; aumenta solo se necessario).
- [ ] Riesegui benchmark e valida con carichi reali.
- [ ] Documenta topologie e motivazioni per auditing e compliance.
Appendice: comandi utili (copiabili)
# 1) Stato SMT sull'host
Get-CimInstance -ClassName Win32_Processor |
Select-Object Name,NumberOfCores,NumberOfLogicalProcessors
2) Elenco VM e versione di configurazione
Get-VM | Format-Table Name, Version
3) Aggiornare versione VM (richiede VM spenta; non reversibile)
Update-VMVersion -Name ""
4) Forzare 1 thread per core nel guest
Set-VMProcessor -VMName "" -HwThreadCountPerCore 1
Restart-VM -Name ""
5) Verificare la topologia esposta
Get-VMProcessor -VMName "" |
Format-List Count, HwThreadCountPerCore, CompatibilityForMigrationEnabled
6) (Opzionale) Impostare classic scheduler a livello host
bcdedit /set hypervisorschedulertype Classic
Restart-Computer
7) Piano energetico ad alte prestazioni (host/guest)
powercfg /L
powercfg /S SCHEME_MIN
Riepilogo per decisori
- Non è un bug di Windows Server 2022: è l’effetto del core scheduler che espone SMT ai guest.
- Obiettivo: performance per core e prevedibilità → forzare
HwThreadCountPerCore = 1
sulle VM sensibili. - Obiettivo: throughput massimo assoluto → mantenere SMT, aumentare vCPU dove utile e monitorare contention.
- Licensing “per core” → evitare di “pagare thread” con resa inferiore: privilegia core pieni nel guest.
Riferimenti (senza link)
- Manage Hyper‑V Hypervisor Scheduler Types — documentazione Microsoft Learn (core vs classic scheduler, SMT e mapping dei thread).
- Manage Hyper‑V Integration Services — documentazione Microsoft Learn (servizi di integrazione in‑box nei sistemi operativi moderni).
- Core scheduler: does it make sense not to use hyper‑threading in this scenario? — discussione tecnica su Microsoft Q&A (considerazioni prestazionali e di licenza).
Conclusione
Il salto a Windows Server 2022 e a CPU moderne mette in evidenza un aspetto spesso trascurato: la topologia CPU che il guest vede. Con il core scheduler e SMT attivo, una VM con 4 vCPU può diventare “2c/4t”, penalizzando carichi che rendono meglio su core pieni e alterando la convenienza delle licenze per core. La correzione è semplice e a basso rischio: imposta HwThreadCountPerCore = 1
per le VM critiche (o disabilita l’HT a livello host se vuoi uniformità assoluta). Così le VM tornano a vedere lo stesso numero di core reali che avevano sul cluster 2016 e recuperano quasi tutto il vantaggio dell’hardware nuovo, con benefici tangibili in tempi di risposta, throughput e prevedibilità operativa.