Home / Alt manpages / perf-iostat(1)

  • perf-iostat(1)
  • User command
  • linux

Measure PCIe I/O with perf iostat

You will finish with a repeatable way to identify the PCIe root ports on a Linux host and measure four traffic counters while a command runs. The counters are inbound read, inbound write, outbound read and outbound write, reported in megabytes.

Allow about fifteen minutes for a first check. You need the perf command from the matching kernel tools package, a shell, and hardware that exposes the PCIe I/O counters supported by this perf build. The installed reference here is linux-tools-common 6.8.0-142.142, while the wrapper selects tools for the running kernel. A different kernel or architecture can expose different support.

1. Check the installed perf tool

Start with read-only checks. They do not need elevated privileges and avoid wasting time on a command that cannot match the running kernel:

$ command -v perf
/usr/bin/perf
$ perf --version
perf version X.Y
$ dpkg-query -W -f='${Package} ${Version}\n' linux-tools-common
linux-tools-common 6.8.0-142.142

The exact perf version is host-specific. Do not treat the linux-tools-common version as proof that the kernel-specific binary is installed. On Debian and Ubuntu systems, the wrapper may tell you to install a package named for the running kernel, such as linux-tools-6.8.0-139-generic. Installing packages is an administrative change, so use your normal change process and confirm the package name for the current kernel first.

Checkpoint: continue only when perf --version returns a version rather than a missing-tool warning. If the wrapper reports that perf is not installed for this kernel, stop here and fix the package mismatch before interpreting later output.

2. List the PCIe root ports

Ask perf iostat for the ports it can monitor:

$ perf iostat list
S0-uncore_iio_0<0000:00>
S1-uncore_iio_0<0000:80>
S0-uncore_iio_1<0000:17>
S1-uncore_iio_1<0000:85>

The names and number of rows come from the machine. The address in angle brackets is the PCI domain and bus identifier used when selecting a port. Treat the output above as a shape example, not a list to paste into your own command. An empty list, an unsupported event error or a permission error means this host cannot currently provide the requested counters.

Save the exact port identifiers you want to compare. The selection syntax in the manual uses identifiers such as 0000:17; it also accepts a comma-separated list. Do not shorten an address until you have checked what your local command accepts.

3. Run a harmless measurement

The command after -- is the workload. Use a short command first, so you can confirm the measurement boundary without creating files or changing services:

$ perf iostat -- sh -c 'printf "workload-ok\n"'
workload-ok

Performance counter stats for 'system wide':

   port             Inbound Read(MB)    Inbound Write(MB)    Outbound Read(MB)   Outbound Write(MB)
0000:00                    0                    0                    0                    0

       0.001234567 seconds time elapsed

The exact counters and elapsed time vary. A short shell command may legitimately produce zeroes because it did not move meaningful data through a monitored PCIe root port. The useful checks are that the child command ran, a counter table appeared and perf exited successfully.

This is a system-wide measurement, not a per-process disk accounting report. The counters describe traffic below each monitored PCIe root port while the workload is active. They do not identify a file, process or filesystem on their own.

4. Measure selected ports

After list has given you real identifiers, restrict the table to the ports relevant to the device you are investigating:

$ perf iostat 0000:17,0000:3a -- sh -c 'printf "selected-ports-ok\n"'
selected-ports-ok

Performance counter stats for 'system wide':

   port             Inbound Read(MB)    Inbound Write(MB)    Outbound Read(MB)   Outbound Write(MB)
0000:17                    0                    0                    0                    0
0000:3a                    0                    0                    0                    0

Use the full address form returned by your host if it differs from this example. A comma joins selections; it is not a shell separator. Keep the separator inside one argument and place -- before the workload so the two parsers cannot be confused.

For a real test, replace the harmless shell command with an existing, understood workload. A storage benchmark can be useful, but it may fill a filesystem, overwrite a block device or disturb a service. Before using one, confirm the destination, free space, I/O policy and rollback plan. Never point a write test at a device containing data unless the test procedure explicitly says that it is safe.

5. Read the four columns correctly

ColumnWhat it measures
Inbound ReadI/O devices below the root port reading from host memory.
Inbound WriteI/O devices below the root port writing to host memory.
Outbound ReadThe CPU reading from I/O devices below the root port.
Outbound WriteThe CPU writing to I/O devices below the root port.

All four values are totals in megabytes for the measured command. They are directions from the PCIe root-port point of view, so "inbound" does not simply mean "application reads". Check the direction against the workload before drawing conclusions. A read from storage commonly involves device-to-memory traffic, while the CPU's requests and completions can appear in more than one column.

Compare like with like: the same port selection, command, duration and cache conditions. Run a quiet baseline before a busy test. If you need rates, record the totals and elapsed time, then calculate them consistently rather than treating the MB columns as instantaneous throughput.

6. Diagnose failures without guessing

If the command fails, capture the first error and check these boundaries in order:

  • A kernel-tools warning means the installed perf binary does not match the running kernel. Check uname -r and the package guidance before changing perf options.
  • A permission error concerns access to performance counters. Inspect the local policy, for example with sysctl kernel.perf_event_paranoid, and follow your administrator's rules. Do not lower a system security setting just to make one measurement work.
  • An unsupported event or empty port list means this hardware or build does not expose the PCIe counters expected by the command. It is not fixed by changing the workload.
  • A non-zero status from the child command belongs to that workload. Run the child alone once to separate its failure from perf's setup.

Running perf with sudo can change whether counters are accessible, but it does not add hardware support or repair a kernel-tools mismatch. Use elevation only when your local policy allows it, and remember that the measured child then starts with root privileges. Do not use a privileged shell around untrusted workload text.

Done means

  • The installed perf binary matches the running kernel well enough to execute.
  • perf iostat list returned the host's available PCIe root ports.
  • A harmless command produced a counter table without changing persistent state.
  • You can select several ports with a comma-separated list and keep the workload after --.
  • You can explain all four columns and distinguish zero traffic from an unsupported or inaccessible counter.
  • Any destructive storage workload has an explicit destination, safety check and recovery plan before it is run.