Looking for that last ounce of performance? Then try affinitizing your VM to a NUMA node

There are not many performance knobs in Hyper-V which is by design. We really seek out of the box performance. However if you are looking for that last bit of performance from your Virtual Machines (VM’s) and have already made a good selection for networking and storage you might consider setting the Non-Uniform Access (NUMA) node.

On AMD and some Intel based architectures the machine might be defined as NUMA. You can find out if the machine is NUMA by looking at the "Hyper-VM VM Vid Numa Node" performance counters. This counter set will report a counter set instance for each NUMA node unless the machine is a single node.

NUMA means each CPU has a different path to memory and those paths can have various lengths. For example CPU 0 on Node 0 when accessing CPU M’s memory on Node X might take 10ns where as CPU 0 on Node 0 accessing CPU N’s memory on Node Y will take 20ns. It’s this difference in memory access times that can impact overall VM performance. The worst case would be for a VM’s Virtual Processor (VP) to be running on a node furthest from where the memory for the VM is allocated.

In order to improve performance you can place VM’s on different nodes. In addition to placing the memory the Hypervisor scheduler will attempt to run the VM’s VP’s near where the memory where the VM is allocated. This creates a dual affinity which can be very beneficial.

If you would like to try placing VM’s on different nodes to improve performance you can use the code sample below to place the VM.

Example 1 – List currently configured VM’s

            C:\> .\numa.ps1 /list

Example 2 – Set NUMA affinity to node 1. Node numbering starts at node 0

            C:\> numa.ps1 /set tonyvm 1

Example 3 - Clear NUMA affinity

            C:\> numa.ps1 /clear tonyvm

  Enjoy,

  Anthony F. Voellm (aka Tony)

Save the following powershell script into a file named numa.ps1. WS08 has powershell as part of the release if you are running management from a remote machine that is XP / Vista you can download powershell here https://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx

################################################
# Developer: Anthony F. Voellm
# : Taylor Brown
# Copyright (c) 2008 by Microsoft Corporation
# All rights reserved
#
# This is "demonstration" code and there are no
# warrantees expressed or implied
################################################

 

# This script will set the Virtual Machine to run
# on a specific NUMA node

# Check command line arguments

if (($args.length -lt 1) -or
(($args[0] -ne "/list") -and
($args[0] -ne "/set") -and
($args[0] -ne "/clear")) -or
(($args[0] -eq "/set") -and ($args.length -lt 3)) -or
(($args[0] -eq "/clear") -and ($args.length -lt 2))) {
Write-Host "numa.ps1 /list [<Hyper-V host>]"
Write-Host "numa.ps1 /set <vm machine name> <required node> [<Hyper-V host>]"
Write-Host "numa.ps1 /clear <vm machine name> [<Hyper-V host>]`n"
Write-Host "Options:"
Write-Host "`t/list - show configured VM's"
Write-Host "`t/set <vm machine name> <required node> - set the NUMA node for the VM"
Write-Host "`t/clear <vm machine name> - clear NUMA node seting for the VM"
exit;
}

 

# just display VM's
if ($args[0] -eq "/list") {
if ($args.length -gt 1) {
$HyperVHost = $args[1];
}
Get-WmiObject -Namespace 'root\virtualization' -Query "Select * From Msvm_ComputerSystem" | select ElementName
exit;
}

 

# Set or clear

$HyperVHost = '.';
if ($args[0] -eq "/set") {
if ($args.length -gt 3) {
$HyperVHost = $args[3];
}
$VMName = $args[1];
$RequiredNode = $args[2];
} elseif ($args[0] -eq "/clear") {
if ($args.length -gt 2) {
$HyperVHost = $args[2];
}
$VMName = $args[1];
}

 
#Main Script Body
$VMManagementService = Get-WmiObject -Namespace root\virtualization -Class Msvm_VirtualSystemManagementService -ComputerName $HyperVHost

$Query = "Select * From Msvm_ComputerSystem Where ElementName='" + $VMName + "'"

$SourceVm = Get-WmiObject -Namespace root\virtualization -Query $Query -ComputerName $HyperVHost

 

$VMSettingData = Get-WmiObject -Namespace root\virtualization -Query "Associators of {$SourceVm} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState" -ComputerName $HyperVHost

 

if ($args[0] -eq "/set") {
$VMSettingData.NumaNodesAreRequired = 1
$VMSettingData.NumaNodeList = @($RequiredNode)
} else {
$VMSettingData.NumaNodesAreRequired = 0
}

 

$VMManagementService.ModifyVirtualSystem($SourceVm, $VMSettingData.PSBase.GetText(1))