Linux CPU utilization
Display the current CPU utilization, as a percentage, calculated from /proc/stat
.
- Task
- Background
Most Linux kernels provide a virtual /proc
filesystem, providing an interface to various internal data structures.
One of these internal structures (/proc/stat
) includes information on the amount of time (in USER_HZ
) spent in various states. From this information, we can, with a little effort, determine the current level of CPU utilization, as a percent of time spent in any states other than idle.
To do this:
- read the first line of
/proc/stat
- discard the first word of that first line (it's always
cpu
) - sum all of the times found on that first line to get the total time
- divide the fourth column ("idle") by the total time, to get the fraction of time spent being idle
- subtract the previous fraction from 1.0 to get the time spent being not idle
- multiple by 100 to get a percentage
- read the first line of
The times in /proc/stat
are monotonically increasing, and begin at some point during the kernel's initialization (ie during boot up). So the steps above will give the total CPU utilization since boot, which may or may not be useful to some. To get a more real-time utilization, we simply repeat the steps above with some small sleep interval in between, and instead of using the absolute total and idle times, we use use the total time delta and the idle time delta to compute the utilization.
This project is based on this blog post by Paul Colby, and the Bash version comes from there.
AWK
BEGIN {
prev_total = 0
prev_idle = 0
while (getline < "/proc/stat") {
close("/proc/stat")
idle = $5
total = 0
for (i=2; i<=NF; i++)
total += $i
print (1-(idle-prev_idle)/(total-prev_total))*100"%"
prev_idle = idle
prev_total = total
system("sleep 1")
}
}
Invocation and output:
>$ awk -f cpu.awk 28.4785% 7.32323% 7.30479% 6.07595% 6.32911%
Alternatively, the output can continuously overwrite itself to remain on a single line a la the UNIX Shell version, by replacing the print
line with:
printf "\rCPU: %5.1f%% \b\b",(1-(idle-prev_idle)/(total-prev_total))*100
C
On Linux, sleep accepts seconds, on Windows, milliseconds. So if you are planning to test this on Windows and then port it to Linux .....The implementation below has been tested on a Linux machine.
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
int main(int argC,char* argV[])
{
char str[100];
const char d[2] = " ";
char* token;
int i = 0,times,lag;
long int sum = 0, idle, lastSum = 0,lastIdle = 0;
long double idleFraction;
if(argC!=3)
printf("Usage : %s <number of times /proc/stat should be polled followed by delay in seconds.>",argV[0]);
else{
times = atoi(argV[1]);
lag = atoi(argV[2]);
while(times>0){
FILE* fp = fopen("/proc/stat","r");
i = 0;
fgets(str,100,fp);
fclose(fp);
token = strtok(str,d);
sum = 0;
while(token!=NULL){
token = strtok(NULL,d);
if(token!=NULL){
sum += atoi(token);
if(i==3)
idle = atoi(token);
i++;
}
}
idleFraction = 100 - (idle-lastIdle)*100.0/(sum-lastSum);
printf("Busy for : %lf %% of the time.", idleFraction);
lastIdle = idle;
lastSum = sum;
times--;
sleep(lag);
}
}
return 0;
}
Invocation and output :
/home/aamrun/rosettaCode>./cpuStat 3 1 Busy for : 2.627333 % of the time. Busy for : 0.000000 % of the time. Busy for : 0.000000 % of the time.
C++
#include <fstream>
#include <iostream>
#include <numeric>
#include <unistd.h>
#include <vector>
std::vector<size_t> get_cpu_times() {
std::ifstream proc_stat("/proc/stat");
proc_stat.ignore(5, ' '); // Skip the 'cpu' prefix.
std::vector<size_t> times;
for (size_t time; proc_stat >> time; times.push_back(time));
return times;
}
bool get_cpu_times(size_t &idle_time, size_t &total_time) {
const std::vector<size_t> cpu_times = get_cpu_times();
if (cpu_times.size() < 4)
return false;
idle_time = cpu_times[3];
total_time = std::accumulate(cpu_times.begin(), cpu_times.end(), 0);
return true;
}
int main(int, char *[]) {
size_t previous_idle_time=0, previous_total_time=0;
for (size_t idle_time, total_time; get_cpu_times(idle_time, total_time); sleep(1)) {
const float idle_time_delta = idle_time - previous_idle_time;
const float total_time_delta = total_time - previous_total_time;
const float utilization = 100.0 * (1.0 - idle_time_delta / total_time_delta);
std::cout << utilization << '%' << std::endl;
previous_idle_time = idle_time;
previous_total_time = total_time;
}
}
- Output:
5.77731% 2.24439% 1.50754% 1.50754% 2.50627%
Qt Console Variant 1
A very basic Qt-port of the the C++ implementation above.
#include <QFile>
#include <unistd.h>
int main(int, char *[]) {
int prevIdleTime = 0, prevTotalTime = 0;
for (QFile file("/proc/stat"); file.open(QFile::ReadOnly); file.close()) {
const QList<QByteArray> times = file.readLine().simplified().split(' ').mid(1);
const int idleTime = times.at(3).toInt();
int totalTime = 0;
foreach (const QByteArray &time, times) {
totalTime += time.toInt();
}
qInfo("%5.1f%%", (1 - (1.0*idleTime-prevIdleTime) / (totalTime-prevTotalTime)) * 100.0);
prevIdleTime = idleTime;
prevTotalTime = totalTime;
sleep(1);
}
}
- Output:
31.7% 7.3% 10.3% 1.3% 4.0%
Qt Console Variant 2
An event-based Qt console implementation. Note, this version does not rely on any system-dependant headers or functions.
#include <QCoreApplication>
#include <QFile>
class CpuUsage : public QObject {
public:
CpuUsage() : prevIdleTime(0), prevTotalTime(0) { }
protected:
virtual void timerEvent(QTimerEvent *)
{
QFile file("/proc/stat");
file.open(QFile::ReadOnly);
const QList<QByteArray> times = file.readLine().simplified().split(' ').mid(1);
const int idleTime = times.at(3).toInt();
int totalTime = 0;
foreach (const QByteArray &time, times) {
totalTime += time.toInt();
}
qInfo("%5.1f%%", (1 - (1.0*idleTime-prevIdleTime) / (totalTime-prevTotalTime)) * 100.0);
prevIdleTime = idleTime;
prevTotalTime = totalTime;
}
private:
int prevIdleTime;
int prevTotalTime;
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
CpuUsage usage;
usage.startTimer(1000);
return app.exec();
}
- Output:
31.7% 4.2% 3.5% 16.2% 2.5% 4.5%
Qt GUI
A GUI version, using the Qt framework.
#include <QApplication>
#include <QFile>
#include <QProgressDialog>
class CpuUsage : public QProgressDialog {
public:
CpuUsage() : prevIdleTime(0), prevTotalTime(0)
{
connect(this, &QProgressDialog::canceled, &QApplication::quit);
setLabelText(tr("CPU utilization"));
setCancelButtonText(tr("Quit"));
startTimer(500);
}
protected:
virtual void timerEvent(QTimerEvent *)
{
QFile file("/proc/stat");
file.open(QFile::ReadOnly);
const QList<QByteArray> times = file.readLine().simplified().split(' ').mid(1);
const int idleTime = times.at(3).toInt();
int totalTime = 0;
foreach (const QByteArray &time, times) {
totalTime += time.toInt();
}
setValue((1 - (1.0*idleTime-prevIdleTime) / (totalTime-prevTotalTime)) * 100.0);
prevIdleTime = idleTime;
prevTotalTime = totalTime;
}
private:
int prevIdleTime;
int prevTotalTime;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
CpuUsage usage;
usage.show();
return app.exec();
}
- Output:
C#
var prevIdle = 0f;
var prevTotal = 0f;
while (true)
{
var cpuLine = File
.ReadAllLines("/proc/stat")
.First()
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Skip(1)
.Select(float.Parse)
.ToArray();
var idle = cpuLine[3];
var total = cpuLine.Sum();
var percent = 100.0 * (1.0 - (idle - prevIdle) / (total - prevTotal));
Console.WriteLine($"{percent:0.00}%");
prevIdle = idle;
prevTotal = total;
Thread.Sleep(1000);
}
Output:
20.88% 15.38% 8.33% 8.33% 0.00% 8.33%
Dart
#!/usr/bin/env dart
import 'dart:io';
List<int> load() {
File f = File('/proc/stat');
List<String> lines = f.readAsLinesSync();
List<int> loads = lines[0]
.substring("cpu ".length)
.split(" ")
.map((String token) => int.parse(token))
.toList();
int idle = loads[3];
int total = loads.reduce((int a, int b) => a + b);
return [idle, total];
}
void main() {
List<int> idleTotalPrev = [0, 0];
while (true) {
List<int> idleTotal = load();
int dTotal = idleTotal[0] - idleTotalPrev[0];
int dLoad = idleTotal[1] - idleTotalPrev[1];
idleTotalPrev = idleTotal;
double percent = 100.0 * (1.0 - dTotal / dLoad);
print("${percent.toStringAsFixed(2)}%");
sleep(const Duration(seconds: 1));
}
}
Output:
13.27% 1.25% 0.75% 1.37% 0.63% 0.63%
Fortran
Program CPUusage
implicit none
integer :: ios, i
integer :: oldidle, oldsum, sumtimes = 0
real :: percent = 0.
character(len = 4) lineID ! 'cpu '
integer, dimension(9) :: times = 0
write(*, *) 'CPU Usage'
write(*, *) 'Press Ctrl<C> to end'
do while (.true.)
open(unit = 7, file = '/proc/stat', status = 'old', action = 'read', iostat = ios)
if (ios /= 0) then
print *, 'Error opening /proc/stat'
stop
else
read(unit = 7, fmt = *, iostat = ios) lineID, (times(i), i = 1, 9)
close(7)
if (lineID /= 'cpu ') then
print *, 'Error reading /proc/stat'
stop
end if
sumtimes = sum(times)
percent = (1. - real((times(4) - oldidle)) / real((sumtimes - oldsum))) * 100.
write(*, fmt = '(F6.2,A2)') percent, '%'
oldidle = times(4)
oldsum = sumtimes
call sleep(1)
end if
end do
end program CPUusage
- Output:
CPU Usage Press Ctrl<C> to end 7.51 % 18.23 % 4.60 % 4.53 % 3.53 % 2.53 %
FreeBASIC
Sub Split(Byval stringToSplit As String, delimeter As Const String, result() As String)
Dim lengthOfDelimeter As Integer = Len(delimeter)
Dim indexOfDelimeter As Integer = Instr(stringToSplit, delimeter)
Dim counter As Integer = 0
While (indexOfDelimeter > 0)
Redim Preserve result(counter+1)
result(counter) = Mid(stringToSplit, 1, indexOfDelimeter - 1)
stringToSplit = Mid(stringToSplit,indexOfDelimeter + lengthOfDelimeter)
indexOfDelimeter = Instr(stringToSplit, delimeter)
counter += 1
Wend
result(counter) = stringToSplit
End Sub
Dim As Ulongint prev_total = 0, prev_idle = 0
Dim As String cpu_line, parts()
Dim As Ulongint current_total, current_idle, diff_total, diff_idle, diff_usage
Print !"CPU Monitoring (press any key to exit)...\n"
Do
' Read line from /proc/stat
Open "/proc/stat" For Input As #1
Line Input #1, cpu_line
Close #1
Split(cpu_line, " ", parts())
If (Ubound(parts) < 9) Orelse (parts(0) <> "cpu") Then
Print !"\nError: Invalid format in /proc/stat"
Exit Do
End If
current_total = 0
For i As Integer = 1 To 8
current_total += Valulng(parts(i))
Next
current_idle = Valulng(parts(4))
If prev_total > 0 Then
diff_total = current_total - prev_total
diff_idle = current_idle - prev_idle
If diff_total > 0 Then
diff_usage = ((diff_total - diff_idle) * 1000 \ diff_total + 5) \ 10
Print Using "CPU: ###%"; diff_usage
End If
End If
prev_total = current_total
prev_idle = current_idle
Sleep 1000, 1
Loop Until Inkey <> ""
Sleep
- Output:
CPU Monitoring (press any key to exit)... CPU: 90% CPU: 100% CPU: 99% CPU: 100% CPU: 99% CPU: 84% CPU: 93% CPU: 51% CPU: 84% CPU: 100%
multi-operating system version
REM Rosetta Code problem: https://rosettacode.org/wiki/Linux_CPU_utilization
REM by Jjuanhdez, 04/2025
#ifdef __FB_LINUX__
#include "crt.bi"
Function get_cpu_times(Byref idle_time As ULongInt, Byref total_time As ULongInt) As Boolean
Dim As FILE Ptr fp
Dim As ZString * 256 linea
Dim As ULongInt user, nice, sys, idle, guest, guest_nice
Dim As ULongInt iowait = 0, irq = 0, softirq = 0, steal = 0
fp = fopen("/proc/stat", "r")
If fp = 0 Then Return False
If fgets(@linea, 256, fp) = 0 Then
fclose(fp)
Return False
End If
fclose(fp)
If sscanf(@linea, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", _
@user, @nice, @sys, @idle, @iowait, @irq, @softirq, @steal, @guest, @guest_nice) < 4 Then
Return False
End If
idle_time = idle + iowait
total_time = user + nice + sys + idle + iowait + irq + softirq + steal
Return True
End Function
#ElseIf defined(__FB_WIN32__)
#include "windows.bi"
Function get_cpu_times(Byref idle_time As ULongInt, Byref total_time As ULongInt) As Boolean
Dim As FILETIME idleTime, kernelTime, userTime
If GetSystemTimes(@idleTime, @kernelTime, @userTime) = 0 Then Return False
idle_time = (CULngInt(idleTime.dwHighDateTime) Shl 32) Or CULngInt(idleTime.dwLowDateTime)
Dim As ULongInt kernel_time = (CULngInt(kernelTime.dwHighDateTime) Shl 32) Or CULngInt(kernelTime.dwLowDateTime)
Dim As ULongInt user_time = (CULngInt(userTime.dwHighDateTime) Shl 32) Or CULngInt(userTime.dwLowDateTime)
total_time = kernel_time + user_time
Return True
End Function
#ElseIf defined(__FB_FREEBSD__) Or defined(__FB_OPENBSD__) Or defined(__FB_NETBSD__)
#include "crt.bi"
' Definitions for sysctl
#define CTL_KERN 1
#define CTL_HW 6
#define KERN_CP_TIME 12
#define HW_NCPU 3
Type cp_time_t
user As ULongInt
nice As ULongInt
sys As ULongInt
interrupt As ULongInt
idle As ULongInt
End Type
Function get_cpu_times(Byref idle_time As ULongInt, Byref total_time As ULongInt) As Boolean
Dim As cp_time_t cp_time
Dim As UInteger lon = SizeOf(cp_time)
Dim As Integer mib(0 To 1)
' Configure MIB for sysctl
mib(0) = CTL_KERN
mib(1) = KERN_CP_TIME
' Getting CPU times using sysctl
If sysctl(@mib(0), 2, @cp_time, @lon, 0, 0) <> 0 Then Return False
idle_time = cp_time.idle
total_time = cp_time.user + cp_time.nice + cp_time.sys + cp_time.interrupt + cp_time.idle
Return True
End Function
#ElseIf defined(__FB_DOS__)
' In DOS, there is no direct method to obtain CPU usage
' We will use an approximation based on measuring execution time
Dim Shared As ULongInt g_last_tick_count = 0
Dim Shared As ULongInt g_busy_time = 0
Dim Shared As ULongInt g_total_time = 1
Sub BusyWork(byval duration_ms As Integer)
Dim As ULongInt start_time = GetTickCount()
Dim As ULongInt end_time = start_time + duration_ms
Dim As Double dummy = 0
While GetTickCount() < end_time
For i As Integer = 1 To 1000
dummy = dummy + Sin(i) * Cos(i)
Next
Wend
End Sub
Function get_cpu_times(Byref idle_time As ULongInt, Byref total_time As ULongInt) As Boolean
Dim As ULongInt current_tick = GetTickCount()
If g_last_tick_count = 0 Then
g_last_tick_count = current_tick
idle_time = 0
total_time = 1
Return True
End If
Dim As ULongInt elapsed = current_tick - g_last_tick_count
g_last_tick_count = current_tick
Dim As ULongInt busy_start = GetTickCount()
BusyWork(10) ' 10 ms of intensive work
Dim As ULongInt busy_elapsed = GetTickCount() - busy_start
' Estimate downtime based on how long our baseline operation took
Dim As Double load_factor = busy_elapsed / 10.0 ' 1.0 means free CPU, >1.0 means load
g_busy_time += CULngInt(elapsed * (load_factor - 1) / load_factor)
g_total_time += elapsed
' Limit counters to avoid overflow
If g_total_time > 1000000 Then
g_busy_time = g_busy_time / 2
g_total_time = g_total_time / 2
End If
idle_time = g_total_time - g_busy_time
total_time = g_total_time
Return True
End Function
Function GetTickCount() As ULongInt
Dim As ULong ticks
Asm
.intel_syntax noprefix
xor ah, ah
int 0x1A
mov [ticks], dx
mov [ticks+2], cx
End Asm
Return ticks * 55 ' 1 tick ˜ 55 ms
End Function
#endif
' Variables to store previous states
Dim As ULongInt prev_idle = 0, prev_total = 0
Dim As Integer first = 1
Do
Dim As ULongInt idle, total
If Not get_cpu_times(idle, total) Then
Print "Error getting CPU times"
Exit Do
End If
If first = 1 Then
prev_idle = idle
prev_total = total
first = 0
Else
Dim As ULongInt idle_delta = idle - prev_idle
Dim As ULongInt total_delta = total - prev_total
If total_delta > 0 Then
Dim As Double utilization = 100.0 * (1.0 - CDbl(idle_delta) / CDbl(total_delta))
Print Using "CPU: ###.#%"; utilization
Else
Print "Insufficient data to calculate"
End If
prev_idle = idle
prev_total = total
End If
Sleep 1000
Loop
Sleep
Go
package main
import (
"bufio"
"fmt"
"log"
"os"
"strconv"
"strings"
"time"
)
func main() {
fmt.Println("CPU usage % at 1 second intervals:\n")
var prevIdleTime, prevTotalTime uint64
for i := 0; i < 10; i++ {
file, err := os.Open("/proc/stat")
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(file)
scanner.Scan()
firstLine := scanner.Text()[5:] // get rid of cpu plus 2 spaces
file.Close()
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
split := strings.Fields(firstLine)
idleTime, _ := strconv.ParseUint(split[3], 10, 64)
totalTime := uint64(0)
for _, s := range split {
u, _ := strconv.ParseUint(s, 10, 64)
totalTime += u
}
if i > 0 {
deltaIdleTime := idleTime - prevIdleTime
deltaTotalTime := totalTime - prevTotalTime
cpuUsage := (1.0 - float64(deltaIdleTime)/float64(deltaTotalTime)) * 100.0
fmt.Printf("%d : %6.3f\n", i, cpuUsage)
}
prevIdleTime = idleTime
prevTotalTime = totalTime
time.Sleep(time.Second)
}
}
- Output:
Sample output:
CPU usage % at 1 second intervals: 1 : 5.025 2 : 7.035 3 : 6.030 4 : 3.941 5 : 2.538 6 : 2.010 7 : 2.020 8 : 3.015 9 : 2.000
Haskell
import Data.List ( (!!) )
splitString :: Char -> String -> [String]
splitString c [] = []
splitString c s = let ( item , rest ) = break ( == c ) s
( _ , next ) = break ( /= c ) rest
in item : splitString c next
computeUsage :: String -> Double
computeUsage s = (1.0 - ((lineElements !! 3 ) / sum times)) * 100
where
lineElements = map (fromInteger . read ) $ tail $ splitString ' ' s
times = tail lineElements
main :: IO ( )
main = do
theTimes <- fmap lines $ readFile "/proc/stat"
putStr $ show $ computeUsage $ head theTimes
putStrLn " %"
- Output:
1.6090321637810434 %
Icon and Unicon
#
# utilization.icn, percentage of running cpu time used versus idle time
#
# tectonics: unicon -s utilization.icn -x
#
procedure main()
local stats, n, total, newtotal, delta, idle, idled
stats := gather()
idle := stats[4]
total := newtotal := 0
every n := !stats do total +:= n
write("Overall utilization: ", (1 - (real(idle) / total)) * 100, "%")
idle := stats[4]
delay(100)
stats := gather()
every n := !stats do newtotal +:= n
delta := newtotal - total
idled := stats[4] - idle
write("Interval utilization: ", (1 - (real(idled) / delta)) * 100, "%")
end
procedure gather()
local f, line, stats
f := open("/proc/stat", "r") | stop("Cannot open /proc/stat")
line := read(f)
close(f)
stats := []
line ? {
tab(upto(' ')) & tab(many(' '))
while put(stats, tab(upto(' '))) do tab(many(' '))
put(stats, tab(0))
}
return stats
end
- Output:
prompt$ unicon -s utilization.icn -x Overall utilization: 4.995469613984859% Interval utilization: 10.52631578947368% prompt$ ./utilization Overall utilization: 4.994924759070784% Interval utilization: 0.0% prompt$ ./utilization Overall utilization: 4.994135168922565% Interval utilization: 4.878048780487809%
J
cputpct=:3 :0
if. 0>nc<'PREVCPUTPCT' do. PREVCPUTPCT=:0 end.
old=. PREVCPUTPCT
PREVCPUTPCT=: (1+i.8){0".}:2!:0{{)nsed '2,$d' /proc/stat}}
100*1-(3&{ % +/) PREVCPUTPCT - old
)
Example use:
cputpct''
1.76237
Notes: this gives the average non-idle time since the last time this verb was used. If for some reason /proc/stat were not updated between calls, the result would be 100 (percent), which seems appropriate.
Java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public static void main(String[] args) throws IOException {
double[] percentages = parseUtilization(procStat());
System.out.printf("%-10s %5.2f%%%n", "idle", percentages[0] * 100);
System.out.printf("%-10s %5.2f%%", "not-idle", percentages[1] * 100);
}
static String procStat() throws IOException {
File file = new File("/proc/stat");
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
return reader.readLine();
}
}
/** @return idle and not-idle percentage values */
static double[] parseUtilization(String string) {
string = string.substring(4).stripLeading();
int total = 0;
double idle = 0;
double notIdle;
int index = 0;
for (String value : string.split(" ")) {
if (index == 3)
idle = Integer.parseInt(value);
total += Integer.parseInt(value);
index++;
}
idle /= total;
notIdle = 1 - idle;
return new double[] { idle, notIdle };
}
idle 93.33% not-idle 6.67%
An alternate demonstration
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.NumberFormat;
import java.time.Duration;
import java.util.Timer;
import java.util.TimerTask;
/* Idiomatic Java
*This certainly could've been done much shorter, but I'm glad with the way it came out
* */
public class Main {
public static void main(String[] args) throws FileNotFoundException {
// this demonstrates the use of Duration class
final var period = Duration.ofSeconds(1);
new Timer().schedule(new CpuUtilizationTask(), 0, period.toMillis());
}
/* By extending the TimerTask abstract class, we're able to use the
* Timer scheduling class */
static class CpuUtilizationTask extends TimerTask {
private final String STAT_FILE_HEADER = "cpu ";
private final NumberFormat percentFormatter;
private final RandomAccessFile statPointer;
long previousIdleTime = 0, previousTotalTime = 0;
public CpuUtilizationTask() throws FileNotFoundException {
this.percentFormatter = NumberFormat.getPercentInstance();
percentFormatter.setMaximumFractionDigits(2);
var statFile = new File("/proc/stat");
/* by using the RandomAcessFile, we're able to keep an open file stream for
* as long as this object lives, making further file openings unnecessary */
this.statPointer = new RandomAccessFile(statFile, "r");
}
@Override
public void run() {
try {
var values = statPointer.readLine()
.substring(STAT_FILE_HEADER.length())
.split(" ");
/* because Java doesn't have unsigned primitive types, we have to use the boxed
* Long's parseUsigned method. It does what it says it does.
* The rest of the arithmetic can go on as normal.
* I've seen solutions reading the value as integers. They're NOT!*/
var idleTime = Long.parseUnsignedLong(values[3]);
var totalTime = 0L;
for (String value : values) {
totalTime += Long.parseUnsignedLong(value);
}
var idleTimeDelta = idleTime - previousIdleTime;
var totalTimeDelta = totalTime - previousTotalTime;
var utilization = 1 - ((double) idleTimeDelta) / totalTimeDelta;
/* Again, this is showing one more advantage of doing idiomatic Java
* we're doing locale aware percentage formatting */
System.out.println(percentFormatter.format(utilization));
previousIdleTime = idleTime;
previousTotalTime = totalTime;
// take us back to the beginning of the file, so we don't have to reopen it
statPointer.seek(0);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
}
Julia
function main()
lastidle = lasttotal = 0
while true
ln = readline("/proc/stat")
fields = parse.(Float64, split(ln)[2:end])
idle, total = fields[4], sum(fields)
Δidle, Δtotal = idle - lastidle, total - lasttotal
lastidle, lasttotal = idle, total
utilization = 100 * (1 - Δidle / Δtotal)
@printf "%5.1f%%\r" utilization
sleep(5)
end
end
main()
Kotlin
// version 1.1.3
import java.io.FileReader
import java.io.BufferedReader
fun main(args: Array<String>) {
println("CPU usage % at 1 second intervals:\n")
var prevIdleTime = 0L
var prevTotalTime = 0L
repeat(10) {
val br = BufferedReader(FileReader("/proc/stat"))
val firstLine = br.readLine().drop(5) // get rid of cpu plus 2 spaces
br.close()
val split = firstLine.split(' ')
val idleTime = split[3].toLong()
val totalTime = split.map { it.toLong() }.sum()
if (it > 0) {
val deltaIdleTime = idleTime - prevIdleTime
val deltaTotalTime = totalTime - prevTotalTime
val cpuUsage = (1.0 - deltaIdleTime.toDouble() / deltaTotalTime) * 100.0
println("$it : ${"%6.3f".format(cpuUsage)}")
}
prevIdleTime = idleTime
prevTotalTime = totalTime
Thread.sleep(1000)
}
}
Sample output:
CPU usage % at 1 second intervals: 1 : 13.043 2 : 8.491 3 : 4.478 4 : 3.553 5 : 2.500 6 : 4.975 7 : 1.015 8 : 4.040 9 : 2.525
Lua
-- No hardcoded interval, hit ENTER to create interval, b***h!
-- Helper function: splits string "s" into a table based on "separator"
local function split(s, separator)
local r = {} -- Result table
local currentSubString = s
while currentSubString ~= "" do
-- Find separator in the current substring
local currentSeparatorStartIndex, currentSeparatorEndIndex = currentSubString:find(separator, 1, true)
if not currentSeparatorStartIndex then
-- No more separators, insert the rest and break
table.insert(r, currentSubString)
break
end
-- Insert substring before separator
local currentItem = currentSubString:sub(1, currentSeparatorStartIndex-1)
table.insert(r, currentItem)
-- Update current substring to everything after separator
currentSubString = currentSubString:sub(currentSeparatorEndIndex+1)
end
return r
end
-- Helper function: sums all arguments passed to it
local function sum(...)
local r = 0
for _, v in ipairs({...}) do
r = r + v
end
return r
end
-- Variables to store previous idle and total CPU times
local lastIdle = 0
local lastTotal = 0
local fields = {} -- Table to store parsed CPU times
local data -- To hold raw data read from "/proc/stat"
-- Repeatedly read CPU usage and calculate utilisation
while true do
-- Read the first line from "/proc/stat" (overall CPU times)
data = split(io.open("/proc/stat", "r"):read("a"), "\n")[1]
-- Parse the first word and the following numbers (times) from the line
for first, times in string.gmatch(data, "([%a%d]+)%s+([%d+ ?]+)") do
-- Split the list of times and insert each one into "fields"
for _, n in ipairs(split(times, " ")) do
table.insert(fields, tonumber(n)/1) -- Convert to number
end
end
local idle = fields[4] -- The fourth field is "idle" time
local total = sum(table.unpack(fields)) -- "total" is the sum of all CPU times
-- Deltas: change in "idle" and "total" since last check
local idleDelta = idle - lastIdle
local totalDelta = total - lastTotal
-- Update last known "idle" and "total"
lastIdle, lastTotal = idle, total
-- Calculate CPU utilisation percentage
local utilisation = 100.0 * (1.0 - idleDelta / totalDelta)
-- Output CPU utilisation and wait for user to hit ENTER
io.write(string.format("%5.1f%%", utilisation).."\t|\tHit \"ENTER\" to continue")
io.read()
-- Clear "fields" for next loop
fields = {}
end
Nim
import math, sequtils, strutils
let firstLine = "/proc/stat".readLines(1)[0]
let values = firstLine.splitWhitespace()[1..^1].map(parseInt)
let totalTime = sum(values)
let idleFrac = values[3] / totalTime
let notIdlePerc = (1 - idleFrac) * 100
echo "CPU utilization = ", notIdlePerc.formatFloat(ffDecimal, precision = 1), " %"
- Output:
CPU utilization = 7.9 %
Pascal
Free Pascal
Program CPU_Utilization;
{$mode ObjFPC}
{$H+}
uses
sysutils, strutils;
const
C_INFNAME = '/proc/stat';
var
filestr: ansistring;
tfIn: TextFile;
a: TStringArray;
i, total, idle: uint32;
PrevTotal: uint32 = 0;
PrevIdle: uint32 = 0;
begin
AssignFile(tfIn, C_INFNAME);
try
while True do
begin
Reset(tfIn);
ReadLn(tfIn, filestr); // ReadLn reads a line from the file
a := filestr.Split([' ']);
total := 0;
for i := 2 to High(a) do
Inc(total, StrToInt(a[i]));
idle := StrToInt(a[5]); // there is an empty field
Writeln((1.0 - (idle - PrevIdle) / (total - PrevTotal)) * 100:4:1, '%');
PrevIdle := idle;
PrevTotal := total;
Sleep(500);
end;
finally
CloseFile(tfIn); // Close the file when done
end;
end.
- Output:
2.8% 2.0% 0.8% 1.0%
Perl
$last_total = 0;
$last_idle = 0;
while () {
@cpu = split /\s+/, `head -1 /proc/stat`;
shift @cpu;
$this_total = 0;
$this_total += $_ for @cpu;
$delta_total = $this_total - $last_total;
$this_idle = $cpu[3] - $last_idle;
$delta_idle = $this_idle - $last_idle;
$last_total = $this_total;
$last_idle = $this_idle;
printf "Utilization: %0.1f%%\n", 100 * (1 - $delta_idle / $delta_total);
sleep 1;
}
- Output:
Utilization: 38.6% Utilization: 96.1% Utilization: 83.3% ^C
Phix
--without js -- (file i/o) with javascript_semantics -- (using the following constant) sequence line = "cpu 259246 7001 60190 34250993 137517 772 0" atom last_idle = 0, last_total = 0 --while true do -- integer fn = open("/proc/stat","r") -- sequence line = trim(gets(fn)) -- close(fn) line = split(line)[2..$] for i=1 to length(line) do {{line[i]}} = scanf(line[i],"%d") end for atom idle = line[4], total = sum(line), idle_delta = idle - last_idle, total_delta = total - last_total last_idle = idle last_total = total atom utilisation = 100*(1-idle_delta/total_delta) printf(1,"%5.1f%%\n",{utilisation}) -- printf(1,"%5.1f%%\r",{utilisation}) -- sleep(1) -- if get_key()=#1B then exit end if --end while
PicoLisp
(scl 8)
(let (Idl 0 Ttl 0)
(loop
(use (L I S)
(in "/proc/stat"
(read)
(setq L (make (do 10 (link (read))))) )
(setq I (get L 4) S (sum prog L))
(prinl
(round
(*/
100.0
(-
1.0
(*/
1.0
(- I (swap 'Idl I))
(- S (swap 'Ttl S)) ) )
1.0 )
1 )
'% )
(wait 1000) ) ) )
Python
from __future__ import print_function
from time import sleep
last_idle = last_total = 0
while True:
with open('/proc/stat') as f:
fields = [float(column) for column in f.readline().strip().split()[1:]]
idle, total = fields[3], sum(fields)
idle_delta, total_delta = idle - last_idle, total - last_total
last_idle, last_total = idle, total
utilisation = 100.0 * (1.0 - idle_delta / total_delta)
print('%5.1f%%' % utilisation, end='\r')
sleep(5)
- Output:
Lines end in \r which causes old values to be overwritten by new when \r is supported otherwise successive figures appear on separate lines.
26.5% 12.4% 10.6% 49.5% 15.5% 13.8% 8.3% 11.0% 18.5% 13.9% 11.8% 35.6%
Racket
#lang racket/base
(require racket/string)
(define (get-stats) ; returns total and idle times as two values
(define line (call-with-input-file* "/proc/stat" read-line))
(define numbers (map string->number (cdr (string-split line))))
(values (apply + numbers) (list-ref numbers 3)))
(define prev-stats #f)
(define (report-cpu-utilization)
;; lazy: fixed string instead of keeping the last time
(define prompt (if prev-stats "last second" "since boot"))
(define-values [cur-total cur-idle] (get-stats))
(define prev (or prev-stats '(0 0)))
(set! prev-stats (list cur-total cur-idle))
(define total (- cur-total (car prev)))
(define idle (- cur-idle (cadr prev)))
(printf "Utilization (~a): ~a%\n" prompt
(/ (round (* 10000 (- 1 (/ idle total)))) 100.0)))
(let loop ()
(report-cpu-utilization)
(sleep 1)
(loop))
Raku
(formerly Perl 6)
my $last-total = 0;
my $last-idle = 0;
loop {
my $Δ-total = (my $this-total = [+] my @cpu = "/proc/stat".IO.lines[0].words[1..*]) - $last-total;
my $Δ-idle = (my $this-idle = @cpu[3]) - $last-idle;
$last-total = $this-total;
$last-idle = $this-idle;
print "\b" x 40, (100 * (1 - $Δ-idle / $Δ-total)).fmt("Utilization: %0.1f%% ");
sleep(1);
}
REXX
This REXX version tests to see if the /proc/stat file was updated.
It also supports the (user) option to HALT the process (by pressing Ctrl-Break).
/*REXX pgm displays current CPU utilization (as a percentage) as per file: /proc/stat */
signal on halt /*enable handling of Ctrl─Break (halt).*/
numeric digits 20 /*ensure enough decimal digits for pgm.*/
parse arg n wait iFID . /*obtain optional arguments from the CL*/
if n=='' | n="," then n= 10 /*Not specified? Then use the default.*/
if wait=='' | wait="," then wait= 1 /* " " " " " " */
if iFID=='' | iFID="," then iFID= '/proc/stat' /* " " " " " " */
prevTot = 0; prevIdle= 0 /*initialize the prevTot and prevIdle. */
do j=1 for n /*process CPU utilization N times. */
parse value linein(iFID, 1) with . $ /*read the 1st line and ignore 1st word*/
tot= 0 /*initalize TOT (total time) to zero.*/
do k=1 for min(8, words($) ) /*only process up to eight numbers in $*/
@.k= word($,k) /*assign the times to an array (@). */
tot= tot + @.k /*add all the times from the 1st line. */
end /*k*/ /*@.4 is the idle time for this cycle.*/
div= tot - prevTot /*DIV may be zero if file isn't updated*/
if div\=0 then say format(((1-(@.4-prevIdle)/div))*100,3,5)"%" /*display CPU busy.*/
prevTot= tot; prevIdle= @.4 /*set the previous TOT and prevIdle.*/
call sleep wait /*cause this pgm to sleep WAIT secs.*/
end /*j*/
/*stick a fork in it, we're all done. */
halt: /*come here when Ctrl-Break pressed.*/
Ruby
puts "Ctrl-c to exit"
loop do
str = File.open("/proc/stat").readline
ar = str.split[1..].map(&:to_f)
idle = ar[3] / ar.sum
cpu = ((1-idle)*100).round(5)
puts "CPU: #{cpu}%\r"
sleep 5
end
Standard ML
val delay = Time.fromSeconds 2
fun p100 (part, full) = (200 * part div full + 1) div 2
val read1stLine =
(fn strm => TextIO.inputLine strm before TextIO.closeIn strm) o TextIO.openIn
val getColumns = Option.map (String.tokens Char.isSpace) o read1stLine
fun cpuStat list = (List.nth (list, 3), foldl op+ 0 list)
fun printStat (list, (idle, total)) =
let
val newStat as (idle', total') = cpuStat (map (valOf o Int.fromString) list)
in
print (Int.toString (100 - p100 (idle' - idle, total' - total)) ^ "%\n");
OS.Process.sleep delay;
newStat
end
fun mainLoop prev =
case getColumns "/proc/stat" of
SOME ("cpu" :: list) => mainLoop (printStat (list, prev))
| _ => ()
val () = mainLoop (0, 0)
Tcl
This is coded a little bit awkwardly in order to correspond neatly to the task description.
proc stat fulfills the task description in two ways:
- if called normally, it returns aggregate CPU utilization since boot
- if called within a coroutine, it prints on stdout and repeats every 1s until the coroutine is terminated
A more reusable implementation might take a command as an argument to stat, and allow that command to interrupt the loop with return false or even break.
# forgive the pun!
proc stat {} {
set fd [open /proc/stat r]
set prevtotal 0
set previdle 0
while {1} {
# read the first line of /proc/stat
set line [gets $fd]
seek $fd 0
# discard the first word of that first line (it's always cpu)
set line [lrange $line 1 end]
# sum all of the times found on that first line to get the total time
set total [::tcl::mathop::+ {*}$line]
# parse each field out of line (we only need $idle)
lassign $line user nice system idle iowait irq softirq steal guest guest_nice
# update against previous measurement
incr idle -$previdle
incr total -$prevtotal
incr previdle $idle
incr prevtotal $total
# divide the fourth column ("idle") by the total time, to get the fraction of time spent being idle
set frac [expr {$idle * 1.0 / $total}]
# subtract the previous fraction from 1.0 to get the time spent being not idle
set frac [expr {1 - $frac}]
# multiply by 100 to get a percentage
set frac [expr {round($frac*100)}]
if {[info coroutine] eq ""} {
return $frac ;# if we're called outside a coroutine, return a number
} else {
puts [format CPU:%3d%% $frac] ;# else print output
yieldto after 1000 [info coroutine]
}
}
}
coroutine watchstat stat
- Output:
CPU: 10% CPU: 3% CPU: 1%
UNIX Shell
Example taken, verbatim, from Github.
#!/bin/bash
# by Paul Colby (http://colby.id.au), no rights reserved ;)
PREV_TOTAL=0
PREV_IDLE=0
while true; do
# Get the total CPU statistics, discarding the 'cpu ' prefix.
CPU=($(sed -n 's/^cpu\s//p' /proc/stat))
IDLE=${CPU[3]} # Just the idle CPU time.
# Calculate the total CPU time.
TOTAL=0
for VALUE in "${CPU[@]:0:8}"; do
TOTAL=$((TOTAL+VALUE))
done
# Calculate the CPU usage since we last checked.
DIFF_IDLE=$((IDLE-PREV_IDLE))
DIFF_TOTAL=$((TOTAL-PREV_TOTAL))
DIFF_USAGE=$(((1000*(DIFF_TOTAL-DIFF_IDLE)/DIFF_TOTAL+5)/10))
echo -en "\rCPU: $DIFF_USAGE% \b\b"
# Remember the total and idle CPU times for the next check.
PREV_TOTAL="$TOTAL"
PREV_IDLE="$IDLE"
# Wait before checking again.
sleep 1
done
- Output:
Each successive output overwrites the previous output, so there is only ever one line, but that line keeps updating in-place.
CPU: 1%
Ursa
#
# linux cpu utilization
#
# define variables to hold last idle and last total
decl int last_idle last_total
# loop indefintely
while true
# read the first line from /proc/stat
decl string line
decl file f
f.open "/proc/stat"
set line (in string f)
# get the data from the first line
decl int i
decl int<> fields
fields.clear
for (set i 2) (< i (size (split (trim line) " "))) (inc i)
append (int (split (trim line) " ")<i>) fields
end for
# get idle stat and total
decl int idle total
set idle fields<3>
set total (int (+ fields))
# set idle_delta and total_delta
decl int idle_delta total_delta
set idle_delta (int (- idle last_idle))
set total_delta (int (- total last_total))
# set last_idle and last_total
set last_idle idle
set last_total total
# set percentage utilization
decl double utilization
set utilization (* 100 (- 1 (/ idle_delta total_delta)))
# output percentage
out utilization "%\r" console
# close f, it will be reopened at the top of the loop
f.close
# sleep 2.5 seconds
sleep 2500
# clear the line of output
for (set i 0) (< i (+ (size (string utilization)) 1.0)) (inc i)
out "\b" console
end for
for (set i 0) (< i (+ (size (string utilization)) 1.0)) (inc i)
out " " console
end for
out "\r" console
end while
Wren
Wren CLI has a problem reading the special file '/proc/stat' whose size is returned as zero even though it does have content. Wren-std has the same problem allocating a buffer when using its C I/O functions but can get around this by invoking a shell command instead. The following uses the 'io' and 'timer' sub-modules.
import "io" for File
import "timer" for Timer
import "./fmt" for Fmt
var prevIdleTime = 0
var prevTotalTime = 0
System.print("CPU usage \% at 1 second intervals:\n")
for (i in 0..9) {
var line = File.head("/proc/stat", 1)[0][3..-1].trim()
var times = line.split(" ")[0..7].map { |t| Num.fromString(t) }.toList
var totalTime = times.reduce { |acc, t| acc + t }
var idleTime = times[3]
var deltaIdleTime = idleTime - prevIdleTime
var deltaTotalTime = totalTime - prevTotalTime
var cpuUsage = (1 - deltaIdleTime/deltaTotalTime) * 100
Fmt.print("$d : $6.3f", i, cpuUsage)
prevIdleTime = idleTime
prevTotalTime = totalTime
Timer.wait(1000)
}
- Output:
Sample output:
CPU usage % at 1 second intervals: 0 : 0.774 1 : 0.000 2 : 0.125 3 : 0.249 4 : 0.125 5 : 0.736 6 : 0.125 7 : 0.373 8 : 0.000 9 : 0.125
zkl
last_idle,last_total:=0,0;
while(True){
f:=File("/proc/stat"); // open each time to get fresh data
fields:=f.readln().strip().split()[1,*];
f.close();
idle, total := fields[3].toFloat(),fields.sum(0.0);
idle_delta, total_delta := idle - last_idle, total - last_total;
last_idle, last_total = idle, total;
utilisation := 100.0 * (1.0 - idle_delta / total_delta);
print("%5.1f%%\r".fmt(utilisation)); // stay on this line, overwrite old value
Atomic.sleep(5);
}
- Output:
Shown on multiple lines, in xterm output stays on one line, overwriting itself.
33.3% 1.2% 1.5% 1.1% 1.6% 1.1% 1.8% ^CCntl C noted