IOCounters
Function Signature
func (p *Process) IOCounters() (*IOCountersStat, error)
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error)
Return Value
Returns a pointer toIOCountersStat:
type IOCountersStat struct {
ReadCount uint64 `json:"readCount"` // Number of read operations
WriteCount uint64 `json:"writeCount"` // Number of write operations
ReadBytes uint64 `json:"readBytes"` // Bytes read (all I/O)
WriteBytes uint64 `json:"writeBytes"` // Bytes written (all I/O)
DiskReadBytes uint64 `json:"diskReadBytes"` // Bytes read from disk (Linux only)
DiskWriteBytes uint64 `json:"diskWriteBytes"` // Bytes written to disk (Linux only)
}
Field Descriptions
Number of read I/O operations performed (syscalls like
read(), pread(), etc.)Number of write I/O operations performed (syscalls like
write(), pwrite(), etc.)Total bytes read from all sources including disk, network, pipes, etc. (on Linux and Windows)
Total bytes written to all destinations including disk, network, pipes, etc. (on Linux and Windows)
Bytes actually read from disk storage (Linux only, from
/proc/[pid]/io)Bytes actually written to disk storage (Linux only, from
/proc/[pid]/io)ReadBytes and WriteBytes include all I/O including cached reads/writes, while DiskReadBytes and DiskWriteBytes (Linux only) represent actual physical disk I/O.Usage Examples
Basic I/O Statistics
package main
import (
"fmt"
"github.com/shirou/gopsutil/v4/process"
)
func main() {
p, err := process.NewProcess(1234)
if err != nil {
panic(err)
}
io, err := p.IOCounters()
if err != nil {
panic(err)
}
fmt.Printf("I/O Statistics:\n")
fmt.Printf(" Read Operations: %d\n", io.ReadCount)
fmt.Printf(" Write Operations: %d\n", io.WriteCount)
fmt.Printf(" Bytes Read: %d MB\n", io.ReadBytes/1024/1024)
fmt.Printf(" Bytes Written: %d MB\n", io.WriteBytes/1024/1024)
// Linux-specific disk I/O
if io.DiskReadBytes > 0 || io.DiskWriteBytes > 0 {
fmt.Printf("\nDisk I/O (Linux):\n")
fmt.Printf(" Disk Read: %d MB\n", io.DiskReadBytes/1024/1024)
fmt.Printf(" Disk Write: %d MB\n", io.DiskWriteBytes/1024/1024)
}
}
Monitor I/O Over Time
package main
import (
"fmt"
"time"
"github.com/shirou/gopsutil/v4/process"
)
func monitorIO(pid int32) {
p, err := process.NewProcess(pid)
if err != nil {
panic(err)
}
name, _ := p.Name()
fmt.Printf("Monitoring I/O for %s (PID %d)\n", name, pid)
fmt.Println("========================================")
// Get initial values
prevIO, _ := p.IOCounters()
prevTime := time.Now()
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
currentIO, err := p.IOCounters()
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
currentTime := time.Now()
elapsed := currentTime.Sub(prevTime).Seconds()
// Calculate deltas
readDelta := currentIO.ReadBytes - prevIO.ReadBytes
writeDelta := currentIO.WriteBytes - prevIO.WriteBytes
readOpsDelta := currentIO.ReadCount - prevIO.ReadCount
writeOpsDelta := currentIO.WriteCount - prevIO.WriteCount
// Calculate rates (bytes per second)
readRate := float64(readDelta) / elapsed
writeRate := float64(writeDelta) / elapsed
fmt.Printf("[%s]\n", currentTime.Format("15:04:05"))
fmt.Printf(" Read: %8.2f KB/s (%d ops)\n",
readRate/1024, readOpsDelta)
fmt.Printf(" Write: %8.2f KB/s (%d ops)\n",
writeRate/1024, writeOpsDelta)
prevIO = currentIO
prevTime = currentTime
}
}
func main() {
monitorIO(1234)
}
I/O Intensive Process Detector
package main
import (
"fmt"
"sort"
"time"
"github.com/shirou/gopsutil/v4/process"
)
type ProcessIO struct {
PID int32
Name string
ReadRate float64
WriteRate float64
TotalRate float64
}
func findIOIntensiveProcesses(topN int) {
pids, _ := process.Pids()
// First snapshot
type snapshot struct {
io *process.IOCountersStat
time time.Time
}
snapshots := make(map[int32]snapshot)
// Take initial measurements
for _, pid := range pids {
p, err := process.NewProcess(pid)
if err != nil {
continue
}
io, err := p.IOCounters()
if err != nil {
continue
}
snapshots[pid] = snapshot{io: io, time: time.Now()}
}
// Wait for measurement interval
fmt.Println("Measuring I/O activity...")
time.Sleep(3 * time.Second)
var processes []ProcessIO
// Take second measurements and calculate rates
for pid, snap1 := range snapshots {
p, err := process.NewProcess(pid)
if err != nil {
continue
}
name, _ := p.Name()
io2, err := p.IOCounters()
if err != nil {
continue
}
elapsed := time.Since(snap1.time).Seconds()
readRate := float64(io2.ReadBytes-snap1.io.ReadBytes) / elapsed
writeRate := float64(io2.WriteBytes-snap1.io.WriteBytes) / elapsed
if readRate > 0 || writeRate > 0 {
processes = append(processes, ProcessIO{
PID: pid,
Name: name,
ReadRate: readRate,
WriteRate: writeRate,
TotalRate: readRate + writeRate,
})
}
}
// Sort by total I/O rate
sort.Slice(processes, func(i, j int) bool {
return processes[i].TotalRate > processes[j].TotalRate
})
fmt.Printf("\nTop %d I/O-intensive processes:\n\n", topN)
fmt.Printf("%-8s %-25s %15s %15s %15s\n",
"PID", "Name", "Read (KB/s)", "Write (KB/s)", "Total (KB/s)")
fmt.Println("--------------------------------------------------------------------------------")
for i := 0; i < topN && i < len(processes); i++ {
p := processes[i]
fmt.Printf("%-8d %-25s %14.2f %14.2f %14.2f\n",
p.PID,
p.Name,
p.ReadRate/1024,
p.WriteRate/1024,
p.TotalRate/1024)
}
}
func main() {
findIOIntensiveProcesses(10)
}
Database Process I/O Monitor
package main
import (
"fmt"
"time"
"github.com/shirou/gopsutil/v4/process"
)
func monitorDatabaseIO(pid int32, alertThresholdMBps float64) {
p, err := process.NewProcess(pid)
if err != nil {
panic(err)
}
name, _ := p.Name()
fmt.Printf("Monitoring database I/O: %s (PID %d)\n", name, pid)
fmt.Printf("Alert threshold: %.2f MB/s\n", alertThresholdMBps)
fmt.Println("========================================")
prevIO, _ := p.IOCounters()
prevTime := time.Now()
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
for range ticker.C {
currentIO, err := p.IOCounters()
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
currentTime := time.Now()
elapsed := currentTime.Sub(prevTime).Seconds()
// Calculate rates in MB/s
readMBps := float64(currentIO.ReadBytes-prevIO.ReadBytes) / elapsed / 1024 / 1024
writeMBps := float64(currentIO.WriteBytes-prevIO.WriteBytes) / elapsed / 1024 / 1024
totalMBps := readMBps + writeMBps
// Calculate IOPS
readIOPS := float64(currentIO.ReadCount-prevIO.ReadCount) / elapsed
writeIOPS := float64(currentIO.WriteCount-prevIO.WriteCount) / elapsed
fmt.Printf("\n[%s]\n", currentTime.Format("2006-01-02 15:04:05"))
fmt.Printf(" Throughput:\n")
fmt.Printf(" Read: %8.2f MB/s\n", readMBps)
fmt.Printf(" Write: %8.2f MB/s\n", writeMBps)
fmt.Printf(" Total: %8.2f MB/s\n", totalMBps)
fmt.Printf(" IOPS:\n")
fmt.Printf(" Read: %8.2f ops/s\n", readIOPS)
fmt.Printf(" Write: %8.2f ops/s\n", writeIOPS)
// Linux-specific: Show disk I/O vs cached I/O
if currentIO.DiskReadBytes > 0 {
diskReadMBps := float64(currentIO.DiskReadBytes-prevIO.DiskReadBytes) / elapsed / 1024 / 1024
diskWriteMBps := float64(currentIO.DiskWriteBytes-prevIO.DiskWriteBytes) / elapsed / 1024 / 1024
fmt.Printf(" Physical Disk I/O:\n")
fmt.Printf(" Read: %8.2f MB/s\n", diskReadMBps)
fmt.Printf(" Write: %8.2f MB/s\n", diskWriteMBps)
cacheReadMBps := readMBps - diskReadMBps
cacheWriteMBps := writeMBps - diskWriteMBps
if cacheReadMBps > 0 || cacheWriteMBps > 0 {
fmt.Printf(" Cached I/O:\n")
fmt.Printf(" Read: %8.2f MB/s\n", cacheReadMBps)
fmt.Printf(" Write: %8.2f MB/s\n", cacheWriteMBps)
}
}
// Alert on high I/O
if totalMBps > alertThresholdMBps {
fmt.Printf("\n⚠️ HIGH I/O ALERT: %.2f MB/s exceeds threshold of %.2f MB/s\n",
totalMBps, alertThresholdMBps)
}
prevIO = currentIO
prevTime = currentTime
}
}
func main() {
monitorDatabaseIO(1234, 50.0) // Alert if I/O exceeds 50 MB/s
}
Cumulative I/O Report
package main
import (
"fmt"
"github.com/shirou/gopsutil/v4/process"
)
func ioReport(pid int32) {
p, err := process.NewProcess(pid)
if err != nil {
panic(err)
}
name, _ := p.Name()
createTime, _ := p.CreateTime()
io, err := p.IOCounters()
if err != nil {
panic(err)
}
// Calculate process uptime
uptime := time.Since(time.Unix(0, createTime*int64(time.Millisecond)))
uptimeHours := uptime.Hours()
fmt.Printf("I/O Report for %s (PID %d)\n", name, pid)
fmt.Println("==========================================")
fmt.Printf("Process uptime: %.2f hours\n\n", uptimeHours)
fmt.Println("Cumulative I/O:")
fmt.Printf(" Read Operations: %d\n", io.ReadCount)
fmt.Printf(" Write Operations: %d\n", io.WriteCount)
fmt.Printf(" Total Operations: %d\n\n", io.ReadCount+io.WriteCount)
fmt.Printf(" Bytes Read: %d (%.2f GB)\n",
io.ReadBytes, float64(io.ReadBytes)/1024/1024/1024)
fmt.Printf(" Bytes Written: %d (%.2f GB)\n",
io.WriteBytes, float64(io.WriteBytes)/1024/1024/1024)
fmt.Printf(" Total I/O: %.2f GB\n\n",
float64(io.ReadBytes+io.WriteBytes)/1024/1024/1024)
// Average rates over process lifetime
if uptimeHours > 0 {
avgReadMBph := float64(io.ReadBytes) / uptimeHours / 1024 / 1024
avgWriteMBph := float64(io.WriteBytes) / uptimeHours / 1024 / 1024
fmt.Println("Average Rates:")
fmt.Printf(" Read: %.2f MB/hour\n", avgReadMBph)
fmt.Printf(" Write: %.2f MB/hour\n", avgWriteMBph)
}
// Average operation sizes
if io.ReadCount > 0 {
avgReadSize := float64(io.ReadBytes) / float64(io.ReadCount) / 1024
fmt.Printf("\nAverage read size: %.2f KB\n", avgReadSize)
}
if io.WriteCount > 0 {
avgWriteSize := float64(io.WriteBytes) / float64(io.WriteCount) / 1024
fmt.Printf("Average write size: %.2f KB\n", avgWriteSize)
}
}
func main() {
ioReport(1234)
}
Platform Support
- Linux
- Windows
- macOS
- BSD
Fully supported. Reads from
/proc/[pid]/io. Includes both total I/O and disk-specific I/O counters.Supported via
GetProcessIoCounters() API. DiskReadBytes and DiskWriteBytes are not available.Limited support. Uses
proc_pid_rusage(). Some counters may not be available.Limited support. Uses
kinfo_proc structure. Feature availability varies by BSD variant.On Linux, reading
/proc/[pid]/io may require elevated privileges depending on the process owner and system configuration.Understanding the Metrics
Read/Write Bytes vs Disk Read/Write Bytes
On Linux:ReadBytes/WriteBytes: All I/O including cached operationsDiskReadBytes/DiskWriteBytes: Actual physical disk I/O
cachedReads := io.ReadBytes - io.DiskReadBytes
cachedWrites := io.WriteBytes - io.DiskWriteBytes
Related Methods
CPU Usage
Monitor CPU usage
Memory Usage
Monitor memory usage
Process Info
Get process information
Overview
Back to process package overview