As others have correctly pointed out, it's hard to get a handle on actual memory used by a process, what with shared regions, and mmap'ed files and whatnot.
If you're an experimenter, you can run valgrind and massif. This may get a bit heavy for the casual user but you'll get an idea of an application's memory behavior over time. If an application malloc()'s exactly what it needs then this will give you a good representation of the real dynamic memory usage of a process. But this experiment can be "poisoned".
To complicate matters, Linux allows you to overcommit your memory. When you malloc() memory, you're stating your intent to consume memory. But allocation doesn't really happen until you write a byte into a new page of your allocated "RAM". You can prove this to yourself by writing and running a little C program like so:
// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
void *p;
sleep(5)
p = malloc(16ULL*1024*1024*1024);
printf("p = %p\n", p);
sleep(30);
return 0;
}
# Shell:
cc test.c -o test && ./test &
top -p $!
Run this on a machine with less than 16GB of RAM and, voila!, you just scored 16GB of memory! (no, not really).
Notice in top
you see "VIRT" as 16.004G but %MEM is 0.0
Run this again with valgrind:
# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30
And massif says "sum of all allocs() = 16GB". So that's not very interesting.
BUT, if you run it on a sane process:
# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30
--------------------------------------------------------------------------------
Command: cc test.c -o test
Massif arguments: (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------
KB
77.33^ :
| #:
| :@::@:#:
| :::::@@::@:#:
| @:: :::@@::@:#:
| ::::@:: :::@@::@:#:
| ::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
| :@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
0 +----------------------------------------------------------------------->Mi
0 1.140
And here we see (very empirically and with very high confidence) that the compiler allocated 77KB of heap.
Why try so hard to get just heap usage? Because all of the shared objects and text sections that a process uses (in this example, the compiler) are not terribly interesting. They're constant overhead for a process. In fact, subsequent invocations of the process almost come for "free".
Also, compare and contrast the following:
MMAP() a 1GB file. Your VMSize will be 1+GB. But you're Resident Set Size will only be the portions of the file that you caused to be paged in (by dereferencing a pointer to that region). And if you "read" the whole file then, by the time you get to the end, the kernel may have already paged out the beginnings (this is easy to do because the kernel knows exactly how/where to replace those pages if dereferenced again). In either case, neither VMSize nor RSS are a good indicator of your memory "usage". You haven't actually malloc()'ed anything.
By contrast, Malloc() and touch LOTS of memory -- until your memory gets swapped to disk. So your allocated memory now exceeds your RSS. Here, your VMSize might start to tell you something (your process owns more memory than what actually resides in your RAM). But it's still difficult to differentiate between VM that is shared pages and VM that is swapped data.
This is where valgrind/massif gets interesting. It shows you what you've intentionally allocated (regardless of the state of your pages).
htop
author to one similar question I had the other day... How to calculate memory usage from /proc/meminfo (like htop)