CPU Settings for an Application Pool <cpu>
Overview
The <cpu>
element of the <add>
element in the <applicationPools>
collection configures values for CPU usage parameters and CPU actions that will be used in application pools.
NUMA Support
Non-Uniform Memory Access (NUMA) is a hardware-based method of associating processors to their own dedicated memory. NUMA is used to increase processor speed as an alternative to the traditional symmetric multiprocessor (SMP) model for multiprocessor support. You can set up IIS 8 and later to distribute and affinitize its processes on NUMA. The use of NUMA is configured in the CPU element by the numaNodeAssignment attribute that enables IIS to identify the most optimal NUMA node when the IIS worker process is about to start, and the numaNodeAffinityMode attribute that determines how the threads from an IIS worker process are affinitized to a NUMA node. NUMA is also configured using the MaxProcesses attribute of the processModel element, which when set to 0
specifies that IIS automatically runs the same number of worker processes as there are NUMA nodes. For more information, see IIS 8.0 Multicore Scaling on NUMA Hardware.
The NUMA selection logic and affinity type can be set in the Advanced Settings dialog box only if IIS is running on NUMA hardware.
Compatibility
Version | Notes |
---|---|
IIS 10.0 | The <cpu> element was not modified in IIS 10.0. |
IIS 8.5 | The <cpu> element was not modified in IIS 8.5. |
IIS 8.0 | Two enum values were added to the action attribute to define throttling behavior. The processorGroup attribute was added to define the number of processor groups used. The numaNodeAssignment and numaNodeAffinityMode attributes were added to specify the behavior of NUMA nodes. |
IIS 7.5 | The <cpu> element was not modified in IIS 7.5. |
IIS 7.0 | The <cpu> element was introduced in IIS 7.0. |
IIS 6.0 | The <cpu> element replaces portions of the IIS 6.0 IIsApplicationPools metabase property. |
Setup
The <applicationPools>
collection is included in the default installation of IIS 7 and later.
How To
How to edit CPU configuration settings
Open Internet Information Services (IIS) Manager:
If you are using Windows Server 2012 or Windows Server 2012 R2:
- On the taskbar, click Server Manager, click Tools, and then click Internet Information Services (IIS) Manager.
If you are using Windows 8 or Windows 8.1:
- Hold down the Windows key, press the letter X, and then click Control Panel.
- Click Administrative Tools, and then double-click Internet Information Services (IIS) Manager.
If you are using Windows Server 2008 or Windows Server 2008 R2:
- On the taskbar, click Start, point to Administrative Tools, and then click Internet Information Services (IIS) Manager.
If you are using Windows Vista or Windows 7:
- On the taskbar, click Start, and then click Control Panel.
- Double-click Administrative Tools, and then double-click Internet Information Services (IIS) Manager.
In the Connections pane, expand the server name, click Application Pools, and then click the application pool that you want to edit.
In the Actions pane, click Advanced Settings...
In the Advanced Settings dialog box, click the CPU property that you want to edit, then edit the value in the property value section of the dialog box, and then click OK. For example, you could change the Limit Action to NoAction, KillW3wp, Throttle, or ThrottleUnderLoad.
How to configure IIS for use with Non-Uniform Memory Access (NUMA) hardware
On the task bar, click Server Manager, click Tools, and then click Internet Information Services (IIS) Manager.
In the Connections pane, expand the server name, and then click Application Pools.
In the Application Pools pane, select the pool that you want to configure for NUMA.
In the Actions pane, select Advanced Settings.
Under Process Model, set Maximum Worker Processes to
0
.Under CPU, set processorGroup, numaNodeAffinityMode, and numaNodeAssignment.
Click OK.
Configuration
Attributes
Attribute | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
action |
Optional enum attribute. Configures the action that IIS takes when a worker process exceeds its configured CPU limit. The action attribute is configured on a per-application pool basis. The action attribute can be one of the following possible values. The default value is NoAction .
|
||||||||||
limit |
Optional uint attribute. Configures the maximum percentage of CPU time (in 1/1000ths of one percent) that the worker processes in an application pool are allowed to consume over a period of time as indicated by the resetInterval attribute. If the limit set by the limit attribute is exceeded, an event is written to the event log and an optional set of events can be triggered. These optional events are determined by the action attribute. Note: In IIS 8.5 and above, set limit in percent in the CPU pane of IIS Manager. In IIS 8.0, set limit in 1/1000ths of one percent in the CPU pane of IIS Manager. For both cases, the limit attribute in applicationHost.config is in 1/1000ths of one percent. The default value is 0 , which disables CPU limiting. |
||||||||||
numaNodeAffinityMode |
Optional enum attribute. Specifies how the threads of a process that is affinitized to a NUMA node will be scheduled on the node's cores. The numaNodeAffinityMode attribute can be one of the following possible values. The default value is Soft .
|
||||||||||
numaNodeAssignment |
Optional enum attribute. Specifies how IIS will determine which NUMA (non-uniform memory access) node to affinitize a process to. A NUMA node contains clusters of cores that share a single memory bank. This attribute is available in the CPU Advanced Settings only if NUMA nodes are available. The numaNodeAssignment attribute can be one of the following possible values. The default value is Most Available Memory .
|
||||||||||
processorGroup |
Optional int attribute. The number of processor groups used (zero-based). A processor group contains multiple cores. The Processor Group attribute is available in the CPU Advanced Settings only if the server has multiple processor groups. The default value is 0 , which means that a single processor group is used. |
||||||||||
resetInterval |
Optional timeSpan attribute. Specifies the reset period (in minutes) for CPU monitoring and throttling limits on an application pool. When the number of minutes elapsed since the last process accounting reset equals the number specified by this property, IIS resets the CPU timers for both the logging and limit intervals. Important: The resetInterval value must be greater than the time between logging operations, otherwise IIS will reset counters before logging has occurred, and process accounting will not occur. Note: Because process accounting in IIS uses Windows job objects to monitor CPU times for the whole process, process accounting will only log and throttle applications that are isolated in a separate process from IIS. The default value is 00:05:00 . |
||||||||||
smpAffinitized |
Optional Boolean attribute. Specifies whether a particular worker process assigned to an application pool should also be assigned to a given CPU. This property is used together with the smpProcessorAffinityMask and smpProcessorAffinityMask2 attributes. The default value is false . |
||||||||||
smpProcessorAffinityMask |
Optional uint attribute. Specifies the hexadecimal processor mask for multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool. Note: On 64-bit computers, the smpProcessorAffinityMask attribute contains the low-order DWORD for the processor mask, and the smpProcessorAffinityMask2 attribute contains the high-order DWORD for the processor mask. On 32-bit computers, the smpProcessorAffinityMask2 attribute has no effect. If you set the value to 1 (which corresponds to 00000000000000001 in binary), the worker processes in an application pool run on only the first processor. If you set the value to 2 (which corresponds to 0000000000000010 in binary), the worker processes run on only the second processor. If you set the value to 3 (which corresponds to 0000000000000011 in binary) the worker processes run on both the first and second processors. Note: Do not set this property to 0. Doing so disables symmetric multiprocessing (SMP) affinity and creates an error condition. This means that processes running on one CPU will not remain affiliated with that CPU throughout their lifetime. The default value is 4294967295 . |
||||||||||
smpProcessorAffinityMask2 |
Optional uint attribute. Specifies the high-order DWORD hexadecimal processor mask for 64-bit multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool. Note: On 64-bit computers, the smpProcessorAffinityMask attribute contains the low-order DWORD for the processor mask, and the smpProcessorAffinityMask2 attribute contains the high-order DWORD for the processor mask. On 32-bit computers, the smpProcessorAffinityMask2 attribute has no effect. The default value is 4294967295 . |
Child Elements
None.
Configuration Sample
The following configuration sample configures a single application pool named DefaultAppPool and sets the CPU to 50%, with an action to kill the worker process with a reset interval of 10 minutes.
<applicationPools>
<add name="DefaultAppPool">
<cpu limit="50000" action="KillW3wp" resetInterval="00:10:00" />
</add>
<applicationPoolDefaults>
<processModel identityType="NetworkService" />
</applicationPoolDefaults>
</applicationPools>
Sample Code
The following code samples configure the default application pool to kill the worker process when it exceeds the CPU limit, and configure the reset interval to four minutes.
AppCmd.exe
appcmd.exe set config -section:system.applicationHost/applicationPools /[name='DefaultAppPool'].cpu.action:"KillW3wp" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /[name='DefaultAppPool'].cpu.resetInterval:"00:04:00" /commit:apphost
Note
You must be sure to set the commit parameter to apphost
when you use AppCmd.exe to configure these settings. This commits the configuration settings to the appropriate location section in the ApplicationHost.config file.
C#
using System;
using System.Text;
using Microsoft.Web.Administration;
internal static class Sample
{
private static void Main()
{
using (ServerManager serverManager = new ServerManager())
{
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection applicationPoolsSection = config.GetSection("system.applicationHost/applicationPools");
ConfigurationElementCollection applicationPoolsCollection = applicationPoolsSection.GetCollection();
ConfigurationElement addElement = FindElement(applicationPoolsCollection, "add", "name", @"DefaultAppPool");
if (addElement == null) throw new InvalidOperationException("Element not found!");
ConfigurationElement cpuElement = addElement.GetChildElement("cpu");
cpuElement["action"] = @"KillW3wp";
cpuElement["resetInterval"] = TimeSpan.Parse("00:04:00");
serverManager.CommitChanges();
}
}
private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)
{
foreach (ConfigurationElement element in collection)
{
if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))
{
bool matches = true;
for (int i = 0; i < keyValues.Length; i += 2)
{
object o = element.GetAttributeValue(keyValues[i]);
string value = null;
if (o != null)
{
value = o.ToString();
}
if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))
{
matches = false;
break;
}
}
if (matches)
{
return element;
}
}
}
return null;
}
}
VB.NET
Imports System
Imports System.Text
Imports Microsoft.Web.Administration
Module Sample
Sub Main()
Dim serverManager As ServerManager = New ServerManager
Dim config As Configuration = serverManager.GetApplicationHostConfiguration
Dim applicationPoolsSection As ConfigurationSection = config.GetSection("system.applicationHost/applicationPools")
Dim applicationPoolsCollection As ConfigurationElementCollection = applicationPoolsSection.GetCollection
Dim addElement As ConfigurationElement = FindElement(applicationPoolsCollection, "add", "name", "DefaultAppPool")
If (addElement Is Nothing) Then
Throw New InvalidOperationException("Element not found!")
End If
Dim cpuElement As ConfigurationElement = addElement.GetChildElement("cpu")
cpuElement("action") = "KillW3wp"
cpuElement("resetInterval") = TimeSpan.Parse("00:04:00")
serverManager.CommitChanges()
End Sub
Private Function FindElement(ByVal collection As ConfigurationElementCollection, ByVal elementTagName As String, ByVal ParamArray keyValues() As String) As ConfigurationElement
For Each element As ConfigurationElement In collection
If String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase) Then
Dim matches As Boolean = True
Dim i As Integer
For i = 0 To keyValues.Length - 1 Step 2
Dim o As Object = element.GetAttributeValue(keyValues(i))
Dim value As String = Nothing
If (Not (o) Is Nothing) Then
value = o.ToString
End If
If Not String.Equals(value, keyValues((i + 1)), StringComparison.OrdinalIgnoreCase) Then
matches = False
Exit For
End If
Next
If matches Then
Return element
End If
End If
Next
Return Nothing
End Function
End Module
JavaScript
var adminManager = new ActiveXObject('Microsoft.ApplicationHost.WritableAdminManager');
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST";
var applicationPoolsSection = adminManager.GetAdminSection("system.applicationHost/applicationPools", "MACHINE/WEBROOT/APPHOST");
var applicationPoolsCollection = applicationPoolsSection.Collection;
var addElementPos = FindElement(applicationPoolsCollection, "add", ["name", "DefaultAppPool"]);
if (addElementPos == -1) throw "Element not found!";
var addElement = applicationPoolsCollection.Item(addElementPos);
var cpuElement = addElement.ChildElements.Item("cpu");
cpuElement.Properties.Item("action").Value = "KillW3wp";
cpuElement.Properties.Item("resetInterval").Value = "00:04:00";
adminManager.CommitChanges();
function FindElement(collection, elementTagName, valuesToMatch) {
for (var i = 0; i < collection.Count; i++) {
var element = collection.Item(i);
if (element.Name == elementTagName) {
var matches = true;
for (var iVal = 0; iVal < valuesToMatch.length; iVal += 2) {
var property = element.GetPropertyByName(valuesToMatch[iVal]);
var value = property.Value;
if (value != null) {
value = value.toString();
}
if (value != valuesToMatch[iVal + 1]) {
matches = false;
break;
}
}
if (matches) {
return i;
}
}
}
return -1;
}
VBScript
Set adminManager = WScript.CreateObject("Microsoft.ApplicationHost.WritableAdminManager")
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST"
Set applicationPoolsSection = adminManager.GetAdminSection("system.applicationHost/applicationPools", "MACHINE/WEBROOT/APPHOST")
Set applicationPoolsCollection = applicationPoolsSection.Collection
addElementPos = FindElement(applicationPoolsCollection, "add", Array("name", "DefaultAppPool"))
If (siteElementPos = -1) Then
WScript.Echo "Element not found!"
WScript.Quit
End If
Set addElement = applicationPoolsCollection.Item(addElementPos)
Set cpuElement = addElement.ChildElements.Item("cpu")
cpuElement.Properties.Item("action").Value = "KillW3wp"
cpuElement.Properties.Item("resetInterval").Value = "00:04:00"
adminManager.CommitChanges()
Function FindElement(collection, elementTagName, valuesToMatch)
For i = 0 To CInt(collection.Count) - 1
Set element = collection.Item(i)
If element.Name = elementTagName Then
matches = True
For iVal = 0 To UBound(valuesToMatch) Step 2
Set property = element.GetPropertyByName(valuesToMatch(iVal))
value = property.Value
If Not IsNull(value) Then
value = CStr(value)
End If
If Not value = CStr(valuesToMatch(iVal + 1)) Then
matches = False
Exit For
End If
Next
If matches Then
Exit For
End If
End If
Next
If matches Then
FindElement = i
Else
FindElement = -1
End If
End Function