How Much Memory Is Your Application Really Using?
“How much RAM is free on my board?” sounds like it should have a one-line answer. As this free linux kernel development course lecture shows, it does not — because Linux deliberately uses “free” memory for buffers and caches it can reclaim in an instant. This lecture teaches you how to read free, /proc/meminfo, and per-process memory correctly, and how to force reclaim when you need a clean baseline for testing.
What You Will Learn
- Why “free” memory reported by the kernel is not the number you actually care about
- How to read
freeoutput correctly on a current system - How the page cache and dentry/inode caches consume memory the kernel can reclaim instantly
- How to force cache reclaim with
drop_cachesfor repeatable measurements - How to check a single process’s real memory footprint with
/proc/<pid>/statusandsmaps_rollup
Prerequisites
You should be comfortable reading files under /proc and running commands as root on a target board or development VM. Nothing here requires kernel module development, but pairs well with the swap/zram and mmap lectures earlier in this chapter.
Why “Free Memory” Is A Misleading Number
Linux treats unused RAM as wasted RAM. Rather than leaving pages sitting idle, the kernel uses them for the page cache — the in-memory copy of file contents you have recently read or written — and for the dentry and inode caches that speed up filesystem lookups. All of that memory is reclaimable within microseconds the moment an application actually needs it, so it is fundamentally different from memory an application has allocated and is actively using.
Reading The Free Command Correctly
On current util-linux/procps versions, free -h gives you a clearer breakdown than the old two-line output some books still show:
$ free -h
total used free shared buff/cache available
Mem: 7.6Gi 1.2Gi 4.6Gi 45Mi 1.8Gi 6.1Gi
Swap: 2.0Gi 0B 2.0Gi
The column that matters most for “how much memory can a new application actually get” is available, not free. available is the kernel’s own estimate of memory it could hand to a new process right now, factoring in how much of buff/cache is realistically reclaimable — it already accounts for the buffers/cache split that older tooling forced you to compute by hand. A system showing 4.6 GiB “free” and 6.1 GiB “available” is healthy; a system where those two numbers are close together and small is genuinely under memory pressure.
Going Deeper With /proc/meminfo
free is a formatted summary of /proc/meminfo, and reading the file directly gives you finer detail than the command exposes:
$ cat /proc/meminfo | head -12
MemTotal: 7973120 kB
MemFree: 4823456 kB
MemAvailable: 6390212 kB
Buffers: 98304 kB
Cached: 1789132 kB
SwapCached: 0 kB
Active: 2102340 kB
Inactive: 1594820 kB
Dirty: 512 kB
Writeback: 0 kB
AnonPages: 1180032 kB
Mapped: 310220 kB
AnonPages is memory backed by no file — heaps, stacks, and anonymous mmap regions, the pages that would actually go to swap under pressure. Cached plus Buffers is what free reports as buff/cache. Dirty tells you how many cached pages have been modified and still need writing back — a large, growing Dirty value under heavy write load is worth watching on flash-backed embedded storage.
Forcing A Clean Baseline With Drop_caches
When you need a repeatable measurement — for example, benchmarking cold-start memory usage of your application — you can force the kernel to drop reclaimable caches:
# sync
# echo 3 > /proc/sys/vm/drop_caches
The value written is a bitmask: 1 frees the page cache, 2 frees dentry and inode caches, and 3 frees both. Always run sync first so dirty pages are written back before you drop them — dropping caches does not discard unwritten data, but skipping sync means you are measuring a system state you did not intend to create. drop_caches is strictly a debugging and benchmarking tool; it is never something a production system should run routinely, since it throws away work the kernel had already done to speed things up.
Measuring A Single Process
System-wide numbers do not tell you what one process is actually costing you. /proc/<pid>/status gives a quick per-process view:
$ grep -E 'Vm(RSS|Size|Swap)' /proc/$(pgrep myapp)/status
VmSize: 215480 kB
VmRSS: 18320 kB
VmSwap: 0 kB
VmSize is the total virtual address space reserved, including memory the process has mapped but never touched — it is almost always a misleadingly large number. VmRSS (resident set size) is the memory actually resident in RAM right now, and is much closer to what people mean by “how much memory is this process using.” For an even more accurate figure that accounts for memory shared between processes (like shared libraries), use the summary rollup:
$ cat /proc/$(pgrep myapp)/smaps_rollup | grep -E 'Rss|Pss'
Rss: 18320 kB
Pss: 9860 kB
Pss (proportional set size) divides shared pages by the number of processes sharing them, so summing Pss across every process on the system gives a number that actually adds up to real physical memory used — Rss alone double-counts shared libraries across every process that maps them.
Memory Metrics Compared
| Metric | Where | What it tells you |
|---|---|---|
| free | free command | System-wide unused memory not currently in use for anything |
| available | free command / MemAvailable | Realistic estimate of memory a new process could get right now |
| buff/cache | free command | Reclaimable page/dentry/inode cache — not wasted, but not “used” either |
| VmRSS | /proc/pid/status | One process’s memory actually resident in RAM |
| Pss | /proc/pid/smaps_rollup | Fair per-process share of memory, correcting for sharing |
Real-World Use Case
A common embedded scenario is chasing down which service is responsible for a slow memory creep before an out-of-memory kill. Summing Pss from smaps_rollup across all long-running services, sampled every few minutes, gives you an accurate trend line without the double-counting that plain VmRSS totals would produce — critical when several daemons share the same C library and other mapped libraries.
Common Mistakes And Troubleshooting
- Panicking over a low “free” number. Most of that memory is usually reclaimable cache — check
availablebefore concluding the system is actually short on memory. - Comparing
VmSizeacross processes. Virtual size includes reserved-but-untouched address space and can be enormous for processes that map large files or libraries; it is rarely the number you want. - Summing
VmRSSacross processes to estimate total usage. Shared libraries get counted once per process, inflating the total — usePssinstead. - Running
drop_cacheson a production system as a “fix.” It forces the kernel to redo work it had already cached, which usually makes things slower, not better.
Best Practices
- Always check
available, notfree, when judging whether a system is genuinely low on memory. - Use
Pssfromsmaps_rollupwhen you need per-process numbers that sum to something meaningful. - Only use
drop_cachesfor controlled benchmarking, always preceded bysync, never as a routine operational step. - Sample memory metrics over time rather than as a single snapshot — a slow creep in
AnonPagesor a single process’sPssis what actually reveals a leak.
Performance And Security Considerations
Reading /proc memory files is cheap enough to poll frequently for monitoring, but walking smaps/smaps_rollup for every process on a large system does add measurable overhead — sample at a reasonable interval rather than in a tight loop. From a security standpoint, /proc/<pid>/smaps and similar files can reveal a process’s memory layout to anything with read access; on multi-user or security-sensitive embedded systems, check your kernel’s hidepid mount option and process permissions rather than assuming these files are only visible to the process owner.
Summary And Key Takeaways
- “Free” memory is not the same as “memory a new process could get” — use
availableorMemAvailableinstead. - Buffers and page cache are reclaimable, not wasted, and Linux uses them deliberately.
drop_cachesforces reclaim for repeatable benchmarking, but is never a production fix.VmRSSshows one process’s resident memory;Psscorrects for memory shared between processes and is the right number to sum across a system.
Conclusion
Answering “how much memory am I actually using” correctly requires knowing which number to look at and why the kernel reports it the way it does. Once you can read free, /proc/meminfo, and per-process smaps_rollup output with real understanding instead of guessing, memory debugging on embedded Linux stops being mysterious — which is exactly the goal of this chapter in the free linux kernel development course.
Frequently Asked Questions
Why does my board show almost no free memory even when idle?
Because Linux deliberately fills unused RAM with page cache and other reclaimable caches. Check the available column instead of free to see the true picture.
Is it safe to run drop_caches on a running system?
It is safe in the sense that no data is lost (after a sync), but it forces the kernel to redo cached work, which typically hurts performance briefly. Use it only for controlled measurement, never as routine maintenance.
What is the difference between VmRSS and Pss?
VmRSS is the raw resident memory for one process, counting shared pages in full; Pss divides shared pages by how many processes map them, so summing Pss across processes gives an accurate system total.
Does a high buff/cache value mean my system needs more RAM?
Not by itself — that memory is available for reclaim on demand. Look at available and whether it stays comfortably high under real load before concluding you need more RAM.
What does the drop_caches bitmask value mean?
1 frees the page cache, 2 frees dentry and inode caches, and 3 frees both together.
How can I track down a memory leak on an embedded board?
Sample Pss from /proc/<pid>/smaps_rollup for suspect processes at regular intervals and watch for a steady upward trend rather than relying on a single snapshot.
JSON-LD FAQ Schema
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{"@type": "Question", "name": "Why does my board show almost no free memory even when idle?",
"acceptedAnswer": {"@type": "Answer", "text": "Linux fills unused RAM with reclaimable page cache; check the available column instead of free."}},
{"@type": "Question", "name": "Is it safe to run drop_caches on a running system?",
"acceptedAnswer": {"@type": "Answer", "text": "It loses no data after a sync but hurts performance briefly; use only for controlled measurement."}},
{"@type": "Question", "name": "What is the difference between VmRSS and Pss?",
"acceptedAnswer": {"@type": "Answer", "text": "VmRSS counts shared pages fully per process; Pss divides them fairly, so it sums to an accurate system total."}},
{"@type": "Question", "name": "Does a high buff/cache value mean my system needs more RAM?",
"acceptedAnswer": {"@type": "Answer", "text": "Not by itself, since that memory is reclaimable on demand; check available under real load instead."}},
{"@type": "Question", "name": "What does the drop_caches bitmask value mean?",
"acceptedAnswer": {"@type": "Answer", "text": "1 frees the page cache, 2 frees dentry/inode caches, 3 frees both."}},
{"@type": "Question", "name": "How can I track down a memory leak on an embedded board?",
"acceptedAnswer": {"@type": "Answer", "text": "Sample Pss from smaps_rollup for suspect processes over time and watch for a steady upward trend."}}
]
}
Continue The Free Linux Kernel Development Course
More hands-on Linux kernel, device driver, and embedded Linux lectures are on the way — all free, all on EmbeddedPathashala.
Browse The Full Course Next Lecture
1 Comment