01.memorymanagement
DESCRIPTION
Document about memory managementTRANSCRIPT
-
System SoftwareProf. Dr. H. Mssenbck
1. Memory Management2. Garbage Collection3. Linkers and Loaders4. Debuggers5. Text Editors
Marks obtained by end-term exam
http://ssw.jku.at/Misc/SSW/
-
21. Memory Management1.1 Overview1.2 Allocation and deallocation of memory1.3 Single free list1.4 Multiple free lists1.5 Buddy system1.6 Memory fragmentation
-
3Main tasks of memory managementAllocation and deallocation of memory
global data global variables, code managed by the loader
stack local variables managed by the compiler
heap dynamically created objects managed by the run-time system
Reclaiming unused memory (garbage collection)p p = q; p q
Dealing with memory fragmentation
Paging and swapping (virtual memory)
not discussed in this course
-
41. Memory Management1.1 Overview1.2 Allocation and deallocation of memory1.3 Single free list1.4 Multiple free lists1.5 Buddy system1.6 Memory fragmentation
-
5Stack-like management of the heap
m = mark();
m
returns the currentend of the heap (top)
top
a = alloc(size);
m
allocates a blockof size size and
returns its address a
topa m
topa
more alloc() calls free(m);
m
resets the heap end to m(deallocates anything that
was allocated after mark())
top
mark/alloc/free
Disadvantageobjects must be deallocated in LIFO order(applicable e.g. for the symbol table ofa compiler)
Advantagesimple and efficient
int alloc(int size) {if (top + size > heapEnd) {
error(...); a = 0;} else {
a = top; top = top + size;}return a;
}
void free(int m) {top = m;
}
-
6Heap management with a free listallocation of a block a = alloc(size);
deallocation of a block dealloc(a);
May lead to holes in the heap, whichmust be maintained by a free list
heap
free(free list)
alloc() must allocate a block from the free list, i.e.: find a sufficiently large block in the free list remove it from the free list
dealloc() add the deallocated block to the free list merge the block with free neighbors
-
71. Memory Management1.1 Overview1.2 Allocation and deallocation of memory1.3 Single free list1.4 Multiple free lists1.5 Buddy system1.6 Memory fragmentation
-
8Single free list
heap
free
All blocks are linked into a single large list
Possible sort orders of the free list
1. LIFO: the most recently deallocated block is the first in the list.Simple to implement
2. FIFO: the most recently deallocated block is the last in the list.3. Blocks are sorted by address.
Simple block merging; slow insert4. Blocks are sorted by their size.
Simple search of a suitable block; slow insert
-
9Possible block format
used block 1 length data
p
free block 0 length unusednext
This format implies a minimum block size (e.g. 8 bytes)
Why do we need the length of used blocks?
It allows us to traverse the heap sequentially: p = p + p.length;
-
10
Allocation of blocksp = alloc(size);
Strategies for searching the free list
First Fit returns the first suitable block with length >= size + 4+ simple and efficient- causes fragmentation (small blocks accumulate at the beginning of the list)
Best Fit returns the block with the smallest waste (blocks are split)blockj: lengthj >= (size+4) && i j: lengthi >= lengthj+ minimum waste- slow (must traverse the whole list; good if the list is sorted by block size)
Next Fit variant of First Fitfree blocks are linked cyclically; the search starts where it ended last time
freefree
-
11
Splitting free blocksFree block
0 len next
len
The block is cut off from the end => next does not have to be changedIf less than 8 bytes would remain the whole block is used
unused
Splitting
p = alloc(size);
0 len' next
len'
1 len''
len''
size
unused used
p
free list
-
12
Allocation of blocks (pseudo code)static Block free; // free liststatic Block alloc (int size) {
Block start = free;Block prev = free; free = free.next;while (free.len < size+4 && free != start) {
prev = free; free = free.next;}if (free == start) { error(...); return null; }else {
Block p = free;int newLen = p.len - (size+4);if (newLen >= 8) { // split block
p = (Block)(p - 4 + p.len - size);p.len = size + 4;free.len = newLen;
} else if (free == prev) { // last free blockfree = null;
} else { // remove block from listprev.next = free.next; free = prev;
}Set all data bytes in block p to 0;p.used = true;return p;
}}
free prev free
0 len next
pfree
size
len
0 nL next
free size
newLen
1 len
p
len
-
13
Deallocation of blocksdealloc(p);
free pleft right
- merge blockp with free neighbors- add merged block to the free list
void dealloc (Block p) {left = left neighbor of p; // traverse heap sequentiallyif (!left.used) {
merge left and p; p = left; // enlarge left.len; left remains in free list} else {
add p to free list;}right = right neighbor of p; // right = (Block)(p + p.len);if (!right.used) {
remove right from free list; // seq. search of right's predecessormerge p and right; // p is already in the free list
}}
Requires sequential traversals of the heap and the free list => slow
-
14
Boundary tagsIn order to avoid the sequential searching of blocks
Free list is doubly linked
length and used bit are also stored at the block end (also in used blocks)
0 0len lennext prev
p
minimum block size = 16 bytes
right neighbor of p: p + p.lenleft neighbor of p: p - (p-8).lensuccessor of p in free list: p.nextpredecessor of p in free list: p.prev
There must be a used dummy block at the beginning and the end of the heap.
-
15
Lazy mergedealloc(p) does not merge free blocks with their neighbors
pfree
If alloc() does not find a sufficiently large block: traverse the heap sequentially merge adjacent free blocks build new free list
p = heapStart; free = null;while (p < heapEnd) {
if (!p.used) {while (right neighbor of p is free) merge neighbor with p;add p to free list;
}p = (Block)(p + p.len);
}
free
free
p.next = free;free = p;
-
16
1. Memory Management1.1 Overview1.2 Allocation and deallocation of memory1.3 Single free list1.4 Multiple free lists1.5 Buddy system1.6 Memory fragmentation
-
17
Allocation of blocksObservation
90% of all blocks have only one of 5 different sizes
Multiple free lists for blocks of size 2i bytes
8163264
128256512
n*1024
free
...
...
Blocks in the last list have different sizes, but their size is a multiple of 1024 bytes
n = next power of 2 greater or equal than s remove the first block from the list corresponding to n Any surplus stays with the allocated block (block size is always 2i)
Strategy for allocating a block of size s
-
18
AlgorithmsBlock alloc (int size) {
if (size > 512) {p = suitable block from the last list (e.g. first fit);put remaining i*1024 byte back to the last list;
} else {int s = 8, n = 3; // free[0..2] are dummieswhile (s < size) { s = 2 * s; n++; } // n = log2(size);if (free[n] == null) split(n+1);p = free[n]; free[n] = p.next; // p = first block from free[n]
}initialize block p with 0;return p;
}
void split (int n) {if (n == 10) {
p = cut off 1024 byte block from the last list;} else {
if (free[n] == null) split(n+1);p = free[n]; free[n] = p.next;
}split p into two equally sized blocks and add them to free[n-1];
}
3456789
10
8 8 816 1632
2048 4096
012
64128256512
-
19
ExampleAllocation of 40 bytes (given the follwing free lists)
8163264
128256512
n*1024
8 8 816 1632
2048 4096
tries to obtain a block of size 64;but the 64-list is empty
8 8 816 1632
2048 4096
Split a 1024 byte block and use it to fill the empty lists
8 8 816 1632
1024 4096512 512
4096
8 8 816 1632
1024512256 256
8 8 816 1632
1024 4096512256128 128
8 8 816 1632
1024 409651225612864 64
Take a 64 byte block leaving 24 bytes unused (internal fragmentation)
In most cases a suitable block is found with a single access => efficientAt the beginning the whole heap is a single block in the 1024-list
-
20
Deallocation of blocks
void dealloc (Block p) {int s = 8, n = 3;while (s < p.len) { s = 2 * s; n++; } // n = log2(p.len);if (n > 10) n = 10;p.next = free[n]; free[n] = p; // add p to free[n]
}
Blocks are not merged, because a block of the same size is probably needed soon again(maybe one should do a lazy merge from time to time)
-
21
Reducing internal fragmentation
... by more block sizes
block sizes
2i 8 16 32 64 128 256 512 1024
8 16 32 64 128 256 512
8 8 8 16 16 32 32 64 64
16 16 16 16 16 16 16 16 16
k * 16 16 32 48 64 80 96 112 128 144 160 ...
2i, 3*2i 8 16 24 32 48 64 96 128 192 256 ...
+ less internal fragmentation- more free lists- more difficult to compute the right list- more complicated to split blocks
-
22
Reducing internal fragmentation
... by free lists containing blocks of variable sizes (in a certain interval)
list i contains blocks of size 2i .. 2i+1-1
Example
we need a block with 40 bytes
search the list containing blocks of size 32..63; we find a block of size 58, say
split the block into 40 + 18 bytes add 18-byte block into list with sizes 16..31
+ no internal fragmentation+ the lists are shorter than with a single free list- the list must be searched for a suitable block (e.g. next fit)- leads to many small blocks of waste
free blocks should be merged lazily from time to time
-
23
1. Memory Management1.1 Overview1.2 Allocation and deallocation of memory1.3 Single free list1.4 Multiple free lists1.5 Buddy system1.6 Memory fragmentation
-
24
Idea of the Buddy System
Goal: simple and efficient merging of blocks
alloc(size)Multiple free lists with blocks of size 2i
8 8 816 16 1632 32 3264 64 64
...
as described above
dealloc(p) Every block has a partner (buddy) of the same size
p
32
q
32p is the buddy of q and vice versa
A block can only be merged with its buddy
The address of p's buddy can be computed from the address of p
-
25
Buddy addressesBuddies emerge from splitting blocks of size 2i
Assume that we have a block of size 64 (= 26) at address 0
640
0 32 adr(x) = 0 = 0 0 0 0 0 0 0 0 size = 25
adr(y) = 32 = 0 0 1 0 0 0 0 032 32x y
If we split this block we obtain two buddies x and y of size 32 (= 25)
5
32 48 adr(x) = 32 = 0 0 1 0 0 0 0 0 size = 24
adr(y) = 48 = 0 0 1 1 0 0 0 016 16x y
If we split y again we obtain
4
8 832 40
x yadr(x) = 32 = 0 0 1 0 0 0 0 0 size = 23
adr(y) = 40 = 0 0 1 0 1 0 0 0
If we split x again we obtain
3
A block of size 2i has an address which is a multiple of 2i (it has i zeroes at the end)
-
26
Deallocation of a block of size 2iMerge the block with its buddy if the buddy is free
iheap
free p
void dealloc (Block p) { // size of p = 2iint s = 8, i = 3, buddy, beg;while (s < p.len) { s = s * 2; i++; } // s = p.len, i = log2(p.len)for (;;) {
if ( ((p-4) >> i) % 2 == 1) {buddy = p - p.len; beg = buddy;
} else {buddy = p + p.len; beg = p;
}if (buddy.used || buddy.len != p.len
|| buddy < heapStart || buddy >= heapEnd) break;remove buddy from free[i]; // seq. search in short listp = beg; p.len = 2 * p.len;i++;
}add p to free[i];
}
p
if p is deallocated,multiple blocks aremerged
cannot be merged withits buddy any more=> add it to the free list
pbuddybeg
buddypbeg
-
27
1. Memory Management1.1 Overview1.2 Allocation and deallocation of memory1.3 Single free list1.4 Multiple free lists1.5 Buddy system1.6 Memory fragmentation
-
28
External and internal fragmentation
external fragmentationsmall (unusable) holesbetween blocks
internal fragmentationunused bytes within an allocated block
heap
External fragmentation can be removed by compaction
+ collects all "holes" into a contiguous area of free memory+ allows simple alloc() without free lists (blocks are cut off from the free area)- compaction leads to new block addresses => all references must be updated
Some garbage collectors compact the heap automatically (see later)
-
29
CompactionRequires 2 traversals of the heap and 1 traversal through all pointers
10 70 130heap
pointers
2. Modify all pointers so that they point to the new address10 70 130
0 30 500 30 50 problem: where are the pointers?
They can be in local variables or inother objects.
3. Move blocks to their new address
0 30 500 30 50
1. For every block, compute its address after compaction10 70 130
0 30 50
allocated blocks must have anextra space to store the newaddress.
0 30 50
-
30
Compaction with master pointers20 30
block size
master pointers
pointers
Pointers reference blocks via master pointers(e.g. "handles" on the Macintosh)Every block is referenced by just a singlemaster pointer
Step 1: Reverse master pointers
20 30 master[]
for (all elements i in master) {p = master[i];master[i] = p.len;p.len = i;
}
Step 2: Compact
20 30
master[]
a = heapStart;for (all blocks p) {
if (p.used) {i = p.len; p.len = master[i]; master[i] = a;move block p to a;a = a + p.len;
}}
+ requires only 2 instead of 3 traversals+ blocks do not need extra space to store their new address- indirect access via master pointers is slower than direct access via pointers