Mac maintenance
Is There an iotop for Mac? (Tracking Disk I/O on macOS)
macOS has no iotop, but you can track disk I/O with fs_usage, iotop.d, iostat, and Activity Monitor — here's how each compares and when to use them.
Your fans spin up. Activity Monitor’s CPU tab is calm. Memory pressure is fine. But the SSD light (if you had one) would be flashing. Something is hammering the disk and you want to know what — process, file, and rate.
On Linux, this is what iotop is for. On macOS, the answer is “no, but…” — there are several decent alternatives. Each has tradeoffs, and the right one depends on what you’re actually trying to figure out.
The short answer
There is no iotop package for macOS. The closest equivalents:
fs_usage— built-in, shows every filesystem syscall in real time. Loud but powerful.iotop.d— a DTrace script (sometimes installed alongside Xcode tools).iostat— shows per-device throughput, no per-process breakdown.topwith the right options.- Activity Monitor’s Disk tab — GUI, per-process I/O.
Each shows a different slice of “disk activity.” Here’s the tour.
fs_usage — the built-in firehose
sudo fs_usage
Output is a live stream of every filesystem operation:
14:32:18 stat64 /private/var/folders/... 0.000043 mdworker_shared.27842
14:32:18 read F=12 B=0x2000 0.000089 mdworker_shared.27842
14:32:18 lstat64 /Users/you/Documents/x.pdf 0.000012 Spotlight
14:32:18 open /private/var/db/... 0.000071 securityd.142
Columns: timestamp, syscall, target path, duration, process.
This is very loud — thousands of lines per second on a busy Mac. The way to use it is filtering. To watch only one process:
sudo fs_usage -w -f filesys mdworker_shared
-w makes it wider (full paths). -f filesys filters to filesystem-only events. The last argument is a process name or PID.
For only specific operations:
sudo fs_usage -w | grep -E "open|write"
To capture and analyze later:
sudo fs_usage -w -t 30 > /tmp/io.log
-t 30 runs for 30 seconds and exits. Then you can grep at leisure.
Finding “what’s writing constantly”
A common diagnostic question. fs_usage filtered to write operations:
sudo fs_usage -w -f filesys | awk '/write|pwrite/ {print $NF}' | sort | uniq -c | sort -rn | head
That counts write syscalls per process over the next few seconds. Ctrl+C when you’ve got enough samples. The top of the list is whatever’s writing the most.
A process that’s logging too much is the most common culprit. Often a third-party agent that’s writing a heartbeat to a log file every second.
fs_usage needs Full Disk Access on recent macOS to see operations from other users' processes. System Settings → Privacy & Security → Full Disk Access → add Terminal.iotop.d — DTrace-based per-process I/O
If your Mac has Xcode command-line tools, there’s a DTrace script:
sudo iotop -C
It looks like this:
PID CMD DEVICE D BYTES
12345 Spotify ??/?? R 1024
2345 Slack ??/?? W 8192
67890 fseventsd ??/?? R 524288
...
-C is “cumulative.” Without it, you get per-second deltas. R/W are read/write.
Caveat: DTrace on macOS requires SIP to be in a certain state. If you’ve kept SIP fully enabled (which you should), some DTrace functionality is restricted, and iotop may not work or may need:
sudo dtrace -n 'io:::start { @[execname] = sum(args[0]->b_bcount); } tick-1sec { printa(@); trunc(@); }'
That’s a one-liner DTrace script that does the same thing. It needs sudo and (on recent macOS) developer mode enabled to bypass SIP restrictions on DTrace.
For most users on most Macs, fs_usage is more practical because it works out of the box.
iostat — per-device throughput
iostat -w 1
Refreshes every 1 second:
disk0 disk2 cpu load average
KB/t tps MB/s KB/t tps MB/s us sy id 1m 5m 15m
16.50 5 0.08 32.00 1 0.03 3 2 95 1.42 1.38 1.31
Per-disk: average request size (KB/t), transactions per second (tps), throughput (MB/s).
This doesn’t tell you which process is doing I/O — it just confirms the disk is busy and how busy. It’s the equivalent of vmstat for disk. Useful in:
- Confirming “yes, the disk is the bottleneck” before you go process-hunting.
- Comparing disks (your internal SSD vs. an external).
- Continuous monitoring without the noise of
fs_usage.
For just a one-shot:
iostat
Without -w, it prints once and exits.
Activity Monitor’s Disk tab
The GUI version. Open Activity Monitor → Disk tab. Sort by “Bytes Written” or “Bytes Read.” For each process:
- Bytes Read / Bytes Written (total since the process started).
- Reads/sec / Writes/sec (current rate).
- Data Read / Data Written (total during this Activity Monitor session).
Pros: visual, sortable, per-process, no shell required.
Cons: the rates are 5-second averages by default (less responsive than CLI). Doesn’t show what files are being touched — only that the process is doing I/O.
For fast triage, this is the easiest. View → Update Frequency → “Very Often” makes it more reactive.
Process inspector via top
top doesn’t show I/O by default, but on macOS the man page says it can. In practice, the I/O fields (PGFLT, MAJFLT, etc.) show page-fault counts, not byte rates. They’re proxies for I/O when memory’s tight, but not what you want most of the time.
For real per-process I/O bytes, you need fs_usage or Activity Monitor.
Common scenarios
Spotlight indexing won’t stop
Symptom: mdworker_shared is constantly active, fans spinning, no obvious cause.
Diagnosis:
sudo fs_usage -w mdworker_shared | head -50
You’ll see what files it’s indexing. If it’s churning through a specific folder, that folder probably contains a lot of small files (e.g., a Node project’s node_modules, an Xcode build artifact directory).
Fix: exclude the folder from Spotlight in System Settings → Spotlight → Privacy.
Time Machine won’t quit running
Symptom: backupd hammering the SSD long after the backup should have finished.
Diagnosis:
sudo fs_usage -w backupd
Often Time Machine is “thinning” old snapshots — that’s the consolidation step that frees space when retention reaches its limit. Normal, but slow.
Or it’s stuck on a permission-denied file. Look for repeated EACCES errors in the output:
sudo fs_usage -w backupd | grep -i denied
A specific app feels slow because of disk
Open Activity Monitor → Disk tab. Look at the app’s “Bytes Written / sec” while you reproduce the slowness. If it’s dramatic, you’ve confirmed disk I/O is the cause.
For diagnosing further, fs_usage -w <appname> while doing the slow operation. You’ll see what files it’s reading and how long each takes.
Your SSD wear is climbing
This isn’t a real-time concern — it’s a long-term one. Check:
brew install smartmontools
sudo smartctl -a /dev/disk0
The “Total LBAs Written” or “Data Units Written” tells you how much has been written to the SSD over its lifetime. Modern Apple SSDs are rated for hundreds of TB written. Most users never come close.
If you’re exceeding it (developers running heavy build pipelines, content creators with terabytes of edits), the long-term fix is reducing unnecessary writes. Tools like fs_usage and Activity Monitor can identify which processes are writing the most.
A simple per-process I/O snapshot script
#!/bin/bash
# Top 10 disk-active processes over a 5-second window
sudo fs_usage -w -t 5 -f filesys 2>/dev/null | \
awk '{print $NF}' | \
awk -F. '{print $1}' | \
sort | uniq -c | sort -rn | head -10
Drop it in ~/bin/disk-active. Run it when you want a quick “what’s making noise on the disk.”
Related: monitoring SSD health long-term
A daily check of SMART data:
sudo smartctl -a /dev/disk0 | grep -E "Power_On|Wear|LBAs"
For a fleet or just persistence:
sudo smartctl -a /dev/disk0 | grep "Data Units Written" >> ~/disk-wear.log
Run it weekly via launchd. Over time you’ll see the trend.
Apple Silicon notes
Apple Silicon Macs use Apple-built NVMe SSDs with custom controllers. Standard SMART output works but some fields are vendor-specific. The “Data Units Written” field is reliable; some others vary.
fs_usage on Apple Silicon is fast — the syscall tracing is lightweight. It can introduce a small slowdown on extremely I/O-heavy workloads, but for normal monitoring it’s noticeable mostly through the volume of output.
DTrace on Apple Silicon is more restricted. Apple’s been quietly removing DTrace functionality and recommending Instruments (Xcode’s profiler) instead. For deep I/O tracing, Instruments has a “File Activity” template that’s the modern replacement for iotop.d.
When to reach for Instruments
Open Xcode → Open Developer Tool → Instruments. The “File Activity” template tracks every file open/read/write/close, with per-process attribution and timeline visualization.
Pros:
- Apple-supported, works without SIP gymnastics.
- Beautiful timeline view.
- Filterable, searchable.
- Can attach to a running process or trace a launch.
Cons:
- GUI-only.
- Requires Xcode (huge install).
- Overkill for “what’s eating the disk right now.”
For a serious investigation — say, an app that has unexplained startup delays — Instruments is the right tool. For ad-hoc diagnosis, fs_usage is faster.
The shortest answer
If you want the closest thing to iotop on macOS, run Activity Monitor’s Disk tab. Sort by “Bytes Written/sec.” That’s a per-process I/O view, refreshed live, no install required.
If you want CLI: sudo fs_usage is the firehose, filtered with grep or awk. It’s not pretty, but it’s available everywhere, and once you know how to filter it, you can answer almost any “what’s the disk doing?” question.
iostat for “is the disk busy at all,” fs_usage for “what specifically is making it busy,” Activity Monitor for “show me a list ranked by who’s writing the most.”
The Linux iotop UX doesn’t translate directly because Apple’s monitoring tooling is structured differently — they invested in DTrace and Instruments instead. Once you accept that, you’ll get the same answers, just with different tools.