70 lines
2.4 KiB
Markdown
70 lines
2.4 KiB
Markdown
|
<i>Disclaimer: I'm trying to learn this stuff. Now a year later, I think
|
||
|
I got some terminology wrong. The process address space is not one, but
|
||
|
many pages. How many depends on the page size.</i>
|
||
|
|
||
|
# Memory management, virtual and residential memory
|
||
|
|
||
|
Memory management is a complex topic and most can be left for the kernel
|
||
|
to handle. But having a fundamental idea about where memory is
|
||
|
allocated greatly helps in understanding top(1) and the memory footprint
|
||
|
of applications.
|
||
|
|
||
|
## Process memory address space (page)
|
||
|
|
||
|
When a process starts up, the kernel assigns it a so called memory page.
|
||
|
The page size depends on the architecture. On amd64 it's 2^64 - 1 bytes.
|
||
|
|
||
|
Every memory allocation this process performs, returns a pointer to some
|
||
|
place within this page. Forcing a pointer outside this page, will cause
|
||
|
a SEGFAULT.
|
||
|
|
||
|
<pre>
|
||
|
char *w = 1; // segfault
|
||
|
char *w = malloc(12); // returns pointer within page
|
||
|
</pre>
|
||
|
|
||
|
# Memory allocation (virtual memory)
|
||
|
|
||
|
Let's say we allocatate 2G of memory:
|
||
|
|
||
|
<pre>
|
||
|
char *m = malloc(2*1073741824); // 2*1G in bytes
|
||
|
</pre>
|
||
|
|
||
|
This will grab 2G of consecutive address space within the process memory.
|
||
|
At this point, the memory is likely available but not guaranteed. The
|
||
|
allocation shows up in top(1) as "SIZE" or on linux as "VIRT"ual memory.
|
||
|
This memory is not actually used. So nothing has been written to the
|
||
|
physical RAM chip in your computer.
|
||
|
|
||
|
# Using memory (residential memory)
|
||
|
|
||
|
Once memory gets used, it will actually use up space on your RAM chip.
|
||
|
|
||
|
<pre>
|
||
|
memset(m, 'u', 1073741824);
|
||
|
</pre>
|
||
|
|
||
|
Now we've written the character "u" to the first 1G of our allocated
|
||
|
memory. If we look at top(), we'll see something like this:
|
||
|
|
||
|
<pre>
|
||
|
PID TID PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND
|
||
|
96621 569318 3 0 2048M 1027M sleep/12 ttyin 0:01 1.66% ./a.out
|
||
|
^ ^
|
||
|
allocated memory -' `- used (written) memory
|
||
|
</pre>
|
||
|
|
||
|
Note 1: When memory is swapped to disk, it leaves the residential bucket and
|
||
|
can be seen as swap->used.
|
||
|
|
||
|
Note 2: Stack memory will also show up as residential when used. Unused stack
|
||
|
memory will *not* show up as virtual memory.
|
||
|
|
||
|
Note 3: Residential memory includes shared memory as well. If you see 10
|
||
|
chrome processes which are consuming 300MB of residential memory each, this
|
||
|
does *not* mean that chrome as a whole is using 3000MB.
|
||
|
|
||
|
TODO: Find out how the shared memory part of RES can be seen on OpenBSD.
|
||
|
(Linux has SHR in top)
|