When your IIS worker process (w3wp.exe) consistently consumes high CPU resources, it typically indicates inefficient code execution, problematic queries, or resource contention. In your case with ASP.NET MVC and Entity Framework, several factors could contribute:
// Common performance pitfalls in EF:
var badQuery = db.Posts
.Include(p => p.Comments)
.Include(p => p.Author)
.ToList() // Premature materialization
.Where(p => p.IsPublished);
Start with these Windows Performance Monitor counters:
- Process(w3wp)\% Processor Time
- ASP.NET Applications(__Total__)\Requests/Sec
- .NET CLR Exceptions(w3wp)\# of Exceps Thrown
- SQLServer:SQL Statistics\Batch Requests/sec
When CPU spikes occur, capture a dump using either:
procdump -ma -n 3 -s 60 w3wp.exe
OR
DebugDiag /capture /process w3wp.exe /wait 60
Enable logging to detect inefficient queries:
// In Application_Start():
db.Database.Log = query => Debug.WriteLine(query);
// Or for more detailed analysis:
using (var context = new BlogContext())
{
context.Database.Log = Console.Write;
// Your query here
}
Check these frequent issues:
- N+1 queries from lazy loading
- Excessive view rendering logic
- Improper caching strategies
- Blocking I/O operations
For MP3 file serving, implement proper response buffering:
public ActionResult StreamAudio(int id)
{
var file = // Get file path from DB
return new FilePathResult(file, "audio/mpeg")
{
FileDownloadName = "podcast.mp3",
EnableRangeProcessing = true // Supports partial content
};
}
Verify these IIS settings:
- Application Pool: .NET 4.x, Integrated Pipeline
- Disable debug="true" in web.config
- Set
in web.config - Enable dynamic content compression
For deep performance analysis:
// Install-Package MiniProfiler
protected void Application_Start()
{
StackExchange.Profiling.MiniProfilerEF6.Initialize();
// Other initialization
}
// In _Layout.cshtml:
@StackExchange.Profiling.MiniProfiler.RenderIncludes()
This will provide detailed SQL timing and query analysis right in your browser.
When your ASP.NET MVC application hosted on IIS shows persistent high CPU usage in w3wp.exe (the IIS worker process), it typically indicates inefficient code execution, problematic database queries, or server configuration issues. Let's explore systematic ways to diagnose this.
Start by examining these key performance counters in PerfMon:
- Process(w3wp)\% Processor Time - ASP.NET Applications\Requests/Sec - ASP.NET Applications\Request Execution Time - SQLServer:SQL Statistics\Batch Requests/sec - Memory\Available MBytes - PhysicalDisk(_Total)\Avg. Disk Queue Length
Use these tools to identify what's happening inside w3wp.exe:
1. Process Explorer (Sysinternals)
Right-click w3wp.exe → Properties → Threads tab to see active threads and their CPU consumption. Look for:
- Managed threads executing .NET code
- External calls to SQL Server
- I/O wait operations
2. DebugDiag Analysis
Create a CPU hang dump when CPU spikes occur:
DebugDiag 2 Collection → Rule Type: Performance → Select w3wp.exe Set threshold at 90% CPU for 30 seconds
MiniProfiler Integration
Add this to your MVC application to identify slow requests:
// Install-Package MiniProfiler protected void Application_Start() { StackExchange.Profiling.MiniProfiler.Configure(new MiniProfilerOptions { RouteBasePath = "~/profiler", SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter(), TrackConnectionOpenClose = true }); } // In your _Layout.cshtml @StackExchange.Profiling.MiniProfiler.RenderIncludes()
Entity Framework Query Analysis
Add logging to detect inefficient EF queries:
// In DbContext constructor this.Database.Log = message => Debug.WriteLine(message); // For more detailed tracing this.Database.Log = msg => { File.AppendAllText(@"C:\EF_Log.txt", msg + Environment.NewLine); };
Verify these critical settings in applicationHost.config:
<system.webServer> <applicationPools> <add name="YourAppPool" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" queueLength="5000"> <recycling logEventOnRecycle="Time, Requests, Memory" /> </add> </applicationPools> <urlCompression doDynamicCompression="true" /> </system.webServer>
1. Isolate the Issue
Create a test endpoint with this simple code:
public ActionResult HealthCheck() { var sw = Stopwatch.StartNew(); // Test database connection var dbTest = db.Users.Count(); // Test file access System.IO.File.ReadAllText(Server.MapPath("~/test.txt")); sw.Stop(); return Content($"Execution time: {sw.ElapsedMilliseconds}ms"); }
2. Memory Dump Analysis
When CPU spikes occur, capture a dump:
procdump -ma -c 90 -n 3 w3wp.exe
Analyze with WinDbg:
.loadby sos clr !dumpheap -stat !threads !runaway ~*e !clrstack
EF Query Improvements
Common problematic patterns and fixes:
// Bad: N+1 queries foreach(var post in db.Posts) { var comments = post.Comments.ToList(); // Executes per iteration } // Good: Eager loading var posts = db.Posts.Include(p => p.Comments).ToList(); // Bad: Client evaluation var results = db.Posts .ToList() // Executes full query .Where(p => p.Title.Contains(searchTerm)); // Good: Server evaluation var results = db.Posts .Where(p => p.Title.Contains(searchTerm)) .ToList();
Output Caching
For static content-heavy pages:
[OutputCache(Duration=3600, VaryByParam="none")] public ActionResult StaticContent() { return View(); }