Короткий ответ

Производительность Hyper-V — не один график Task Manager гостя. Снимите четыре слоя: (1) хост CPU/RAM/сеть, (2) раздел VM (Measure-VM, Hyper-V Hypervisor counters), (3) storage (CSV Direct, latency Virtual Storage Device), (4) внутри гостя. Добавление vCPU «на всякий» часто ухудшает scheduling. Сначала измерьте, потом меняйте один параметр.

Включите Resource Metering, посмотрите 15–30 минут пика, не 10 секунд в обед.

Симптомы и как отличить

Типичная картина:

  • RDP в VM-APP01 тягучий, CPU в госте 20%;
  • хост CPU 100%, гости «ждут»;
  • диск в госте очереди, хост iSCSI 100%;
  • после Live Migration на HV02 всё летает — виноват узел/CSV, не приложение.

Отличия:

Что видноКуда
Только диск / AVHDX / redirectedнагрузка диска, CSV
Только RAM balloonDynamic Memory
Нет baseline хостаhealth
Медленно только во время LMLive Migration

Возможные причины

  1. Переподписка vCPU, VP:LP далеко > 1–2 на OLTP без измерения.
  2. Memory pressure, smart paging, CSV swap.
  3. Storage: AVHDX, redirected, тонкий LUN, антивирус.
  4. VMQ/RSS/слишком много мелких VM на одном 1 GbE.
  5. NUMA spanning неуместный.
  6. Гость крутит антивирус+индексацию+backup внутри.
  7. Power plan Balanced на хосте (C-states) — иногда.

Диагностика

1. Обзор VM

Get-VM | Format-Table Name, State, CPUUsage, @{N='MemGB';E={[math]::Round($_.MemoryAssigned/1GB,1)}}, MemoryDemand, MemoryStatus, Uptime
Enable-VMResourceMetering -VMName 'VM-APP01'
Start-Sleep -Seconds 5
Measure-VM -Name 'VM-APP01' | Format-List

Полезные поля Measure-VM: AvgCPU, AvgRAM, MaxRAM, AggregatedAverageLatency, AggregatedAverageNormalizedIOPS, Network.

Сброс интервала после замера пика: Reset-VMResourceMetering -VMName 'VM-APP01' только когда сознательно начинаете новый период.

2. CPU хоста и гипервизора

Get-VMHost | Format-List LogicalProcessorCount, NumaSpanningEnabled
Get-Counter '\Hyper-V Hypervisor Logical Processor(_Total)\% Total Run Time','\Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time' -ErrorAction SilentlyContinue
Get-Process | Sort-Object CPU -Descending | Select-Object -First 15 Name, CPU, WorkingSet

Если набор счётчиков не зарегистрирован — Get-Counter -ListSet 'Hyper-V*' и берите существующие имена (локаль OS меняет display, пути часто английские).

В госте параллельно: % Processor Time, не только «диспетчер задач глазами».

3. Память

Get-VMMemory -VMName 'VM-APP01'
Get-VM | Format-Table Name, MemoryAssigned, MemoryDemand, MemoryStatus
Get-Counter '\Memory\Available MBytes','\Hyper-V Dynamic Memory Balancer(*)\Available Memory' -ErrorAction SilentlyContinue

Smart paging in use — уже авария слоя RAM, не «медленный SQL сам по себе».

4. Диск

Get-VMHardDiskDrive -VMName 'VM-APP01' | ForEach-Object { Get-VHD -Path $_.Path | Format-List Path, VhdType, ParentPath, FileSize }
Get-ClusterSharedVolumeState -ErrorAction SilentlyContinue | Format-Table Node, StateInfo
Get-Counter '\Hyper-V Virtual Storage Device(*)\Read Latency','\Hyper-V Virtual Storage Device(*)\Write Latency' -ErrorAction SilentlyContinue

Latency в секундах: 0.020 = 20 ms. Сверьте с гостевым PhysicalDisk.

5. Сеть

Get-VMNetworkAdapter -VMName 'VM-APP01' | Format-Table SwitchName, BandwidthUsage, CurrentIPAddresses
Get-VMSwitch | Format-Table Name, BandwidthReservationMode, IovEnabled

Не включайте SR-IOV «для скорости» без поддержки NIC/коммутатора и понимания Live Migration.

Журналы не заменят счётчики, но Error VMMS за час стоит глянуть.

Решение

Меняйте один рычаг за окно.

Сценарий A. CPU wait на хосте

Разъедьте VM, снизьте vCPU у «8 CPU потому что можно» до измеренного (часто 2–4). Не увеличивайте всем. Смотрите VP wait counters.

Сценарий B. RAM pressure

Статья Dynamic Memory: max/min/static для СУБД, не reboot всех.

Сценарий C. Диск

Слейте AVHDX, почините redirected, QoS соседям, не compact в пик. Разнесите log/data.

Сценарий D. Сеть

Отдельный NIC/SET для VM vs LM vs CSV. Проверьте VLAN и ошибки NIC (Get-NetAdapterStatistics).

Сценарий E. Гостевой шум

Патч, антивирус исключения внутри по вендору приложения, не Defender Off на хосте навсегда.

Снимайте хост и гостя в одно окно времени. Иначе склеите ночной backup с дневным CPU и вылечите не то.

Сравните HV01 и HV02 на одной и той же VM после LM: если на втором узле latency втрое меньше — это CSV/HBA/redirected на первом, не «SQL деградировал». Не добавляйте RAM на гостя, пока не исключили redirected.

Get-ClusterSharedVolumeState | Format-Table Node, StateInfo, VolumeFriendlyName
Measure-VM -Name 'VM-APP01'

Нормализуйте IOPS к размеру блока. Мелкий 4K random и последовательный backup не сравнивают одной цифрой «диск плохой». Смотрите Read vs Write latency раздельно: write-cache СХД маскирует reads иначе.

Не меняйте одновременно Dynamic Memory, vCPU и MaximumIOPS. После каждого шага — те же 15 минут пика и запись в заявку.

Как проверить, что проблема устранена

Тот же Measure-VM и Get-Counter на пике бизнеса: latency и CPU wait в целевом диапазоне (запишите числа в заявке: было/стало). Пользовательский сценарий (открыть форму, проводка) — секунды, не «ощущение админа». После Live Migration на другой узел картина не хуже.

Measure-VM -Name 'VM-APP01' | Format-List AvgCPU, AvgRAM, AggregatedAverageLatency, AggregatedAverageNormalizedIOPS
Get-VM -Name 'VM-APP01' | Format-List CPUUsage, MemoryStatus

Если не помогло

  • Только одно приложение: профайлер приложения, блокировки SQL, не Hyper-V.
  • Все VM на узле: СХД/HBA/сеть CSV.
  • После добавления vCPU хуже: верните, измеряйте VP:LP.
  • NUMA: большие VM > размер ноды — смотрите spanning, не гадайте.

Профилактика

  • Metering на критичных VM постоянно.
  • Алерт latency storage и MemoryStatus.
  • Запрет «8 vCPU шаблон».
  • Capacity: не сумма Maximum RAM.
  • Health-check перед патчем драйверов NIC/HBA.
  • Разделение сетей LM/CSV/VM.

FAQ

Сколько vCPU давать?

Стартуйте с измеренного пика гостя + небольшой запас. Лицензии Windows/SQL тоже считаются. Не «число ядер хоста».

Measure-VM врёт после Sleep?

Это среднее с момента Enable/Reset. Для пика — короткий Reset и измерение в час пик.

Нужен ли PerfMon GUI?

Можно. Get-Counter воспроизводим в заявке. Не забудьте длительность сбора.

Dynamic Memory для SQL «чтобы быстрее»?

Обычно наоборот. Static + max server memory.

VMQ выключить?

Только как тест при известных багах NIC, не постоянный «тюнинг с форума». Смотрите статистику VMQ.

Достаточно ли Task Manager на HV01?

Нет. Он плохо показывает hypervisor wait и per-VM storage. Без Measure-VM/счётчиков Hyper-V вы лечите не тот слой.