Question
How to Measure CPU and Memory Usage from Inside a C++ Process on Windows and Linux
Question
I need to determine performance metrics from inside a running application, and the code must work on both Windows and Linux.
The metrics I want to access are:
- Total virtual memory available
- Virtual memory currently used
- Virtual memory currently used by the current process
- Total RAM available
- RAM currently used
- RAM currently used by the current process
- Percentage of CPU currently used
- Percentage of CPU currently used by the current process
This seems like a standard systems-programming task, but reliable information is often scattered, incomplete, outdated, or platform-specific. What is the correct way to gather these CPU and memory statistics from within a C++ application on Windows and Linux?
Short Answer
By the end of this page, you will understand how applications can inspect system and process resource usage from inside the program itself. You will learn the difference between system-wide and process-specific metrics, how CPU usage is calculated over time, how memory figures differ between virtual memory and RAM, and how to gather this information in C++ on both Windows and Linux.
Concept
System resource monitoring from inside an application means asking the operating system for information about memory and CPU usage.
There are two big ideas here:
- System-wide metrics: how much memory or CPU the whole machine is using
- Process-specific metrics: how much memory or CPU your program is using
A beginner-friendly way to think about this is:
- RAM is physical memory currently available on the machine
- Virtual memory is the larger address space that processes can use, including swapped or mapped memory
- CPU usage is not a fixed number you can read instantly like a variable; it is usually calculated by comparing CPU time between two moments
This matters in real programming because many applications need to:
- display health or diagnostics information
- log performance data
- trigger alerts when usage is too high
- tune workloads based on current system pressure
- help developers debug memory leaks or CPU spikes
In C++, this task is platform-dependent because Windows and Linux expose this data through different APIs and files:
- Windows commonly uses Win32 APIs such as
GlobalMemoryStatusEx,GetProcessMemoryInfo, andGetSystemTimes - Linux commonly reads from
/proc, such as/proc/meminfo,/proc/stat, and
Mental Model
Imagine your computer is an office building.
- Total RAM available is the total desk space in the building.
- RAM currently used is how many desks are occupied.
- RAM used by your process is how much desk space your team is using.
- Virtual memory is like all the rooms your team has reserved on paper, even if nobody is currently sitting in them.
- CPU usage is like how busy the workers are over a period of time.
The important part is CPU usage: you cannot walk in and ask, "How busy are you right this exact instant?" You need to observe work done over a short interval.
So memory is usually a snapshot, while CPU usage is usually a rate measured over time.
Syntax and Examples
Core idea
In C++, you usually create small functions such as:
struct MemoryStats {
std::uint64_t totalPhysical;
std::uint64_t usedPhysical;
std::uint64_t processPhysical;
std::uint64_t totalVirtual;
std::uint64_t usedVirtual;
std::uint64_t processVirtual;
};
struct CpuTimes {
std::uint64_t idle;
std::uint64_t total;
};
Then you provide platform-specific implementations.
Windows example: total and used memory
#include <windows.h>
#include <iostream>
#include <cstdint>
int main() {
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
if (GlobalMemoryStatusEx(&memInfo)) {
std::uint64_t totalPhys = memInfo.ullTotalPhys;
std::uint64_t availPhys = memInfo.ullAvailPhys;
std::uint64_t usedPhys = totalPhys - availPhys;
std::cout << "Total RAM: " << totalPhys << ;
std::cout << << usedPhys << ;
}
}
Step by Step Execution
Example: computing Linux system CPU usage from /proc/stat
Consider this simplified line from /proc/stat:
cpu 100 20 30 400 10 0 0 0
These numbers are cumulative CPU time counters since boot.
A simple parser might use:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <thread>
#include <chrono>
struct CpuSnapshot {
unsigned long long user = 0;
unsigned long long nice = 0;
unsigned long long system = 0;
unsigned long long idle = ;
iowait = ;
irq = ;
softirq = ;
steal = ;
};
{
;
std::string line;
std::(file, line);
;
std::string cpuLabel;
CpuSnapshot s;
iss >> cpuLabel >> s.user >> s.nice >> s.system >> s.idle
>> s.iowait >> s.irq >> s.softirq >> s.steal;
s;
}
{
s.user + s.nice + s.system + s.idle + s.iowait + s.irq + s.softirq + s.steal;
}
{
CpuSnapshot a = ();
std::this_thread::(std::chrono::());
CpuSnapshot b = ();
totalDiff = (b) - (a);
idleDiff = b.idle - a.idle;
usage = * (totalDiff - idleDiff) / totalDiff;
std::cout << << usage << ;
}
Real World Use Cases
Monitoring dashboards
Applications often expose internal metrics so operators can see:
- current memory use
- CPU pressure
- whether one process is consuming too many resources
Background services and daemons
A service may reduce work when:
- free RAM is low
- CPU usage is high
- the current process exceeds a memory budget
Debugging and profiling
Developers log process memory and CPU usage to detect:
- memory leaks
- runaway loops
- unexpected spikes after a deployment
Desktop applications
A GUI app may show a diagnostics panel with:
- system RAM usage
- app memory usage
- app CPU percentage
Batch processing tools
A data-processing program may periodically report:
- how much RAM it is using
- whether it is saturating CPU
- whether the system is under heavy load
Autoscaling and self-throttling
Server software can make decisions based on current machine state, for example:
- reduce worker count if RAM is almost full
- delay heavy tasks if CPU is already near 100%
Real Codebase Usage
In real projects, developers usually do not scatter operating-system calls all over the codebase. Instead, they wrap resource monitoring behind a small interface.
Common pattern: platform abstraction
struct SystemStats {
std::uint64_t totalRam;
std::uint64_t usedRam;
double cpuPercent;
};
struct ProcessStats {
std::uint64_t rss;
std::uint64_t virtualSize;
double cpuPercent;
};
class ResourceMonitor {
public:
SystemStats getSystemStats();
ProcessStats getProcessStats();
};
Then you implement:
resource_monitor_windows.cppresource_monitor_linux.cpp
Guard clauses and validation
Real code checks whether the OS call succeeded before using values.
if (!GlobalMemoryStatusEx(&memInfo)) {
throw std::runtime_error("Failed to read memory status");
}
Common Mistakes
1. Treating virtual memory as the same as RAM
These are not the same.
- Virtual memory: address space reserved or mapped by a process
- RAM: physical memory actually resident in memory
A process can have large virtual memory usage without using that much RAM.
2. Expecting CPU usage from a single read
This is one of the most common mistakes.
Broken idea:
// Incorrect concept: one snapshot is not enough for CPU percentage
double cpu = readCpuCounter();
Why it is wrong:
- CPU counters are cumulative totals
- you need two samples and a time interval
3. Using the wrong Linux memory field
Beginners often use fields that do not mean what they think.
For example:
VmSizeis virtual memory sizeVmRSSis resident memoryMemFreealone is often not the best estimate of available memoryMemAvailableis usually more useful for modern Linux systems
4. Forgetting unit conversions
Linux /proc files often use kilobytes, while Windows APIs often return bytes.
Comparisons
| Concept | What it represents | Best use |
|---|---|---|
| Total RAM | Physical memory installed/usable | Machine capacity |
| Used RAM | Physical memory currently in use | System pressure |
| Process RSS | Physical memory used by your process | Real process memory footprint |
| Process virtual memory | Reserved/mapped address space | Understanding mappings or allocation patterns |
| System CPU usage | How busy the whole machine is | Load monitoring |
| Process CPU usage | How much CPU your program uses | Profiling your app |
RSS vs Virtual Memory
| Metric | Meaning | Can be misleading? |
|---|
Cheat Sheet
Quick reference
System memory
Windows
- Use
GlobalMemoryStatusEx ullTotalPhys= total RAMullAvailPhys= available RAMullTotalPageFile= total virtual memory/page file related valueullAvailPageFile= available virtual memory/page file related value
Linux
- Read
/proc/meminfo MemTotal= total RAMMemAvailable= available RAM- Used RAM ≈
MemTotal - MemAvailable
Process memory
Windows
- Use
GetProcessMemoryInfo WorkingSetSize≈ RAM used by processPagefileUsageoften used as process virtual/private usage indicator
Linux
- Read
/proc/self/status
FAQ
How do I get CPU usage of my current process in C++?
Use platform-specific APIs and compare two snapshots over time. On Windows, use GetProcessTimes. On Linux, read /proc/self/stat and compute the delta.
How do I get RAM usage of my process on Linux?
Read /proc/self/status and look for VmRSS for resident memory and VmSize for virtual memory.
Is virtual memory the same as physical memory?
No. Virtual memory is address space reserved or mapped by a process. Physical memory is actual RAM currently in use.
Why can process CPU usage be above 100%?
On multi-core systems, a process can use more than one core. Depending on how you report it, usage may exceed 100%.
What is the best memory metric for real usage?
For process memory, RSS is usually the most practical metric. For system memory, MemAvailable is often better than MemFree on Linux.
Can I do this with only the C++ standard library?
No. The C++ standard library does not provide portable APIs for system CPU and memory statistics. You need OS-specific code.
Is /proc always available on Linux?
Usually yes on standard Linux systems, but not in every environment. Some containers, restricted systems, or non-Linux Unix systems may differ.
Mini Project
Description
Build a small cross-platform C++ resource monitor that prints basic system and process memory information and demonstrates the sampling idea needed for CPU usage. This project is useful because it mirrors how real applications collect diagnostics for logs, health pages, or performance dashboards.
Goal
Create a console program that reports total RAM, used RAM, and memory used by the current process, using separate implementations for Windows and Linux.
Requirements
- Create a
MemoryStatsstruct to hold system and process memory values. - Implement one code path for Windows and one for Linux using preprocessor checks.
- On Windows, use
GlobalMemoryStatusExandGetProcessMemoryInfo. - On Linux, read
/proc/meminfoand/proc/self/status. - Print all values in bytes and also in megabytes for readability.
Keep learning
Related questions
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C printf Format Specifier for bool: How to Print Boolean Values
Learn how to print bool values in C with printf, why no %b/%B specifier exists, and the common patterns to print true/false or 0/1.
Calling C or C++ from Python: Building Python Bindings
Learn the quickest ways to call C or C++ from Python, including ctypes, C extensions, Cython, and binding tools with practical examples.