Hyper-V + NUMA Nodes

While I had come across the information before, until recently I did not find the time to put the necessary research in to what’s involved in properly configuring Hyper-V with NUMA nodes to take advantage of today’s multi-processor multi-core servers.

In simple terms, disabling NUMA node spanning in the Hyper-V hypervisor will prevent the system from “reaching” for RAM that is, by circuitry, further away and thus slower. If more detail is what you want, please check out the links below that I found very informative.

In my opinion a large part of NUMA node optimization is derived from manually assigning NUMA nodes based on memory need. This manual assignment can be done by creating a PowerShell script. Copy/paste the below text in to Notepad and save it as numa.ps1 (or whatever you would like with .ps1 extension.)

################################################
# 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))

I found the above PowerShell scripting when I was reading through this article on the MSDN blog. If you’re running through the steps here,  the next hurdle you’ll run in to is the script permissions on Windows 2008. See the below TechNet article for correcting the “File XXX cannot be loaded because the execution of scripts is disabled on this system.” error.
Modifying PowerShell script permissions: http://technet.microsoft.com/en-us/library/ee176949.aspx