How to Monitor Windows Server Performance with Built-in Tools (PerfMon, WPR, and PowerShell)

Last updated January 16, 2026 ~24 min read 28 views
Windows Server performance monitoring PerfMon Performance Monitor Resource Monitor Task Manager Event Viewer Windows Performance Recorder Windows Performance Analyzer WPR WPA PowerShell Get-Counter Perfmon counters Data Collector Sets PAL Reliability Monitor ETW Server performance baseline capacity planning
How to Monitor Windows Server Performance with Built-in Tools (PerfMon, WPR, and PowerShell)

Windows Server performance monitoring is easiest when you approach it as a workflow rather than a single tool. You start with fast, interactive views to confirm what’s “hot” right now, then you move into repeatable counter-based telemetry to prove patterns over time, and finally you capture deep traces only when you need root-cause evidence.

This article walks through that workflow using built-in Windows Server tools: Task Manager, Resource Monitor, Performance Monitor (PerfMon) with Data Collector Sets, Event Viewer and Reliability Monitor, and Windows Performance Recorder/Analyzer (WPR/WPA). You’ll also use PowerShell to query and log performance counters locally and remotely so monitoring can be automated and scaled.

The goal is not to teach you every counter. The goal is to help you monitor Windows Server performance in a way that is defensible (baseline + evidence), efficient (lightweight until you need depth), and actionable (you can tie symptoms to a subsystem and a change).

Start with a monitoring workflow: baseline, detect, investigate

If you only look at a server when someone complains, you end up diagnosing by anecdote. Built-in tools can absolutely support proactive monitoring, but you need a minimal structure.

A practical workflow looks like this:

First, establish a baseline: what do CPU, memory, disk, and network look like when the server is healthy under normal load? A baseline is not a single snapshot; it’s a time series over representative periods (business hours, batch windows, patch night, month end). You’ll use PerfMon logs (BLG/CSV) or PowerShell exports to capture that.

Second, detect deviations: when the server is “slow,” you want to quickly identify whether you’re dealing with CPU saturation, memory pressure, storage latency/queueing, or network constraints. Task Manager and Resource Monitor are ideal for that first pass because they provide per-process context.

Third, investigate with precision: if the basic counters show something like “disk is busy,” you need to prove why. Is it a single process with high I/O? Is it antivirus scanning? A storage path issue? A driver problem? This is where correlation (PerfMon + Event Viewer) and, when needed, ETW tracing via WPR/WPA becomes invaluable.

As you read, keep the workflow in mind. Each tool is strongest at a particular stage, and you’ll get better outcomes by combining them rather than trying to force one tool to answer every question.

Define what “performance” means on Windows Server

Performance issues are rarely “the CPU is high.” In practice, performance is the server’s ability to meet service-level expectations—request latency, throughput, and stability—while using resources efficiently.

On Windows Server, most performance investigations boil down to these subsystems:

CPU (compute): CPU saturation can be caused by a busy application, excessive context switching, interrupt/DPC load, or virtualization scheduling.

Memory: Memory pressure shows up as paging, low available memory, rising commit, or working set trimming. On modern Windows, “free” memory is not the goal; the goal is avoiding sustained paging and ensuring the working set fits.

Storage (disk): Storage problems frequently manifest as latency and queueing rather than “disk throughput.” High IOPS at low latency is fine; low IOPS with high latency is pain.

Network: Network issues can be raw bandwidth limits, but more often involve retransmits, drops, NIC offload/driver behavior, SMB client/server throttling, or packet processing overhead.

OS and kernel behavior: Driver issues, kernel contention, or excessive interrupts can cause symptoms that look like “the app is slow.”

Windows gives you built-in visibility across these areas. The key is choosing counters and views that map to the question you’re answering.

Establish a baseline with PerfMon and a minimal counter set

PerfMon is the core built-in tool for time-series performance data. It’s available on Windows Server via Performance Monitor (perfmon.msc) and supports both interactive charts and logged collections.

A baseline should be lightweight enough to run continuously (or at least during key windows), but rich enough to let you distinguish “normal busy” from “resource starvation.” The trick is choosing a minimal set that covers CPU, memory, disk, and network without flooding you with noise.

Choose a minimal baseline counter set

The specific counters vary by workload (file server vs. SQL vs. web server), but a general-purpose baseline often includes:

CPU:

  • Processor(_Total)\% Processor Time (overall CPU usage)
  • System\Processor Queue Length (run queue pressure; interpret with core count in mind)
  • Processor(_Total)\% Privileged Time (kernel time vs. user time)

Memory:

  • Memory\Available MBytes (immediate headroom; watch trends)
  • Memory\Committed Bytes and Memory\% Committed Bytes In Use (commit pressure)
  • Memory\Pages/sec (paging activity; interpret carefully, look for sustained values)

Disk (per logical disk and/or per physical disk depending on your setup):

  • LogicalDisk(_Total)\Avg. Disk sec/Read
  • LogicalDisk(_Total)\Avg. Disk sec/Write
  • LogicalDisk(_Total)\Current Disk Queue Length (queueing; interpret with storage type)
  • LogicalDisk(_Total)\Disk Bytes/sec (throughput context)

Network:

  • Network Interface(*)\Bytes Total/sec (traffic level)
  • Network Interface(*)\Output Queue Length (rarely large on modern systems, but useful when it is)

These won’t solve every problem, but they let you answer the first-order question: which subsystem is under pressure when users feel slowness?

Create a Data Collector Set for baseline logging

A Data Collector Set (DCS) is PerfMon’s mechanism for scheduled logging. It can write to BLG (binary) or CSV. BLG is efficient and preserves counter metadata; CSV is easy to open but can be large.

In perfmon.msc:

  1. Expand Data Collector Sets.
  2. Right-click User DefinedNewData Collector Set.
  3. Choose Create manually (Advanced).
  4. Select Performance counter.
  5. Add your baseline counters.
  6. Choose a sample interval (often 15 seconds for baseline; use 5 seconds for short incident windows).
  7. Set the log location on a disk with sufficient space.

For servers with sensitive performance profiles (busy SQL nodes, storage-heavy file servers), choose a larger interval (15–30 seconds) for always-on baselining and reserve 5-second sampling for short periods.

Use PowerShell to capture a baseline without the GUI

For repeatability, PowerShell is a strong companion to PerfMon. You can collect counters with Get-Counter and export to CSV for analysis.

Here’s a minimal example that samples a baseline set every 15 seconds for 30 minutes and writes a CSV:

$Counters = @(
  '\Processor(_Total)\% Processor Time',
  '\System\Processor Queue Length',
  '\Memory\Available MBytes',
  '\Memory\% Committed Bytes In Use',
  '\LogicalDisk(_Total)\Avg. Disk sec/Read',
  '\LogicalDisk(_Total)\Avg. Disk sec/Write',
  '\LogicalDisk(_Total)\Current Disk Queue Length',
  '\Network Interface(*)\Bytes Total/sec'
)

$SampleInterval = 15
$MaxSamples = 120 

# 120*15s = 30 minutes

Get-Counter -Counter $Counters -SampleInterval $SampleInterval -MaxSamples $MaxSamples |
  Export-Counter -Path 'C:\PerfLogs\baseline.csv' -FileFormat CSV

A useful operational pattern is to keep a “known good” baseline from last week/month and compare it to an incident capture. This comparison mindset helps you avoid false alarms, especially on servers with cyclical workloads.

Triage in real time with Task Manager (beyond CPU%)

Task Manager is often treated as a beginner tool, but it provides fast, actionable context: which processes are consuming CPU, memory, disk, and network right now, and whether contention is localized to one process or systemic.

When someone reports “the server is slow,” Task Manager answers the first question: is the system currently constrained?

Use the right Task Manager views for server triage

The Processes tab is useful, but for servers you’ll often get more from:

  • Performance tab: quick subsystem graphs and shortcut to Resource Monitor.
  • Details tab: more precise per-process view, columns for CPU time, working set, I/O, and priorities.
  • Users tab: helpful on RDS/session hosts.

On the Performance tab, pay attention to these patterns:

CPU: sustained near 100% suggests saturation, but also check whether it’s a spike or sustained plateau.

Memory: watch “In use” and “Committed.” A server can have high memory usage without pressure; pressure shows up when commit approaches commit limit and paging becomes sustained.

Disk: if disk active time is high, don’t stop there—correlate with latency counters in PerfMon or with Resource Monitor’s disk view.

Ethernet: high throughput might be normal (backup window) or a clue (unexpected replication, large file copy).

Real-world example: patch night causes CPU spikes on an RDS host

Consider an RDS Session Host where users report sluggish logons every Tuesday night. Task Manager shows CPU near 90–100% and multiple TiWorker.exe and TrustedInstaller.exe processes consuming CPU while logons stall.

This is a classic case where immediate triage is enough to identify the cause (servicing stack/Windows Update maintenance). But to make it operationally useful, you’d follow up by:

  1. Capturing a short PerfMon log during the window to quantify impact.
  2. Checking Event Viewer for WindowsUpdateClient events to confirm timing.
  3. Adjusting maintenance windows or update orchestration so the CPU-heavy phase doesn’t overlap with logon peaks.

Task Manager gives you the “what.” PerfMon and Event Viewer give you the “when” and the evidence to justify changes.

Pinpoint contention with Resource Monitor

Resource Monitor (resmon.exe) sits in the sweet spot between Task Manager and PerfMon: it’s interactive and per-process, but more detailed about disk and network activity.

Resource Monitor is particularly valuable when:

  • Disk is “busy” and you need to identify which files/processes are driving I/O.
  • Network is saturated or connections are stalling and you need per-process sockets.
  • Memory pressure is suspected and you need insight into commit/working set patterns.

Disk tab: identify high-latency I/O and the processes behind it

On the Disk tab, the “Disk Activity” and “Storage” sections help you connect symptoms to a process. Look at:

  • Total (B/sec) per process: who is generating I/O.
  • Response Time (ms): whether the storage is servicing requests promptly.
  • File path: what data is being touched (database files, log files, temp directories, profile containers).

If you see a process doing moderate throughput but with very high response time, you may be storage-latency bound rather than throughput-bound. That is where PerfMon disk latency counters become essential to quantify the issue over time.

Network tab: map bandwidth to processes and connections

The Network tab shows per-process network usage and current TCP connections. This is useful when a “slow server” is actually waiting on a remote dependency: a web app waiting on a backend API, a file server waiting on a domain controller, or a backup agent saturating the link.

Resource Monitor won’t tell you if you have packet loss on the wire, but it will quickly tell you whether the server itself is sending/receiving heavily and which process owns the sockets.

Memory tab: interpret memory pressure correctly

The Memory tab presents “Hard Faults/sec,” which is frequently misinterpreted. A hard fault is not automatically “bad”; it can include legitimate reads from the file cache or mapped files. What matters is sustained elevated faults alongside other signs of pressure (low available MB, high commit, performance degradation).

A good habit is to correlate memory observations in Resource Monitor with PerfMon:

  • If hard faults are high but disk latency is low and overall performance is fine, it may simply be caching behavior.
  • If hard faults are high and disk latency spikes coincide, paging pressure is more likely impacting responsiveness.

This is where you transition from interactive tools to logged counters.

Use PerfMon for targeted investigation (not just baselining)

Once you’ve identified the likely subsystem, you refine your PerfMon counter set to answer a more specific question. The key is to avoid “counter sprawl.” Add counters intentionally and use instances (per disk, per NIC, per process) when needed.

CPU: distinguish saturation, kernel time, and scheduling issues

When CPU is high, you want to know whether the load is in user mode (application work) or privileged mode (kernel/driver work), and whether the system is context-switching heavily.

Useful counters include:

  • Processor(*)\% Processor Time (per core; can reveal single-thread bottlenecks)
  • Processor(_Total)\% Privileged Time (high values suggest kernel/driver overhead)
  • System\Context Switches/sec (very high rates can indicate contention or too many threads)
  • System\Processor Queue Length (persistent queueing suggests CPU pressure)

If % Privileged Time is unusually high, it often points toward driver issues, heavy interrupt load (network/storage), or antivirus/filter drivers. That’s a case where ETW tracing (later in this article) becomes a better tool than adding dozens of counters.

Memory: focus on commit, working set, and paging signals

Memory problems can be subtle because Windows uses RAM aggressively for caching. You’re looking for evidence that the workload’s working set doesn’t fit and Windows is compensating with paging or trimming.

Useful counters include:

  • Memory\% Committed Bytes In Use (approaching high values indicates commit pressure)
  • Memory\Available MBytes (trending low indicates reduced headroom)
  • Memory\Pages/sec (sustained paging activity is a red flag)
  • Per-process: Process(*)\Working Set and Process(*)\Private Bytes (identify growth/leaks)

Interpreting these correctly requires context. A server with 4 GB RAM will naturally have low available memory under load; a server with 128 GB might also have low available if file cache is large. Commit pressure and sustained paging are the differentiators.

Disk: treat latency as the primary health signal

Disk throughput alone rarely explains slowness. Latency does.

Key counters:

  • LogicalDisk(*)\Avg. Disk sec/Read and Avg. Disk sec/Write
  • LogicalDisk(*)\Disk Reads/sec and Disk Writes/sec (IOPS context)
  • LogicalDisk(*)\Current Disk Queue Length (queueing; interpret with disk type)

On modern storage, queue length interpretation depends heavily on the underlying media and controller. For HDDs, sustained queueing and high latency are clear indicators. For SSD/SAN, queueing can be normal at high IOPS, but latency should remain stable.

Also be deliberate about which disk object you use. LogicalDisk works for volumes. PhysicalDisk can be confusing with storage spaces, SAN LUNs, or multipathing unless you know how instances map.

Network: measure utilization and errors, then drill into SMB/IIS as needed

Network monitoring often starts with throughput:

  • Network Interface(*)\Bytes Total/sec

But “the network is slow” is usually about retransmits, drops, or server-side processing. Built-in counters for errors are limited depending on driver exposure, so you often correlate:

  • Throughput + CPU (% Privileged Time, interrupts if you later trace)
  • Application-specific counters (SMB Server, IIS)

For SMB file servers, consider:

  • SMB Server Shares(*)\Avg. Data Queue Length (queueing at share level)
  • SMB Server Sessions\Active Sessions

For IIS, built-in performance objects like Web Service and W3SVC_W3WP can provide request rates and queue lengths depending on configuration.

Operationalize PerfMon: scheduling, retention, and log formats

Once you’ve validated a counter set, the biggest win is making it repeatable and low-touch.

Decide on sampling interval and retention

Sampling interval is always a tradeoff between fidelity and overhead/storage.

For most servers:

  • 15 seconds: good general baseline.
  • 5 seconds: good for short incident windows.
  • 30–60 seconds: good for long-term capacity trending.

Retention depends on how quickly you need to prove patterns. Keeping 7–14 days of baseline logs is often enough for incident correlation, while longer trending might be handled by an external system. Since this article focuses on built-in tools, you can still keep longer retention if storage allows—just be intentional about log rotation.

Use BLG for efficient logging and later analysis

BLG is efficient and can be reopened in PerfMon. You can also convert BLG to CSV if you need to process it with scripts.

To convert:

powershell
relog "C:\PerfLogs\baseline.blg" -f csv -o "C:\PerfLogs\baseline.csv"

relog is a built-in utility that’s useful when you want to normalize sampling intervals, trim time windows, or merge logs.

Centralize logs without adding third-party agents

Even with built-in tools, you can centralize logs by writing PerfMon output to a network share, as long as you manage permissions and availability. In practice, many teams write locally (to avoid dependency on the network during incidents) and then copy logs to a file share for analysis.

PowerShell remoting can also be used to trigger collections on demand during incidents, which is particularly useful when you’re responding to a performance regression after a change.

Query and trend performance counters with PowerShell

PowerShell gives you two practical capabilities: rapid ad-hoc queries (what is happening now?) and scripted capture (what happened over time?). For Windows Server estates, it also enables remote access without RDP.

Discover counters and instances

Counter names can be inconsistent across versions and roles, and instances (like per-process names) can change. Use Get-Counter -ListSet to discover what’s available:

powershell
Get-Counter -ListSet *disk* | Select-Object -ExpandProperty CounterSetName

To list counters in a set:

powershell
(Get-Counter -ListSet 'LogicalDisk').Paths | Select-Object -First 20

This discovery step saves time when you’re building a DCS for a specific role.

Remote counter queries

You can query counters on a remote server directly:

powershell
$Server = 'FS01'
Get-Counter -ComputerName $Server -Counter '\Processor(_Total)\% Processor Time'

For repeatable checks across multiple servers:

powershell
$Servers = 'APP01','APP02','DB01'
$Counter = '\Memory\% Committed Bytes In Use'

$Servers | ForEach-Object {
  $s = $_
  $v = (Get-Counter -ComputerName $s -Counter $Counter).CounterSamples.CookedValue
  [pscustomobject]@{ Server=$s; Counter=$Counter; Value=[math]::Round($v,2) }
}

When remote queries fail, it’s usually due to firewall rules, permissions, or RPC/WMI access requirements, which is one reason many teams standardize on scheduled logging locally and centralized collection later.

Export short incident captures for correlation

A common incident pattern is “capture 10 minutes of high-resolution counters while the issue is happening.” PowerShell makes that quick:

powershell
$Counters = @(
  '\Processor(_Total)\% Processor Time',
  '\Processor(_Total)\% Privileged Time',
  '\System\Context Switches/sec',
  '\Memory\Available MBytes',
  '\Memory\Pages/sec',
  '\LogicalDisk(_Total)\Avg. Disk sec/Read',
  '\LogicalDisk(_Total)\Avg. Disk sec/Write',
  '\Network Interface(*)\Bytes Total/sec'
)

Get-Counter -Counter $Counters -SampleInterval 5 -MaxSamples 120 |
  Export-Counter -Path 'C:\PerfLogs\incident-5s.csv' -FileFormat CSV

Even if you later move to WPR/WPA for deep analysis, these counters give you the “shape” of the incident so you can align trace windows and avoid capturing unnecessarily long ETW traces.

Correlate performance with Event Viewer and Reliability Monitor

Counters tell you what the system was doing. Logs tell you what the system thought happened—service restarts, driver resets, storage timeouts, update events, and application errors.

This correlation step is where many investigations become conclusive. A latency spike that aligns with storage timeout events means something very different from a latency spike that aligns with a backup job.

Event Viewer: focus on time correlation and high-signal logs

Event Viewer can be overwhelming, so treat it as a correlation tool. Start from the symptom time range you observed in PerfMon.

High-signal places to look include:

  • System log: disk, storage, NIC, driver, service control manager events.
  • Application log: application crashes, timeouts, or warnings.
  • Role-specific logs (e.g., Microsoft-Windows-SMBServer/Operational, IIS logs are separate, Hyper-V logs).

Instead of browsing manually, use filtered views and export relevant events around the incident window.

PowerShell can help you pull a targeted slice:

powershell
$Start = (Get-Date).AddHours(-2)
$End   = Get-Date

Get-WinEvent -FilterHashtable @{LogName='System'; StartTime=$Start; EndTime=$End} |
  Select-Object TimeCreated, Id, LevelDisplayName, ProviderName, Message |
  Sort-Object TimeCreated

The point is not to automate everything; it’s to quickly answer: did the OS record an error that aligns with the performance symptom?

Reliability Monitor: find regressions after updates or driver changes

Reliability Monitor (viewed via perfmon /rel) summarizes stability events—application failures, Windows failures, and hardware errors—on a timeline. It’s especially useful for performance regressions that started “sometime last week” because it visualizes changes.

If you have a server that began performing poorly after patching, Reliability Monitor can highlight:

  • Windows Updates installed
  • Driver installations
  • Application crashes or hangs

You still need PerfMon counters to quantify performance impact, but Reliability Monitor helps you form a plausible hypothesis quickly.

Build role-aware monitoring: file server, IIS, SQL, and virtualization

A generic baseline is necessary, but it won’t always be sufficient. The next step is to add role-aware counters and views that explain the workload’s behavior.

The important transition here is moving from “is the server slow?” to “which layer is slow?”—SMB, IIS request queueing, SQL waits (outside PerfMon’s scope unless you use SQL counters), or VM host contention.

File servers (SMB): measure queueing and client load

On file servers, CPU might be moderate while users still see slow file operations. The root cause can be storage latency, antivirus scanning, SMB signing/encryption overhead, or a surge in client connections.

PerfMon objects that can help include SMB Server-related counters, along with disk latency and network throughput. Use them to determine whether:

  • The server is queueing requests (server-side backlog).
  • Storage latency aligns with SMB delays.
  • Network throughput spikes align with user complaints.

You’ll often find that “slow file server” is actually “storage latency spike on the volume hosting the shares,” and the SMB counters help you prove the relationship rather than guessing.

IIS/web servers: look for request queueing and worker process pressure

For IIS, the server can be “up” but slow due to:

  • Worker process CPU saturation
  • Garbage collection pressure (for .NET apps)
  • Thread pool starvation (often visible indirectly via queueing)
  • Backend dependency latency

Use a combination of:

  • Process counters for w3wp (CPU, private bytes)
  • IIS-related counters (requests/sec, current connections, queue length depending on configuration)
  • Network and disk counters if the app is I/O heavy

A useful pattern is to correlate “requests/sec” with CPU and response latency (from your application’s perspective). Built-in tools won’t give you full APM, but they do let you prove whether the bottleneck is local resource pressure or external dependency latency.

SQL Server on Windows: separate OS pressure from database behavior

If SQL Server runs on Windows Server, OS-level monitoring is still essential. Many SQL performance complaints are caused by storage latency, memory pressure from other processes, or CPU contention on the host.

At the OS layer, focus on:

  • Disk latency on data and log volumes
  • CPU saturation and privileged time
  • Memory commit pressure and paging (paging is especially harmful for database workloads)

SQL-specific counters and DMVs are beyond the scope of “built-in Windows tools,” but the OS counters above still provide critical evidence. In mixed-use servers (not recommended, but common), Process counters for non-SQL processes can reveal a “noisy neighbor” causing contention.

Hyper-V hosts: ensure host contention isn’t starving VMs

On Hyper-V, users often complain “the VM is slow,” but the bottleneck may be on the host: CPU ready-like contention (expressed differently on Windows), storage latency, or networking.

Host-level monitoring should include:

  • CPU and context switching on the host
  • Storage latency on the volumes backing VHDX files
  • Network throughput and any driver-related errors

This is also a common place where ETW tracing becomes valuable if you suspect a driver or storage stack issue, because PerfMon counters might show symptoms without identifying the component responsible.

Real-world example: slow file server copies traced to storage latency spikes

Imagine a Windows Server file server hosting departmental shares. Users report that copying files is fast in the morning but crawls mid-afternoon. There is no obvious CPU spike, and network utilization looks moderate.

You start with Resource Monitor during the complaint window and see that System and lsass.exe aren’t doing anything abnormal, but srv2.sys-associated activity isn’t directly visible there. On the Disk tab, response time jumps from single-digit milliseconds to hundreds of milliseconds on the volume hosting the shares, and the process list shows a backup agent intermittently reading large files.

You then check your baseline PerfMon DCS logs and confirm that LogicalDisk(D:)\Avg. Disk sec/Read and Avg. Disk sec/Write spike consistently between 2 PM and 3 PM, aligning with Disk Bytes/sec bursts. Event Viewer shows no disk errors, suggesting saturation rather than failure.

At this point, you have a defensible narrative: storage latency increases when a scheduled job runs, and SMB operations slow as a consequence. The corrective action might be rescheduling the job, tuning it, or moving shares to faster storage. The key is that built-in tools let you prove the cause-and-effect chain without guessing.

Use WPR/WPA for deep root cause with ETW tracing

When PerfMon tells you “disk latency is high” or “CPU privileged time is high,” you sometimes need to know why at the kernel level. Windows Performance Recorder (WPR) and Windows Performance Analyzer (WPA) are Microsoft tools built on Event Tracing for Windows (ETW), a high-performance tracing framework built into Windows.

WPR/WPA is still “built-in” in the sense that it’s a Microsoft-provided toolset commonly available through the Windows ADK or Windows features depending on environment. Many server teams treat it as standard kit because it provides visibility that counters can’t.

Use WPR/WPA when:

  • You suspect driver/kernel overhead (high privileged time, interrupts/DPCs).
  • You need to pinpoint disk I/O sources and latency contributors.
  • You need CPU sampling to identify hot code paths.

Capture a focused WPR trace during an incident

The biggest operational mistake with ETW is capturing too much for too long. Use your counter-based monitoring to narrow the time window, then capture a focused trace.

From an elevated command prompt:

cmd
wpr -start generalprofile
rem Reproduce the issue for 60-120 seconds
wpr -stop C:\PerfLogs\incident.etl

generalprofile is a broad profile that often provides enough signal for CPU and I/O analysis. In more specialized cases, you might use other built-in WPR profiles, but the principle remains: keep it focused and time-bound.

Then analyze the ETL in WPA. You’ll typically look at:

  • CPU Usage (Sampled) to see which processes and stacks consumed CPU
  • Disk Usage graphs to see I/O by process, file, and stack
  • Networking graphs if relevant

WPA analysis is a skill on its own, but even basic views can confirm whether a backup agent, antivirus filter driver, or storage stack component is responsible for latency.

Real-world example: high CPU privileged time caused by network driver DPC load

Consider a Hyper-V host where VMs intermittently stutter. PerfMon shows % Processor Time around 60%, but % Privileged Time spikes to 40% during stutters, and context switches rise sharply. Network throughput is high but not extreme.

A short WPR trace during the stutter window reveals heavy DPC/ISR activity tied to the NIC driver path. That points you toward a driver/firmware update or offload feature interaction rather than “the CPU is too small.” Without ETW, you might keep chasing application-level explanations.

The important takeaway is the escalation path: you only reach for WPR/WPA after counters indicate the likely subsystem and you need kernel-level attribution.

Create repeatable monitoring with logman (built-in) for Data Collector Sets

While PerfMon’s GUI is fine, many administrators prefer scripting DCS creation so it’s consistent across servers. Windows includes logman.exe, which can create and manage performance counter logs.

A simple example creates a counter log named Baseline with a 15-second interval:

cmd
logman create counter Baseline -f bincirc -max 250 -c \
  "\\Processor(_Total)\\% Processor Time" \
  "\\System\\Processor Queue Length" \
  "\\Memory\\Available MBytes" \
  "\\Memory\\% Committed Bytes In Use" \
  "\\LogicalDisk(_Total)\\Avg. Disk sec\\Read" \
  "\\LogicalDisk(_Total)\\Avg. Disk sec\\Write" \
  "\\LogicalDisk(_Total)\\Current Disk Queue Length" \
  "\\Network Interface(*)\\Bytes Total\\sec" \
  -si 00:00:15 -o C:\PerfLogs\Baseline

A few notes:

A circular log (-f bincirc) caps disk usage, which is useful for always-on baselining without manual cleanup. The -max parameter controls maximum size in MB.

You can start and stop it like this:

cmd
logman start Baseline
logman stop Baseline

This approach is especially handy if you want to standardize monitoring across a fleet without relying on manual GUI setup.

Interpret common performance patterns (what to look for, and what it usually means)

Once you’ve collected data, interpretation matters more than collection. The same counter value can mean different things depending on workload and hardware.

CPU patterns: sustained saturation vs. spikes vs. single-thread limits

Sustained near-100% CPU typically correlates with throughput collapse, but spikes can be benign if the workload is bursty. If overall CPU is moderate but one core is pegged, you may have a single-thread bottleneck.

Correlate:

  • % Processor Time with Processor Queue Length (persistent queueing indicates pressure).
  • % Privileged Time with driver activity suspicion.
  • Per-process CPU in Task Manager/Resource Monitor to identify the source.

Memory patterns: commit pressure and paging that align with slowness

Treat low available memory as a clue, not a verdict. The strongest evidence for memory-caused slowness is sustained paging activity that aligns with user-perceived latency.

Correlate:

  • Pages/sec with disk latency counters. If paging rises and disk latency spikes, user-facing slowness is likely.
  • Process working sets/private bytes over time to detect growth.

Disk patterns: latency spikes, not high throughput, drive complaints

If you see high Disk Bytes/sec but stable low latency, storage is likely healthy. If you see latency spikes and queueing, you have a bottleneck.

Correlate:

  • Latency counters with the schedule (backups, AV scans, batch jobs).
  • Resource Monitor file-level activity to identify the processes.
  • System event logs for storage warnings/timeouts.

Network patterns: saturation vs. retransmits vs. server-side processing

High Bytes Total/sec might simply reflect expected load (backup window). Slowness with moderate throughput can indicate retransmits, latency, or server-side processing limitations.

Correlate:

  • Network throughput with CPU privileged time (packet processing overhead).
  • Application logs for timeouts.
  • SMB or IIS counters for request queueing.

These correlation habits keep you from making changes based on a single metric.

Real-world example: IIS app slow due to memory growth and GC pressure symptoms

Consider an IIS server hosting a .NET application. Users report that the site is responsive after an app pool recycle but degrades over several days. CPU is not consistently high, but response time gradually worsens.

You add a targeted PerfMon set alongside your baseline: Process(w3wp)\Private Bytes, Process(w3wp)\Working Set, and the standard memory counters for commit/available MB. Over 72 hours, Private Bytes grows steadily, Memory\% Committed Bytes In Use rises, and occasional Pages/sec bursts align with slow periods. Resource Monitor shows increased disk activity during those bursts.

Even without application-level profiling, you now have strong evidence of memory growth leading to pressure and paging that correlates with degraded performance. You can take that evidence to the application team, adjust recycling strategy as a mitigation, and plan deeper profiling. The key is that built-in monitoring produces a narrative that explains why “recycle fixes it” and why the fix doesn’t last.

Put it all together: a practical monitoring playbook using built-in tools

At this point you’ve seen how each tool fits. The value comes from combining them into a repeatable playbook that works during calm periods and during incidents.

Day-2 operations: keep a lightweight baseline running

Use a PerfMon DCS (GUI or logman) to log a minimal baseline counter set at 15–30 second intervals. Keep logs locally in a capped circular format if you want always-on visibility without managing retention constantly.

This baseline turns “it was slow yesterday” into something measurable. It also helps you distinguish normal peak load from abnormal contention.

Incident response: confirm, capture, correlate

When an incident occurs:

Start with Task Manager and Resource Monitor for immediate attribution (which process, which disk, which connection).

Then capture a short high-resolution PerfMon/PowerShell log (5-second sampling for 10–15 minutes) to preserve evidence.

Correlate with Event Viewer and Reliability Monitor for errors and changes.

Escalate to WPR/WPA only if counters tell you the symptom but not the component.

This is efficient because it keeps heavy tracing rare and targeted.

Built-in tools can support basic capacity planning. If you track CPU headroom, disk latency trends, and memory commit over time, you can answer questions like:

  • Are we approaching CPU saturation at peak?
  • Is storage latency increasing as the dataset grows?
  • Is memory pressure rising after application updates?

Even without an external monitoring platform, these trends can justify resizing, storage upgrades, or workload distribution changes.

Appendix-style reference: common commands you’ll reuse

The following commands tend to show up repeatedly in Windows Server performance work, especially when you’re operating remotely or automating captures.

Quick view of a counter

powershell
Get-Counter '\Processor(_Total)\% Processor Time'

Export a short capture to CSV

powershell
Get-Counter -Counter '\Memory\Available MBytes','\Memory\Pages/sec' -SampleInterval 5 -MaxSamples 120 |
  Export-Counter -Path 'C:\PerfLogs\mem-incident.csv' -FileFormat CSV

Convert BLG to CSV

powershell
relog 'C:\PerfLogs\Baseline.blg' -f csv -o 'C:\PerfLogs\Baseline.csv'

Create and start a baseline log with logman

cmd
logman create counter Baseline -f bincirc -max 250 -si 00:00:15 -o C:\PerfLogs\Baseline ^
  -c "\\Processor(_Total)\\% Processor Time" "\\Memory\\Available MBytes" "\\LogicalDisk(_Total)\\Avg. Disk sec\\Read" "\\Network Interface(*)\\Bytes Total\\sec"

logman start Baseline

Capture a short WPR trace

cmd
wpr -start generalprofile
wpr -stop C:\PerfLogs\incident.etl

Used together with the workflow described earlier, these built-in commands and tools are sufficient for most Windows Server performance monitoring and a surprising number of root-cause investigations.