Dynamic Memory Allocation
description
Transcript of Dynamic Memory Allocation
1
Dynamic Memory Allocation
2
Outline
• Implementation of a simple allocator• Explicit Free List• Segregated Free List
• Suggested reading: 10.9, 10.10, 10.11,
10.12, 10.13
3
Dynamic Memory Allocation P731
• Explicit vs. Implicit Memory Allocator
– Explicit: application allocates and frees space
• E.g., malloc and free in C
– Implicit: application allocates, but does not free
space
• E.g. garbage collection in Java, ML or Lisp
4
Dynamic Memory Allocation
• Allocation
– In both cases the memory allocator provides an
abstraction of memory as a set of blocks
– Doles out free memory blocks to application
Doles: 发放
5
Malloc package P731
• #include <stdlib.h>
• void *malloc(size_t size)
– if successful:
• returns a pointer to a memory block of at least size bytes, aligned to 8-byte boundary.
• if size==0, returns NULL
– if unsuccessful: returns NULL
• void free(void *p)
– returns the block pointed at by p to pool of available memory
– p must come from a previous call to malloc,calloc or realloc.
6
sbrk() Function P732
• #include <unistd.h>
• void *sbrk(int incr)– If successful
• It returns the old value of brk
– If unsuccessful• It returns –1
• It sets errno to ENOMEM
– If incr is zero• It returns the current value
– incr can be a negative number
7
10.9.2 Why Dynamic Memory Allocation
8
1 #include "csapp.h"2 #define MAXN 1521334 int array[MAXN];56 int main()7 {8 int i, n;910 scanf("%d", &n);11 if (n > MAXN)12 app_error("Input file too big");13 for (i = 0; i < n; i++)14 scanf("%d", &array[i]);15 exit(0);16 }
Why Dynamic Memory Allocation P734
9
1 #include "csapp.h"23 int main()4 {5 int *array, i, n;67 scanf("%d", &n);8 array = (int *)Malloc(n * sizeof(int));9 for (i = 0; i < n; i++)10 scanf("%d", &array[i]);11 exit(0);12 }
Why Dynamic Memory Allocation P734
10
• Assumptions made in this lecture– memory is word addressed (each word can
hold a pointer)
Allocated block(4 words)
Free block(3 words)
Free word
Allocated word
Assumptions
11
p1 = malloc(4)
p2 = malloc(5)
p3 = malloc(6)
free(p2)
p4 = malloc(2)
Allocation examples
Figure 10.36 P733
12
10.9.3 Allocator Requirements and Goals
13
Constraints
• Applications:
– Can issue arbitrary sequence of allocation and
free requests
– Free requests must correspond to an allocated
block
14
Constraints
• Allocators
– Can’t control number or size of allocated blocks
– Must respond immediately to all allocation
requests
• i.e., can’t reorder or buffer requests
– Must allocate blocks from free memory
• i.e., can only place allocated blocks in free memory
15
Constraints
• Allocators
– Must align blocks so they satisfy all alignment
requirements
• usually 8 byte alignment
– Can only manipulate and modify free memory
– Can’t move the allocated blocks once they are
allocated
• i.e., compaction is not allowed
16
Goals P735
• Given some sequence of malloc and free requests:
– R0, R1, ..., Rk, ... , Rn-1
• Want to maximize throughput and peak memory utilization.– These goals are often conflicting
17
Performance goals: throughput
• Number of completed requests per unit
time
• Example:
– 5,00 malloc calls and 5,00 free calls in 1
seconds
– throughput is 1,000 operations/second.
18
Performance goals: peak memory utilization
• Given some sequence of malloc and free requests:– R0, R1, ..., Rk, ... , Rn-1
• Def: aggregate payload Pk:
– malloc(p) results in a block with a payload of p bytes.
– After request Rk has completed, the aggregate
payload Pk is the sum of currently allocated
payloads.Aggregate: 合计,累计
19
Performance goals: peak memory utilization
• Given some sequence of malloc and free requests:
– R0, R1, ..., Rk, ... , Rn-1
• Def: current heap size is denoted by Hk
– Note that Hk is monotonically nondecreasing
• Def: peak memory utilization: – After k requests, peak memory utilization is:
• Uk = ( maxi<k Pi ) / Hk
20
10.9.4 Fragmentation
Fragmentation: 分裂
21
Fragmentation
• Poor memory utilization caused by
fragmentation
– Comes in two forms:
• internal fragmentation
• external fragmentation
22
Internal Fragmentation
• Internal fragmentation– For some block, internal fragmentation is the
difference between the block size and the payload size
payloadInternal fragmentation
block
Internal fragmentation
23
Internal Fragmentation
• Internal fragmentation
– Is caused by overhead of maintaining heap
data structures, padding for alignment
purposes, or explicit policy decisions (e.g., not
to split the block).
– Depends only on the pattern of previous
requests, and thus is easy to measure.
24
External fragmentation
• Occurs when there is enough aggregate heap memory, but no single
• free block is large enoughp1 = malloc(4)
p2 = malloc(5)
p3 = malloc(6)
free(p2)
p4 = malloc(6)
25
External fragmentation
• External fragmentation depends on
– the pattern of future requests
– and thus is difficult to measure
26
10.9.5 Implementation Issues
27
Implementation issues
• How do we know how much memory to free just given a pointer?
• How do we keep track of the free blocks?
p1 = malloc(1)
p0
free(p0)
28
Implementation issues
• What do we do with the extra space when
allocating a structure that is smaller than
the free block it is placed in?
• How do we pick a block to use for
allocation
– many might fit?
• How do we reinsert freed block?Reinsert:重新插入
29
Knowing how much to free
• Standard method
– keep the length of a structure in the word
preceding the structure
• This word is often called the header field or header
– requires an extra word for every allocated
structure
30
Knowing how much to free
free(p0)
p0 = malloc(4) p0
Block size data
5
31
10.9.6 Implicit Free Lists
32
Implicit list
• Need to identify whether each block is
free or allocated
– Can use extra bit
– Bit can be put in the same word as the size if
block sizes are always multiples of 8 (mask
out low order bit when reading size).
33
Implicit list
size
1 word
Format ofallocated andfree blocks
payload
a = 1: allocated block a = 0: free block
size: block size
payload: application data(allocated blocks only)
a
optionalpadding
00
4 4 26
p
Figure 10.37 P738
34
10.9.7 Placing Allocated Blocks
35
Finding a free block
• 1 ) First fit:– Search list from beginning, choose first free
block that fits– Can take linear time in total number of blocks
(allocated and free)– In practice it can cause “splinters” at
beginning of listp = start; while ((p < end) || \\ not passed end (*p & 1) || \\ already allocated (*p <= len) ); \\ too small
36
Finding a free block
• 2 ) Next fit:– Like first-fit, but search list from location of
end of previous search– Research suggests that fragmentation is worse
• 3 ) Best fit:– Search the list, choose the free block with the
closest size that fits– Keeps fragments small --- usually helps
fragmentation– Will typically run slower than first-fit
37
10.9.8 Splitting Free Blocks
38
Allocating in a free block
• Allocating in a free block - splitting– Since allocated space might be smaller than
free space, we might want to split the block
4 4 26
p
4 24 24
39
10.9.9 Getting Additional Heap Memory
40
10.9.10 Coalescing Free Blocks
Coalescing:接合
41
Freeing a block
• Simplest implementation:– Only need to clear allocated flag– But can lead to “false fragmentation” – There is enough free space, but the allocator
won’t be able to find it
4 24 2
free(p) p
4 4 2
4
4 2
malloc(5)
42
Coalescing
• Join with next and/or previous block if they are free– Coalescing with next block– But how do we coalesce with previous block?
4 24 2
free(p) p
4 4 2
4
6
43
10.9.11 Coalescing with Boundary Tags
44
Bidirectional
• Boundary tags [Knuth73]– replicate size/allocated word at bottom of free
blocks
– Allows us to traverse the “list” backwards, but requires extra space
– Important and general technique!
45
Bidirectional
4 4 4 4 6 46 4
size
1 word
Format ofallocated andfree blocks
payload andpadding
a = 1: allocated block a = 0: free block
size: block size
payload: application data(allocated blocks only)
a
size aboundary tag (footer)
header 00
00
Figure 10.41 P742
46
allocated
allocated
allocated
free
free
allocated
free
free
block beingfreed
Case 1 Case 2 Case 3 Case 4
Constant time coalescing
Figure 10.42 P743
47
m1 1
m1 1
n 1
n 1
m2 1
m2 1
m1 1
m1 1
n 0
n 0
m2 1
m2 1
Constant time coalescing (case 1)
48
m1 1
m1 1
n+m2 0
n+m2 0
m1 1
m1 1
n 1
n 1
m2 0
m2 0
Constant time coalescing (case 2)
49
m1 0
m1 0
n 1
n 1
m2 1
m2 1
n+m1 0
n+m1 0
m2 1
m2 1
Constant time coalescing (case 3)
50
m1 0
m1 0
n 1
n 1
m2 0
m2 0
n+m1+m2 0
n+m1+m2 0
Constant time coalescing (case 4)
51
10.9.12 Putting it Together: Implementing a Simple Allocator
52
1 int mm_init(void);
2 void *mm_malloc(size_t size);
3 void mm_free(void *bp);
Implementing a Simple Allocator
53
Data Structure
Figure 10.44 P745
54
1 #include "csapp.h"23 /* private global variables */4 static void *mem_start_brk; /* points to first byte of the heap */5 static void *mem_brk; /* points to last byte of the heap */6 static void *mem_max_addr; /* max virtual address for the heap */78 /*9 * mem_init - initializes the memory system model10 */11 void mem_init(int size)12 {13 mem_start_brk = (void *)Malloc(size); /* models
available VM */14 mem_brk = mem_start_brk; /* heap is
initially empty */15 mem_max_addr = mem_start_brk + size; /* max VM address
for heap */16 }17
Initialize Figure 10.43 P745
55
18 /*19 * mem_sbrk - simple model of the the sbrk function.
Extends the heap20 * by incr bytes and returns the start address of the new
area. In21 * this model, the heap cannot be shrunk.22 */23 void *mem_sbrk(int incr)24 {25 void *old_brk = mem_brk;2627 if ( (incr < 0) || ((mem_brk + incr) >
mem_max_addr)) {28 errno = ENOMEM;29 return (void *)-1;30 }31 mem_brk += incr;32 return old_brk;33 }
Initialize
56
1 /* Basic constants and macros */
2 #define WSIZE 4 /* word size (bytes) */
3 #define DSIZE 8 /* doubleword size (bytes) */
4 #define CHUNKSIZE (1<<12) /* initial heap size (bytes) */
5 #define OVERHEAD 8 /* overhead of header and footer (bytes) */
6
7 #define MAX(x, y) ((x) > (y)? (x) : (y))
8
9 /* Pack a size and allocated bit into a word */
10 #define PACK(size, alloc) ((size) | (alloc))
11
12 /* Read and write a word at address p */
13 #define GET(p) (*(size_t *)(p))
14 #define PUT(p, val) (*(size_t *)(p) = (val))
15
Macros Figure 10.45 P746
57
16 /* Read the size and allocated fields from address p */
17 #define GET_SIZE(p) (GET(p) & ˜0x7)
18 #define GET_ALLOC(p) (GET(p) & 0x1)
19
20 /* Given block ptr bp, compute address of its header and footer */
21 #define HDRP(bp) ((void *)(bp) - WSIZE)
22 #define FTRP(bp) ((void *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
23
24 /* Given block ptr bp, compute address of next and previous blocks */
25 #define NEXT_BLKP(bp) ((void *)(bp) + GET_SIZE(HDRP(bp)))
26 #define PREV_BLKP(bp) ((void *)(bp) - GET_SIZE(((void *)(bp) - DSIZE)))
size t size = GET SIZE(HDRP(NEXT_BLKP(bp)));
Macros
58
1 int mm_init(void)2 {3 /* create the initial empty heap */4 if ((heap_listp = mem_sbrk(4*WSIZE)) == NULL)5 return -1;6 PUT(heap_listp, 0); /* alignment padding */7 PUT(heap_listp+WSIZE, PACK(OVERHEAD, 1)); /* prologue header
*/8 PUT(heap_listp+DSIZE, PACK(OVERHEAD, 1)); /* prologue footer
*/9 PUT(heap_listp+WSIZE+DSIZE, PACK(0, 1)); /* epilogue header
*/10 heap_listp += DSIZE;1112 /* Extend the empty heap with a free block of CHUNKSIZE bytes
*/13 if (extend_heap(CHUNKSIZE/WSIZE) == NULL)14 return -1;15 return 0;16 }
mm_init() Figure 10.46 P747
59
1 static void *extend_heap(size_t words)2 {3 char *bp;4 size_t size;56 /* Allocate an even number of words to maintain alignment */7 size = (words % 2) ? (words+1) * WSIZE : words * WSIZE;8 if ((int)(bp = mem_sbrk(size)) < 0)9 return NULL;1011 /* Initialize free block header/footer and the
epilogue header */12 PUT(HDRP(bp), PACK(size, 0)); /* free
block header */13 PUT(FTRP(bp), PACK(size, 0)); /* free
block footer */14 PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* new
epilogue header */1516 /* Coalesce if the previous block was free */17 return coalesce(bp);18 }
mm_init() Figure 10.47 P748
60
1 void mm_free(void *bp)
2 {
3 size_t size = GET_SIZE(HDRP(bp));
4
5 PUT(HDRP(bp), PACK(size, 0));
6 PUT(FTRP(bp), PACK(size, 0));
7 coalesce(bp);
8 }
9
mm_free() Figure 10.48 P749
61
10 static void *coalesce(void *bp)11 {12 size_t prev_alloc =
GET_ALLOC(FTRP(PREV_BLKP(bp)));13 size_t next_alloc =
GET_ALLOC(HDRP(NEXT_BLKP(bp)));14 size_t size = GET_SIZE(HDRP(bp));1516 if (prev_alloc && next_alloc) { /* Case 1 */17 return bp;18 }1920 else if (prev_alloc && !next_alloc) { /* Case 2
*/21 size += GET_SIZE(HDRP(NEXT_BLKP(bp)));22 PUT(HDRP(bp), PACK(size, 0));23 PUT(FTRP(bp), PACK(size,0));24 return(bp);25 }26
mm_free()
62
27 else if (!prev_alloc && next_alloc) { /* Case 3 */
28 size += GET_SIZE(HDRP(PREV_BLKP(bp)));
29 PUT(FTRP(bp), PACK(size, 0));
30 PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
31 return(PREV_BLKP(bp));
32 }
33
34 else { /* Case 4 */
35 size += GET_SIZE(HDRP(PREV_BLKP(bp))) +
36 GET_SIZE(FTRP(NEXT_BLKP(bp)));
37 PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
38 PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
39 return(PREV_BLKP(bp));
40 }
41 }
mm_free() Figure 10.48 P749
63
1 void *mm_malloc (size_t size)2 {3 size_t asize; /* adjusted block size */4 size_t extendsize; /* amount to extend heap if no fit */5 char *bp;67 /* Ignore spurious requests */8 if (size <= 0)9 return NULL;1011 /* Adjust block size to include overhead and
alignment reqs. */12 if (size <= DSIZE)13 asize = DSIZE + OVERHEAD;14 else15 asize = DSIZE * ((size + (OVERHEAD) +
(DSIZE-1)) / DSIZE);16
mm_malloc() Figure 10.49 P750
64
17 /* Search the free list for a fit */
18 if ((bp = find_fit(asize)) != NULL) {
19 place (bp, asize);
20 return bp;
21 }
22
23 /* No fit found. Get more memory and place the block */
24 extendsize = MAX (asize, CHUNKSIZE) ;
25 if ((bp = extend_heap (extendsize/WSIZE)) == NULL)
26 return NULL;
27 place (bp, asize);
28 return bp;
29 }
mm_malloc()
65
1. static void *find_fit(size_t asize)
2. {
3. void *bp ;
4.
5. /* first fit search */
6. for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0 ; bp = NEXT_BLKP(bp) ) {
7. if (!GET_ALLOC(HDRP(bp)) && (asize<=GET_SIZE(HDRP(bp)))) {
8. return bp;
9. }
10. }
11. return NULL; /*no fit */
12. }
mm_alloc()
66
1. static void place(void *bp, size_t asize)
2. {
3. size_t csize = GET_SIZE(HDRP(bp)) ;
4.
5. if ( (csize –asize) >= (DSIZE + OVERHEAD) ) {
6. PUT(HDRP(bp), PACK(asize, 1)) ;
7. PUT(FTRP(bp), PACK(asize, 1)) ;
8. bp = NEXT_BLKP(bp) ;
9. PUT(HDRP(bp), PACK(csize-asize, 0) ;
10. PUT(FTRP(bp), PACK(csize-asize, 0) ;
11. } else {
12. PUT(HDRP(bp), PACK(csize, 1) ;
13. PUT(FTRP(bp), PACK(csize, 1) ;
14. }
15. }
mm_alloc()
67
10.9.13 Explicit Free Lists
68
Explicit free lists
• Explicit list among the free blocks using
pointers within the free blocks
• Use data space for link pointers
– Typically doubly linked
– Still need boundary tags for coalescing
– It is important to realize that links are not
necessarily in the same order as the blocks
69
Explicit free lists
A B C
4 4 4 4 66 44 4 4
Forward links
Back links
A B
C
70
Freeing with explicit free lists
• Where to put the newly freed block in the
free list
– LIFO (last-in-first-out) policy
• insert freed block at the beginning of the free list
• pro: simple and constant time
• con: studies suggest fragmentation is worse than
address ordered.
71
Freeing with explicit free lists
• Where to put the newly freed block in the free list– Address-ordered policy
• insert freed blocks so that free list blocks are always in address order
– i.e. addr(pred) < addr(curr) < addr(succ)• con: requires search
• pro: studies suggest fragmentation is better than LIFO
72
10.9.14 Segregated Free Lists
73
Segregated Storage
• Each size “class” has its own
collection of blocks
– Often have separate collection for every small
size (2,3,4,…)
– For larger sizes typically have a collection for
each power of 2
74
Segregated Storage
1-2
3
4
5-8
9-16
75
• Separate heap and free list for each size class
• No splitting• To allocate a block of size n:
– if free list for size n is not empty,• allocate first block on list (note, list can be implicit or
explicit)
– if free list is empty, • get a new page • create new free list from all blocks in page• allocate first block on list
– constant time
1) Simple segregated storage
76
• To free a block:
– Add to free list
– If page is empty, return the page for use by
another size (optional)
• Tradeoffs:
– fast, but can fragment badly
Simple segregated storage
77
• Array of free lists, each one for some size
class
2) Segregated fits
78
• To allocate a block of size n:– search appropriate free list for block of size m
> n
– if an appropriate block is found:
• split block and place fragment on appropriate list (optional)
– if no block is found, try next larger class
– repeat until block is found
– if no blocks is found in all classes, try more heap memory
Segregated fits
79
• To free a block:– coalesce and place on appropriate list
(optional)
• Tradeoffs– faster search than sequential fits (i.e., log
time for power of two size classes)– controls fragmentation of simple segregated
storage– coalescing can increase search times
• deferred coalescing can help
Segregated fits
80
• A special case of segregated fits
– Each size is power of 2
• Initialize
– A heap of size 2m
3) Buddy Systems
81
• Allocate
– Roundup to power of 2 such as 2k
– Find a free block of size 2j (k j m)
– Split the block in half until j=k
• Each remaining half block (buddy) is placed on the
appreciate free list
• Free
– Continue coalescing with the free buddies
Buddy Systems
82
10.10 Garbage Collection
83
10.11 Common Memory-Related Bugs in C Programs
84
10.12 Recapping Some Key Ideas About Virtual Memory
85
10.13 Summary