Windows Server High CPU / Memory / Disk — Performance Degradation Diagnosis
A Windows Server becomes sluggish, applications time out, or users report slowness. Systematic diagnosis using Resource Monitor, PerfMon counters, and process-level tools identifies whether the bottleneck is CPU saturation, memory pressure, kernel pool exhaustion, or I/O queue depth.
Indicators
- Task Manager shows sustained CPU > 85 % with no obvious single-process cause
- Available memory consistently below 500 MB — excessive paging to disk
- Disk latency > 20 ms sustained — PhysicalDisk\Avg. Disk sec/Transfer
- Users report application slowness or timeouts on server-hosted workloads
- Event ID 2004 (Resource Exhaustion) or 2019/2020 (Non-paged/paged pool exhaustion) in System log
Likely causes
- Runaway process or service consuming CPU — antivirus full scan, Windows Update, or runaway service
- Memory leak in a service or driver — kernel non-paged pool growing unbounded
- Disk I/O bottleneck — undersized storage, RAID degraded, or SAN path latency
- Insufficient RAM for workload — server hosting more VMs or users than originally sized for
- Hyper-V Dynamic Memory balloon driver stealing guest RAM on over-committed host
- Antivirus real-time scanning directory with high file churn (database, spool)
Diagnostic steps
-
Open Resource Monitor (resmon.exe) — review CPU, Memory, Disk and Network tabs to identify the top consuming process and resource
-
Open PerfMon and add counters: \Processor(_Total)\% Processor Time, \Memory\Available MBytes, \PhysicalDisk(_Total)\Avg. Disk sec/Transfer, \PhysicalDisk(_Total)\Avg. Disk Queue Length
-
Identify top memory consumers: Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object Name, Id, @{N='MB';E={[math]::Round($_.WorkingSet64/1MB,1)}} | Select-Object -First 15
-
Check kernel pool leaks (Event ID 2019/2020): run poolmon.exe (from Windows SDK) — sort by NonP column; identify the tag consuming most non-paged pool and cross-reference against driver list
-
Check disk health: Get-PhysicalDisk | Select FriendlyName, HealthStatus, OperationalStatus; run CrystalDiskInfo for S.M.A.R.T data on physical hardware
-
Capture a 30-minute PerfMon data collector set baseline and export to BLG file for trend analysis; use Windows Admin Center Performance History if available
Resolution path
- Identify bottleneck resource (CPU / RAM / disk / network) using resmon and PerfMon
- Kill or restart runaway service; exclude high-churn directories from AV scanning
- For memory leaks: identify pool tag with poolmon, update or roll back driver
- For disk I/O: check RAID health, expand storage, or move heavy workloads to dedicated LUN
Prevention
- Establish PerfMon baselines at deployment — capture 24-hour counter log at normal load
- Configure Windows Admin Center alerts or SCOM performance thresholds
- Exclude database data files, spool directories and NTDS from AV real-time scanning
- Right-size RAM before deployment: 4 GB minimum + workload RAM per Microsoft guidance
Tools
- resmon.exe — Resource Monitor
- perfmon.exe — Performance Monitor
- poolmon.exe (Windows SDK) — kernel pool leak detection
- Process Explorer (Sysinternals) — per-thread CPU and handle counts
- Windows Admin Center — Performance History
- CrystalDiskInfo — disk S.M.A.R.T health
- Get-Process (PowerShell)