The first line of /proc/stat
provides cumulative CPU time counters since system boot, divided into various states:
cpu 67891300 39035 6949171 2849641614 118251644 365498 2341854 0 0 0
The columns represent (in order):
- user: normal processes in user mode
- nice: niced processes in user mode
- system: processes in kernel mode
- idle: idle time (includes iowait on older kernels)
- iowait: waiting for I/O
- irq: servicing interrupts
- softirq: servicing softirqs
- steal: stolen time (virtualized environments)
- guest: running guest OS
- guest_nice: running niced guest
While accurate percentage calculation typically requires two samples, you can estimate current utilization with these steps:
# Sample Python implementation
def calculate_cpu_util(stat_line):
fields = [int(x) for x in stat_line.split()[1:]]
# Calculate total non-idle time
non_idle = fields[0] + fields[1] + fields[2] + fields[4] + fields[5] + fields[6]
# Calculate total time (including idle)
total = sum(fields[:7])
# Return percentage (0-100)
return (non_idle / total) * 100 if total > 0 else 0
This approach makes several assumptions:
- All CPU states are accounted for in the sum of fields
- I/O wait should be considered as non-idle time (varies by use case)
- The percentage represents utilization since system boot
For more accurate results when only one sample is available:
# Bash implementation
read -r cpu user nice system idle iowait irq softirq steal guest guest_nice <<< $(head -n1 /proc/stat)
total=$((user + nice + system + idle + iowait + irq + softirq + steal))
used=$((total - idle - iowait)) # Exclude idle and iowait
echo "CPU Usage: $((100 * used / total))%"
When implementing this in production:
- Cache the previous sample when possible
- Handle counter overflow (unlikely on modern systems)
- Consider SMP systems (per-core stats available in /proc/stat)
- Account for containerized environments (different accounting methods)
The Linux kernel exposes CPU statistics through the /proc/stat
pseudo-file, which provides a wealth of information about system resource usage. The first line represents aggregate CPU activity across all cores, with subsequent lines showing per-core statistics.
# Example /proc/stat output
cpu 67891300 39035 6949171 2849641614 118251644 365498 2341854 0
The columns represent different CPU states (in units of USER_HZ, typically 100Hz):
- user: Normal processes in user mode
- nice: Niced processes in user mode
- system: Processes in kernel mode
- idle: Idle time (includes iowait on older kernels)
- iowait: Waiting for I/O completion
- irq: Hardware interrupt servicing
- softirq: Software interrupt servicing
- steal: Time stolen by hypervisor
Here's a Python implementation to calculate CPU usage percentage from a single read of /proc/stat:
def get_cpu_utilization():
with open('/proc/stat') as f:
line = f.readline()
fields = [float(column) for column in line.strip().split()[1:]]
# Calculate total time (excluding guest and guest_nice which are included in user/nice)
total_time = sum(fields[:8])
# Calculate idle time (idle + iowait)
idle_time = fields[3] + fields[4]
# Calculate non-idle time
non_idle_time = total_time - idle_time
# Calculate percentage
utilization = (non_idle_time / total_time) * 100
return round(utilization, 2)
Several factors affect the accuracy of this approach:
- For multi-core systems, you might want to calculate per-core utilization
- The values represent time since boot, so for most use cases you'll want to sample twice with a delay
- On modern kernels, iowait is not counted as idle time
- Virtualization environments may show significant steal time
If you absolutely must calculate from a single read, you can estimate utilization by comparing against the system uptime:
import time
def estimate_cpu_utilization():
with open('/proc/stat') as f:
stat_line = f.readline()
with open('/proc/uptime') as f:
uptime_seconds = float(f.readline().split()[0])
fields = [float(col) for col in stat_line.strip().split()[1:8]]
total_jiffies = sum(fields)
jiffies_per_second = total_jiffies / uptime_seconds
idle_jiffies = fields[3] + fields[4]
utilization = 100 * (1 - (idle_jiffies / total_jiffies))
return round(utilization, 2)
For production monitoring systems, consider these optimizations:
- Cache the /proc/stat file handle if reading frequently
- Use binary parsing for better performance
- Consider using the psutil library which handles these calculations internally