{"id":4957,"date":"2026-10-02T15:01:41","date_gmt":"2026-10-02T09:31:41","guid":{"rendered":"https:\/\/cpanelfree.com\/blog\/how-to-monitor-disk-io-performance-in-linux-with-iostat-and-iotop\/"},"modified":"2026-10-02T15:01:41","modified_gmt":"2026-10-02T09:31:41","slug":"how-to-monitor-disk-io-performance-in-linux-with-iostat-and-iotop","status":"publish","type":"post","link":"https:\/\/cpanelfree.com\/blog\/how-to-monitor-disk-io-performance-in-linux-with-iostat-and-iotop\/","title":{"rendered":"How to Monitor Disk I\/O Performance in Linux with iostat and iotop"},"content":{"rendered":"<p>Uncontrolled disk latency is one of the most insidious performance killers in modern Linux infrastructure, quietly degrading database transaction throughput and choking web application worker pools before traditional CPU or memory alarms trigger. When application response times spike while overall system load averages climb, discerning whether the bottleneck stems from saturated NVMe controller queues, misbehaving background daemon flushes, or paging churn is vital for system reliability. Engineers deploying web workloads on <a href=\"https:\/\/cpanelfree.com\">CpanelFree<\/a> frequently encounter high I\/O wait states that demand precise diagnostic telemetry rather than blind hardware upgrades.<\/p>\n<p><!-- more --><\/p>\n<h2 style=\"color:#001b41;font-size:24px;margin-top:32px;font-weight:700\">Executive Summary &amp; Definitive Diagnostic Answer<\/h2>\n<div style=\"background:#f9f9f9;border-left:4px solid #001b41;padding:16px 20px;margin:20px 0;border-radius:4px;color:#333;font-size:15px;line-height:1.6\">\n  <strong style=\"color:#001b41\">Direct Answer:<\/strong> To monitor Linux disk I\/O performance effectively, use <code>iostat -xz 1<\/code> from the <code>sysstat<\/code> suite to measure block device latency (<code>r_await<\/code>, <code>w_await<\/code>), request queue depth (<code>aqu-sz<\/code>), and saturation (<code>%util<\/code>), paired with <code>iotop -aoP<\/code> to identify the exact processes, threads, and swap activity driving storage thrashing in real time.\n<\/div>\n<p>Diagnosing storage performance requires a two-tiered observability approach. Device-level tools like <code>iostat<\/code> expose hardware throughput limits, queue delays, and controller saturation across physical block devices and virtual logical volumes (LVM). However, device statistics cannot pinpoint the culprit process causing the bottleneck. Per-process observability tools like <code>iotop<\/code> leverage Linux kernel task delay accounting to reveal which processes are executing heavy sequential writes, random seeks, or high-priority synchronous flushes.<\/p>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Linux Storage Architecture: The Anatomy of an I\/O Request<\/h2>\n<p>Understanding how storage metrics correlate requires dissecting the Linux Block I\/O Layer. When an application initiates a write operation, the request cascades through multiple kernel subsystems:<\/p>\n<ol style=\"color:#444;line-height:1.8;margin:16px 0 24px 20px\">\n<li><strong>Virtual File System (VFS) &amp; Page Cache:<\/strong> Buffered writes hit RAM instantly. The kernel flags these memory pages as &#8220;dirty&#8221; and defers physical disk writes until background flush threads (<code>kworker\/flush<\/code>) sync them to persistent storage.<\/li>\n<li><strong>Block Layer &amp; Generic Block Interface:<\/strong> Asynchronous or direct I\/O requests are converted into block I\/O (<code>bio<\/code>) structures, queued, and merged to minimize head movements on HDDs or optimize parallel flash transfers on SSDs\/NVMe drives.<\/li>\n<li><strong>Multi-Queue I\/O Scheduler (blk-mq):<\/strong> Modern Linux kernels route requests through software staging queues to hardware dispatch queues using schedulers such as <code>none<\/code> (bypassing scheduling on low-latency NVMe drives), <code>mq-deadline<\/code>, or <code>bfq<\/code>.<\/li>\n<li><strong>Host Bus Adapter (HBA) \/ Device Driver:<\/strong> The controller processes command queues and writes blocks to physical flash NAND or magnetic media.<\/li>\n<\/ol>\n<blockquote class=\"wp-block-quote\" style=\"background:#f9f9f9;border-left:4px solid #001b41;padding:16px 20px;margin:24px 0\">\n<p><strong style=\"color:#001b41\">Architecture Note:<\/strong> High CPU <code>%iowait<\/code> in <code>top<\/code> or <code>vmstat<\/code> merely indicates that at least one CPU core is idle while waiting for an outstanding disk I\/O request to finish. It does not measure storage utilization or identify which disk is struggling. Always transition immediately to <code>iostat<\/code> to verify physical storage behavior.<\/p>\n<\/blockquote>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Tool Comparison Matrix: Linux Storage Observability<\/h2>\n<p>Selecting the right command depends on whether you are isolating system-wide storage controller latency or zeroing in on a runaway cron job. Below is a comparative operational matrix:<\/p>\n<figure class=\"wp-block-table is-style-regular\">\n<table style=\"width:100%;border-collapse:collapse;margin:24px 0;font-size:15px;text-align:left\">\n<thead style=\"background:#001b41;color:#ffffff\">\n<tr>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Feature \/ Metric<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Standard \/ Default<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Tuned \/ Production<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\"><strong>Observability Level<\/strong><\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Device-wide aggregate (iostat)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Combined Device + Thread PID (iostat + iotop)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\"><strong>Read\/Write Latency Threshold<\/strong><\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">&gt; 25.0 ms (HDD standard)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">&lt; 1.5 ms (Enterprise NVMe target)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\"><strong>Queue Saturation Metric<\/strong><\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Unmonitored %util (misleading on NVMe)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Little&#8217;s Law Validation (aqu-sz vs IOPS)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\"><strong>Kernel Overhead<\/strong><\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Continuous \/proc polling (~1-2% CPU)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Netlink Task Delay Accounting (&lt; 0.1% CPU)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\"><strong>Dirty Page Flushing Cadence<\/strong><\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Default vm.dirty_ratio = 20% (bursty stalls)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">vm.dirty_background_ratio = 5% (continuous smooth drain)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Deep Dive 1: Device-Level Metrics Mastery with iostat<\/h2>\n<p>The <code>iostat<\/code> utility is part of the <code>sysstat<\/code> package. When monitoring live systems, never run plain <code>iostat<\/code> without interval arguments, as the first report outputs cumulative averages since the machine last booted.<\/p>\n<p>The gold-standard command for real-time investigation is:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Install sysstat if missing\napt-get install -y sysstat || dnf install -y sysstat\n\n# Monitor extended statistics, omits inactive devices, updates every 1 second\niostat -xz 1<\/code><\/pre>\n<h3 style=\"color:#001b41;font-size:18px;margin-top:24px;font-weight:600\">Decoding the Critical iostat Columns<\/h3>\n<ul style=\"color:#444;line-height:1.8;margin:16px 0 24px 20px\">\n<li><strong><code>r\/s<\/code> and <code>w\/s<\/code>:<\/strong> Completed read and write requests per second (IOPS). High IOPS with low payload sizes indicate random access patterns (common in OLTP databases like MySQL or PostgreSQL).<\/li>\n<li><strong><code>rMB\/s<\/code> and <code>wMB\/s<\/code>:<\/strong> Total data read and written per second in megabytes. Useful for tracking sequential throughput such as database dumps, backup streaming, or video transcoding.<\/li>\n<li><strong><code>rrqm\/s<\/code> and <code>wrqm\/s<\/code>:<\/strong> Number of queued read and write requests merged per second by the block layer. High merge rates demonstrate optimal sequential operations.<\/li>\n<li><strong><code>r_await<\/code> and <code>w_await<\/code>:<\/strong> The average time (in milliseconds) for read and write requests to be served. This encompasses both queue wait time and actual device service time. On enterprise NVMe storage, <code>r_await<\/code> should remain below 1.0 ms. Values exceeding 15-20 ms signal heavy drive congestion.<\/li>\n<li><strong><code>aqu-sz<\/code> (Average Queue Size):<\/strong> The average number of requests waiting in the device queue. Under Little&#8217;s Law, Queue Size = (Throughput &times; Latency). If <code>aqu-sz<\/code> spikes while <code>r_await<\/code> rises, the storage backend cannot keep pace with request arrival rates.<\/li>\n<li><strong><code>%util<\/code>:<\/strong> The percentage of elapsed CPU time during which I\/O requests were issued to the device. <em>Warning for NVMe drives:<\/em> On legacy spinning disks, 100% meant physical head saturation. On parallel multi-queue NVMe devices capable of handling 64,000 queues simultaneously, 100% util simply means at least one request was constantly in flight, not that the drive is fully saturated. Look at <code>await<\/code> and <code>aqu-sz<\/code> instead.<\/li>\n<\/ul>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Deep Dive 2: Per-Process Triage with iotop<\/h2>\n<p>Once <code>iostat<\/code> reveals that a specific drive (e.g., <code>\/dev\/nvme0n1<\/code> or <code>\/dev\/sda<\/code>) is suffering high <code>await<\/code>, execute <code>iotop<\/code> to isolate the responsible user, process, or thread.<\/p>\n<p>Standard <code>iotop<\/code> provides an interactive curses interface, but production troubleshooting requires tailored flags:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Install iotop or high-performance iotop-c\napt-get install -y iotop-c || dnf install -y iotop\n\n# Launch in real-time mode filtering only processes actively executing I\/O\n# -o: show only active processes\n# -P: aggregate by process ID instead of individual thread tasks\n# -a: accumulate total I\/O bandwidth spent since launch\niotop -aoP<\/code><\/pre>\n<p>For capturing forensic log data inside automated monitoring jobs or background terminal multiplexers without full screen rendering, run <code>iotop<\/code> in batch mode:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Batch mode snapshot: 5 iterations, 2-second delay, timestamped\niotop -b -n 5 -d 2 -o -t -P &gt; \/var\/log\/iotop-incident-$(date +%F_%T).log<\/code><\/pre>\n<h3 style=\"color:#001b41;font-size:18px;margin-top:24px;font-weight:600\">Interpreting iotop Output Fields<\/h3>\n<ul style=\"color:#444;line-height:1.8;margin:16px 0 24px 20px\">\n<li><strong><code>DISK READ<\/code> &amp; <code>DISK WRITE<\/code>:<\/strong> Current real-time read and write throughput generated by the process.<\/li>\n<li><strong><code>SWAPIN %<\/code>:<\/strong> Percentage of time the thread spent waiting for swapped memory pages to be retrieved from disk. A high <code>SWAPIN %<\/code> indicates severe RAM starvation and memory pressure rather than application disk thrashing.<\/li>\n<li><strong><code>IO &gt; %<\/code>:<\/strong> Percentage of time the process spent blocked waiting on disk I\/O requests to complete. If a database or web server process exhibits 80-99% <code>IO &gt;<\/code>, the process is stalled waiting on persistent storage.<\/li>\n<\/ul>\n<blockquote class=\"wp-block-quote\" style=\"background:#f9f9f9;border-left:4px solid #001b41;padding:16px 20px;margin:24px 0\">\n<p><strong style=\"color:#001b41\">Architecture Note:<\/strong> In containerized Docker or Kubernetes environments, processes appear inside the host&#8217;s <code>iotop<\/code> table under their root PID namespaces. Use <code>iotop -P<\/code> alongside <code>ps -fp &lt;PID&gt;<\/code> or <code>crictl inspectp<\/code> to trace the PID directly to its target container containerID.<\/p>\n<\/blockquote>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Real Production Configuration Files<\/h2>\n<p>When high I\/O latency occurs, the root cause is often stock Linux kernel parameters configured for generic desktop computers rather than high-performance server hardware. Below are production configurations to optimize storage behavior.<\/p>\n<h3 style=\"color:#001b41;font-size:18px;margin-top:24px;font-weight:600\">1. Enterprise Virtual Memory &amp; Dirty Cache Tuning<\/h3>\n<p>By default, Linux permits dirty memory to occupy up to 20% of total RAM before forcing writeouts. On a server with 128GB of RAM, this permits over 25GB of unwritten data to accumulate, resulting in massive, multi-second flusher stalls (the dreaded &#8220;writeback pause&#8221;). Create the following sysctl drop-in to force smooth, continuous background flushing:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/etc\/sysctl.d\/99-io-performance.conf\n# Enterprise Linux Storage Optimization Configuration\n\n# Start background flusher threads when dirty memory hits 5%\nvm.dirty_background_ratio = 5\n\n# Hard limit: Block writing processes and force synchronous flushing at 10%\nvm.dirty_ratio = 10\n\n# Age (in hundredths of a second) at which dirty data must be committed (5 seconds)\nvm.dirty_expire_centisecs = 500\n\n# Interval at which pdflush\/kworker threads wake up to check dirty pages (1 second)\nvm.dirty_writeback_centisecs = 100\n\n# Retain inode\/dentry directory structures in RAM to reduce filesystem metadata I\/O\nvm.vfs_cache_pressure = 50\n\n# Prevent aggressive swapping when physical RAM is available\nvm.swappiness = 10\n\n# Protect against memory overcommit failures\nvm.overcommit_memory = 0<\/code><\/pre>\n<p>Activate these parameters immediately without rebooting:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>sysctl --system<\/code><\/pre>\n<h3 style=\"color:#001b41;font-size:18px;margin-top:24px;font-weight:600\">2. Udev Rules for Multi-Queue I\/O Schedulers<\/h3>\n<p>Ensure that modern NVMe solid-state storage uses the zero-overhead <code>none<\/code> scheduler while SATA SSDs and virtual disks use <code>mq-deadline<\/code>. Configure persistent udev rules across system boots:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/etc\/udev\/rules.d\/60-disk-scheduler.rules\n# Automated Multi-Queue Scheduler Selection\n\n# NVMe drives: disable software queuing overhead and rely on hardware controller\nACTION==\"add|change\", KERNEL==\"nvme[0-9]*\", ATTR{queue\/scheduler}=\"none\"\n\n# SATA SSDs and VirtIO block disks: use mq-deadline for balanced fairness\nACTION==\"add|change\", KERNEL==\"sd[a-z]|vd[a-z]\", ATTR{queue\/rotational}==\"0\", ATTR{queue\/scheduler}=\"mq-deadline\"\n\n# Rotational HDDs: use bfq or mq-deadline to prevent seek starvation\nACTION==\"add|change\", KERNEL==\"sd[a-z]\", ATTR{queue\/rotational}==\"1\", ATTR{queue\/scheduler}=\"bfq\"<\/code><\/pre>\n<p>Apply the udev rules immediately:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>udevadm control --reload-rules &amp;&amp; udevadm trigger --type=devices --action=change<\/code><\/pre>\n<h3 style=\"color:#001b41;font-size:18px;margin-top:24px;font-weight:600\">3. Automated Storage Latency Watchdog Systemd Service<\/h3>\n<p>Deploy a lightweight watchdog script to capture system state automatically whenever disk <code>await<\/code> latency spikes above critical operational limits:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/usr\/local\/bin\/io-latency-watchdog.sh\n#!\/bin\/bash\nset -euo pipefail\n\n# Threshold in milliseconds\nLATENCY_THRESHOLD=25.0\nLOG_FILE=\"\/var\/log\/io-bottleneck.log\"\n\n# Parse average write await across all active block devices using iostat\nMAX_AWAIT=$(iostat -xz 1 2 | awk 'NR&gt;3 &amp;&amp; $10 ~ \/^[0-9.]+\/ {if ($10 &gt; max) max=$10} END {print (max == \"\" ? 0 : max)}')\n\nif (( $(echo \"$MAX_AWAIT &gt; $LATENCY_THRESHOLD\" | bc -l) )); then\n    TIMESTAMP=$(date \"+%Y-%m-%d %H:%M:%S\")\n    echo \"[$TIMESTAMP] ALERT: High I\/O Latency Detected: ${MAX_AWAIT}ms\" &gt;&gt; \"$LOG_FILE\"\n    echo \"--- TOP DISK CONSUMING PROCESSES ---\" &gt;&gt; \"$LOG_FILE\"\n    iotop -b -n 2 -d 1 -o -P &gt;&gt; \"$LOG_FILE\"\n    echo \"-----------------------------------\" &gt;&gt; \"$LOG_FILE\"\nfi<\/code><\/pre>\n<p>Encapsulate the watchdog in a systemd service and timer pair:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/etc\/systemd\/system\/io-watchdog.service\n[Unit]\nDescription=Storage Latency Incident Watchdog\nAfter=network.target\n\n[Service]\nType=oneshot\nExecStart=\/bin\/bash \/usr\/local\/bin\/io-latency-watchdog.sh\n\n# \/etc\/systemd\/system\/io-watchdog.timer\n[Unit]\nDescription=Periodic Trigger for Storage Watchdog\n\n[Timer]\nOnBootSec=2min\nOnUnitActiveSec=60s\nAccuracySec=5s\n\n[Install]\nWantedBy=timers.target<\/code><\/pre>\n<p>Enable and start the automated monitoring timer:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>chmod +x \/usr\/local\/bin\/io-latency-watchdog.sh\nsystemctl daemon-reload\nsystemctl enable --now io-watchdog.timer<\/code><\/pre>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Diagnostic Incident Playbook: Resolving Runaway I\/O<\/h2>\n<p>When storage latency disrupts production availability, follow this ordered incident triage procedure:<\/p>\n<ol style=\"color:#444;line-height:1.8;margin:16px 0 24px 20px\">\n<li><strong>Check Overall CPU Wait State:<\/strong> Run <code>vmstat 1 5<\/code>. Observe the <code>wa<\/code> (I\/O wait) and <code>b<\/code> (blocked processes waiting on resources) columns. If <code>b &gt; 2<\/code> and <code>wa &gt; 15%<\/code>, storage latency is impacting the run queue.<\/li>\n<li><strong>Identify the Bottlenecked Block Device:<\/strong> Run <code>iostat -xz 1 5<\/code>. Inspect <code>r_await<\/code> and <code>w_await<\/code>. Identify whether reads or writes are delayed, and verify whether a single device or a RAID mirror is saturated.<\/li>\n<li><strong>Isolate Offending PIDs:<\/strong> Launch <code>iotop -aoP<\/code>. Identify whether the heavy writer is an application server, an unindexed database query scanning multi-gigabyte tables, or a background backup utility like <code>rsync<\/code> or <code>tar<\/code>.<\/li>\n<li><strong>Throttle or De-prioritize Offending Tasks:<\/strong> If an uncritical background backup or batch job is starving interactive web traffic, use the <code>ionice<\/code> command to set the I\/O scheduling class to &#8220;Best Effort&#8221; with low priority or &#8220;Idle&#8221;:\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Throttle PID 4125 to idle I\/O priority (only accesses disk when idle)\nionice -c 3 -p 4125\n\n# Alternatively, set lowest priority in best-effort class\nionice -c 2 -n 7 -p 4125<\/code><\/pre>\n<\/li>\n<li><strong>Mitigate Memory Thrashing:<\/strong> If <code>iotop<\/code> reveals high <code>SWAPIN %<\/code> for active processes, the root problem is RAM exhaustion, not physical disk speed. Immediately inspect memory using <code>free -h<\/code> and check kernel OOM logs using <code>dmesg -T | grep -E -i \"oom|killed process\"<\/code>.<\/li>\n<\/ol>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Infrastructure Considerations: When Software Tuning Reaches Physical Limits<\/h2>\n<p>System tuning, intelligent dirty page cache flushing, and process I\/O throttling can recover significant headroom on burdened servers. However, shared-tenancy virtual private servers frequently suffer from &#8220;noisy neighbors&#8221; whose unconstrained I\/O operations saturate hypervisor storage buses.<\/p>\n<p>For revenue-generating web properties, high-traffic eCommerce stores, and enterprise databases requiring predictable sub-millisecond latencies, migrating to dedicated resources or premium enterprise-grade cloud platforms is essential. For production-grade resilience, consider hosting mission-critical systems on <a href=\"https:\/\/merahost.org\" target=\"_blank\" rel=\"noopener\">MeraHost Enterprise Cloud<\/a>, where pure Enterprise NVMe arrays, LiteSpeed Web Server, and strictly isolated I\/O bandwidth prevent noisy neighbor degradation while guaranteeing transparent, predictable renewal pricing.<\/p>\n<h2 style=\"color:#001b41;font-size:22px;margin-top:32px;font-weight:700\">Frequently Asked Questions (FAQs)<\/h2>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Why does iostat show 100% %util on my NVMe SSD even when performance feels fast?<\/summary>\n<p style=\"margin-top:10px;color:#444\">The <code>%util<\/code> metric measures the percentage of time during the sampling window that the device had at least one request active. On traditional single-spindle mechanical hard drives, 100% util meant the physical read\/write head was saturated. However, modern NVMe SSDs utilize parallel multi-queue architectures supporting thousands of concurrent commands. An NVMe SSD can run at 100% %util with a queue depth of 1 while still having 95% of its overall IOPS capacity available. Instead of %util, monitor <code>r_await<\/code>, <code>w_await<\/code>, and <code>aqu-sz<\/code> to gauge true NVMe saturation.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">What is the difference between await, r_await, and w_await in iostat?<\/summary>\n<p style=\"margin-top:10px;color:#444\"><code>await<\/code> is the blended average response time (in milliseconds) for all read and write requests delivered to the device, combining both queuing delay and physical hardware service time. <code>r_await<\/code> isolates read operations, while <code>w_await<\/code> isolates write operations. This distinction is critical because database read latency directly impacts synchronous user response times, whereas write operations are often buffered asynchronously in writeback cache or write-ahead logs (WAL).<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Why is iotop failing with &#8220;CONFIG_TASK_DELAY_ACCT not enabled&#8221; in my kernel?<\/summary>\n<p style=\"margin-top:10px;color:#444\"><code>iotop<\/code> relies on the Linux kernel&#8217;s task delay accounting feature (Netlink taskstats interface) to measure per-process I\/O times without invasive overhead. If your custom kernel or virtual container environment disabled this setting at compile time, enable it dynamically if supported using <code>sysctl kernel.task_delayacct=1<\/code> or pass <code>delayacct<\/code> in the kernel bootloader line (GRUB_CMDLINE_LINUX). Alternatively, use the standalone <code>iotop-c<\/code> package which provides fallback compatibility modes.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Can I restrict disk I\/O using systemd without modifying the application code?<\/summary>\n<p style=\"margin-top:10px;color:#444\">Yes. Under systemd with cgroups v2, you can place resource limits directly inside the unit file or dynamically via <code>systemctl set-property<\/code>. Using directives like <code>IOReadBandwidthMax=\/dev\/sda 10M<\/code> and <code>IOWriteBandwidthMax=\/dev\/sda 20M<\/code>, or <code>IOWeight=100<\/code> (where default is 1000), you can programmatically prevent noisy background jobs from consuming excessive disk bandwidth.<\/p>\n<\/details>\n<div class=\"wp-block-group has-background\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:8px;padding:32px;margin:40px 0;text-align:center\">\n<h3 style=\"color:#001b41;margin-top:0;font-size:24px;font-weight:700\">Deploy Enterprise-Grade Production Infrastructure<\/h3>\n<p style=\"color:#444;font-size:16px;line-height:1.6;max-width:680px;margin:12px auto 24px auto\">Need guaranteed performance with zero price hikes? Host mission-critical workloads on <strong style=\"color:#001b41\">MeraHost<\/strong> with pure Enterprise NVMe, LiteSpeed Web Server, and Same Renewal Price, Always (starting at \u20b999\/mo).<\/p>\n<div class=\"wp-block-buttons\" style=\"display:flex;gap:16px;justify-content:center;flex-wrap:wrap\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"https:\/\/merahost.org\" style=\"background:#001b41;color:#ffffff;font-weight:700;padding:12px 28px;border-radius:4px;text-decoration:none;display:inline-block;font-size:15px\" target=\"_blank\" rel=\"noopener\">Explore MeraHost NVMe Cloud &rarr;<\/a><\/div>\n<div class=\"wp-block-button is-style-outline\"><a class=\"wp-block-button__link\" href=\"https:\/\/cpanelfree.com\" style=\"background:transparent;color:#001b41;font-weight:600;padding:12px 24px;border:2px solid #001b41;border-radius:4px;text-decoration:none;display:inline-block;font-size:15px\">Deploy Free Staging on CpanelFree<\/a><\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Diagnose storage bottlenecks and process latency in Linux using iostat and iotop with battle-tested metrics, production sysctl tuning, and triage playbooks.<\/p>\n","protected":false},"author":1,"featured_media":4956,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[217],"tags":[57,177,87,218,101],"class_list":["post-4957","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux-administration","tag-almalinux","tag-databases-performance","tag-devops","tag-linux-administration","tag-sysadmin"],"_links":{"self":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/4957","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/comments?post=4957"}],"version-history":[{"count":0,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/4957\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media\/4956"}],"wp:attachment":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media?parent=4957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/categories?post=4957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/tags?post=4957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}