Type to search 66 articles.

    Practical engineering guidance

    Windows Server storage performance: the counters that matter

    Disk queue length is the counter everyone quotes and the one that misleads most often. Latency is the number that corresponds to what users experience.

    Series: Windows Server and Azure Local

    • Windows Server
    • Performance
    • Troubleshooting

    “The server is slow” arrives without evidence, and storage is blamed more often than it is responsible. The useful response is to measure the small number of counters that distinguish a storage problem from something that merely looks like one.

    The single most common error in this area is reading queue length and concluding there is a bottleneck. On modern storage that counter means much less than it did when the guidance around it was written.

    The symptom, and what to establish first

    Before measuring anything:

    Is it constant or intermittent? Intermittent points at contention — a backup, an antivirus scan, a scheduled job, a noisy neighbour on shared storage. Constant points at a design or configuration problem.

    What changed? A workload added, a patch applied, a storage array reconfigured, a virtual machine moved. Storage performance rarely degrades spontaneously.

    Is it this server, or everything on this storage? One server on a shared array tells you a different story from all of them.

    The counters worth watching, and what each means

    Latency, first and always

    PhysicalDisk\Avg. Disk sec/Read and PhysicalDisk\Avg. Disk sec/Write.

    This is how long an I/O operation takes, in seconds, and it is the number that corresponds to what a user or an application experiences. Everything else is context for this.

    As a starting point for investigation — not as a target, and not as a service level:

    Range Interpretation
    Under 10 ms Generally fine for most workloads
    10–20 ms Worth attention; poor for a latency-sensitive database
    20–50 ms A problem for most workloads
    Over 50 ms Something is wrong

    Those bands are conventional and coarse, and they must be read against the platform. All-flash storage delivering 15 ms is underperforming badly. A spinning-disk archive volume at 20 ms may be entirely as designed. The figure only means something relative to what the storage should deliver — which is why the first question about any latency number is what the storage is.

    Throughput and operation rate, for context

    PhysicalDisk\Disk Read Bytes/sec and Disk Write Bytes/sec, with Disk Reads/sec and Disk Writes/sec.

    These tell you whether the latency is being caused by genuine load or is occurring at trivial volume. High latency at high throughput may simply mean the storage is at capacity — a provisioning answer. High latency at low throughput is a fault, and a much more interesting finding.

    Dividing bytes by operations gives the average I/O size, which is useful: a workload doing many small random operations behaves completely differently from one doing few large sequential ones, and storage is provisioned for one or the other.

    Queue length, read properly

    PhysicalDisk\Current Disk Queue Length and Avg. Disk Queue Length.

    The old rule of thumb — two per spindle — came from an era of single mechanical disks. Applied to a modern array, an SSD, a virtualised disk or a storage space spanning many devices, it is meaningless, because you do not know how many underlying devices the queue is being served by.

    A deep queue with low latency means the storage is absorbing the load, which is good. A shallow queue with high latency means each operation is slow, which is bad. Queue length alone tells you neither. Read it alongside latency or not at all.

    Idle time, as a sanity check

    PhysicalDisk\% Idle Time is more reliable than % Disk Time, which can exceed 100 per cent on multi-device storage and confuses people accordingly. Low idle time with acceptable latency is a busy, healthy system.

    Split I/O, occasionally

    PhysicalDisk\Split IO/sec indicates operations being broken into multiple requests, often from fragmentation or a misaligned workload. Worth checking when latency is high and nothing else explains it.

    Collecting the evidence

    For a quick look at what is happening now:

    Get-Counter -Counter @(
        '\PhysicalDisk(*)\Avg. Disk sec/Read',
        '\PhysicalDisk(*)\Avg. Disk sec/Write',
        '\PhysicalDisk(*)\Disk Reads/sec',
        '\PhysicalDisk(*)\Disk Writes/sec',
        '\PhysicalDisk(*)\Current Disk Queue Length',
        '\PhysicalDisk(*)\% Idle Time'
    ) -SampleInterval 5 -MaxSamples 12 |
        ForEach-Object { $_.CounterSamples } |
        Where-Object { $_.InstanceName -ne '_total' -and $_.CookedValue -gt 0 } |
        Select-Object Timestamp, Path, CookedValue

    For an intermittent problem, a spot sample is close to useless. Capture over a period that includes the slow window:

    # Collect for a period, to a file, for later analysis.
    $counters = @(
        '\PhysicalDisk(*)\Avg. Disk sec/Read',
        '\PhysicalDisk(*)\Avg. Disk sec/Write',
        '\PhysicalDisk(*)\Disk Bytes/sec',
        '\PhysicalDisk(*)\Current Disk Queue Length'
    )
    
    Get-Counter -Counter $counters -SampleInterval 15 -MaxSamples 240 |
        Export-Counter -Path 'C:\Temp\disk-perf.blg' -FileFormat BLG

    An hour at fifteen-second intervals is a reasonable starting capture. For a problem that happens once a day, use a data collector set that runs continuously — the evidence you do not have when it recurs is the evidence you needed.

    To connect latency to a specific process, the Storage tab in Resource Monitor gives per-file and per-process I/O with response times, which is frequently the fastest way to identify what is actually generating the load.

    Interpreting what you find

    High latency, high throughput. The storage is doing as much as it can. This is a capacity conversation: more or faster storage, or less demand. Check first whether the demand is legitimate — a misconfigured backup window or an indexing job can look like genuine load.

    High latency, low throughput. A fault. Check the storage path: a failing drive, a degraded array, a bad cable or HBA, a multipath configuration that has lost a path. On a Storage Spaces Direct cluster, check whether a repair job is running, using the sequence in Storage Spaces Direct: what actually breaks.

    Latency spikes at intervals. Correlate against scheduled work. Backups, antivirus scans, database maintenance, replication and patching are the usual causes, and the fix is scheduling rather than storage.

    Write latency much worse than read. Often a cache issue — a write cache disabled, a battery-backed cache in a degraded state, or a storage tier that has filled. A controller cache that has dropped to write-through because its battery failed produces exactly this and is easy to miss.

    One virtual machine slow, others fine, same storage. Look at the virtual disk type, any configured limits, and the queue depth at the virtual layer before looking at the physical storage.

    Resolution and validation

    The fix follows the finding, and there are only a few categories: reschedule contending work, repair the degraded path, provision more capability, or reduce the demand.

    Whatever you change, measure again under the same conditions. The most common mistake in performance work is changing something during a quiet period and declaring success. Capture during the same window, with the same counters, and compare like with like.

    Keep the before-and-after captures. When the problem recurs in six months, they are what tell you whether it is the same problem.

    Operations

    Baseline while things are healthy. A capture from a period when nobody was complaining is the most valuable artefact you can have, and nobody ever has one. It takes an hour to produce.

    Alert on latency, not on queue length or disk busy. Latency is the counter that corresponds to user experience.

    Record what the storage is supposed to deliver. The vendor’s or platform’s expected latency and throughput figures, written down alongside the baseline, are what turn a measured number into a judgement.

    Verification and limits

    The counter names and their meanings, the unreliability of % Disk Time on multi-device storage, and the Get-Counter and Export-Counter usage were checked against current Microsoft documentation on 20 September 2026. The latency bands are conventional rules of thumb for triage, not Microsoft-published thresholds, and the interpretation guidance is my own practice.

    No measurements were taken for this article. The commands are read-only and safe, though continuous collection consumes disk space for the output file. Treat the latency table as a prompt to investigate rather than as a target — acceptable latency depends entirely on the storage platform and the workload, and applying a generic threshold to an unfamiliar system produces false conclusions in both directions.

    References