{"id":22047,"date":"2013-11-26T15:27:30","date_gmt":"2013-11-26T22:27:30","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/aspnet\/?p=22047"},"modified":"2013-11-26T15:27:30","modified_gmt":"2013-11-26T22:27:30","slug":"modified-asp-net-4-5-cpu-throttling","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/modified-asp-net-4-5-cpu-throttling\/","title":{"rendered":"Modified ASP.NET 4.5 CPU Throttling"},"content":{"rendered":"<p>A while back, Jose blogged about the <a href=\"http:\/\/blogs.msdn.com\/b\/josere\/archive\/2011\/09\/13\/cpu-throttling-for-asp-net-asynchronous-scenarios.aspx\">CPU throttling feature in ASP.NET 4.5<\/a>. As described in the original post, this feature is intended to correct negative scaling in server throughput when handling async requests on a server with saturated CPU.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/MSDNBlogsFS\/prod.evol.blogs.msdn.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/01\/37\/00\/5148.cpu_throttling_rps_vs_client.gif\" width=\"324\" height=\"209\" \/><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/MSDNBlogsFS\/prod.evol.blogs.msdn.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/01\/37\/00\/2548.cpu_throttling_rps_vs_client_with_throttling.gif\" width=\"308\" height=\"210\" \/><\/p>\n<p>Now, for the next chapter to this story: CPU throttling under stress scenarios.<\/p>\n<p>This feature was tested during development in the ASP.NET performance lab. Performance testing, unlike stress, tends to be very homogenous: measure server throughput under full load (CPU) when handling a specific scenario or request. When this feature entered the stress lab, it encountered more real-world applications: longer run times, various requests and bursty traffic. Under these conditions it became clear that CPU throttling had a problem with recovery.<\/p>\n<p>**PROBLEM: **As Jose mentioned, ASP.NET throttles requests by adding them to a native queue until the managed layer is ready to process them. This is the same native queue used when <a href=\"http:\/\/blogs.msdn.com\/b\/tmarq\/archive\/2007\/07\/21\/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx\">MaxConcurrentRequestsPerCpu or MaxConcurrentThreadsPerCpu<\/a> is exceeded. ASP.NET attempts to dequeue when other requests enter or complete the pipeline. This behavior is fine for requests queued due to high concurrency, since a large number of requests are executing and headed for completion. However, CPU throttling is not based on number of requests but on how expensive they are. As a result, there could be just a few CPU-intensive requests causing a backup in the native queue with no way to empty it aside from incoming requests.<\/p>\n<p><strong>SOLUTION:<\/strong> ASP.NET CPU throttling was modified just prior to RTM. ASP.NET now supports more aggressive dequeuing from the native queue both with incoming\/completing requests and via a timer. Also, a second configuration, **\u201cpercentCpuLimitMinActiveRequestPerCpu\u201d **was added to ensure a minimum number of requests are being served before throttling kicks in. The default throttling limit was also lowered from 99% to 90% in order to detect high pressure and avoid negative scaling earlier.<\/p>\n<p>In conclusion, it is highly recommended that you don\u2019t run your web servers at full capacity. Enabled by default, this feature is primarily intended as a safety net to prevent degradation in performance when serving async requests under load. If you find that requests are sitting in the queue (see: <strong>\u201cASP.NET\\Requests in Native Queue\u201d<\/strong>) even after the CPU has normalized, try disabling the feature by setting percentCpuLimit to 0.\u00a0<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">&lt;<\/span><span class=\"html\">configuration<\/span><span class=\"kwrd\">&gt;<\/span>\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">system.web<\/span><span class=\"kwrd\">&gt;<\/span>\n        <span class=\"kwrd\">&lt;<\/span><span class=\"html\">applicationPool<\/span> <span class=\"attr\">percentCpuLimit<\/span>=\u201d<span class=\"attr\">90<\/span>\u201d <span class=\"attr\">percentCpuLimitMinActiveRequestPerCpu<\/span>=\u201d<span class=\"attr\">100<\/span>\u201d<span class=\"kwrd\">&gt;<\/span>\n    <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">system.web<\/span><span class=\"kwrd\">&gt;<\/span>\n<span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">configuration<\/span><span class=\"kwrd\">&gt;<\/span><\/pre>\n<p>Many thanks to Konst Khurin for his work on this feature and blog review.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Security and Quality Rollup is available via Windows Update, Windows Server Update Services, and Microsoft Update Catalog.<\/p>\n","protected":false},"author":404,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[4,11],"class_list":["post-22047","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-net","tag-net-framework"],"acf":[],"blog_post_summary":"<p>The Security and Quality Rollup is available via Windows Update, Windows Server Update Services, and Microsoft Update Catalog.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/22047","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/404"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=22047"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/22047\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=22047"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=22047"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=22047"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}