applications - new york university⬛programmers use dynamic memory allocators (such as malloc) to...

17
Dynamic Memory Allocation Computer Systems Organization (Spring 2017) CSCI-UA 201, Section 3 Instructor: Joanna Klukowska Slides adapted from Randal E. Bryant and David R. O’Hallaron (CMU) Mohamed Zahran (NYU) Basic Concepts 2 Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime. Dynamic memory allocators manage an area of process virtual memory known as the heap. malloc .text .data bss brk 3 Allocator maintains heap as collection of variable sized blocks, which are either allocated or free Types of allocators Explicit allocator: application allocates and frees space E.g., malloc and free in C Implicit allocator: application allocates, but does not free space E.g. garbage collection in Java, ML, and Lisp 4

Upload: others

Post on 13-May-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

Dynamic Memory Allocation

Computer Systems Organization (Spring 2017)CSCI-UA 201, Section 3

Instructor: Joanna Klukowska

Slides adapted from Randal E. Bryant and David R. O’Hallaron (CMU)

Mohamed Zahran (NYU)

Basic Concepts

2

⬛ Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time.

▪ For data structures whose size is only known at runtime.

⬛ Dynamic memory allocators manage an area of process virtual memory known as the heap. malloc

.text

.data

bss

brk

3

⬛ Allocator maintains heap as collection of variable sized blocks, which are either allocated or free

⬛ Types of allocators

▪ Explicit allocator: application allocates and frees space ▪ E.g., malloc and free in C

▪ Implicit allocator: application allocates, but does not free space▪ E.g. garbage collection in Java, ML, and Lisp

4

Page 2: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

malloc

#include <stdlib.h>

void *malloc(size_t size)▪ Successful:

▪ Returns a pointer to a memory block of at least size bytesaligned to an 8-byte (x86) or 16-byte (x86-64) boundary

▪ If size == 0, returns NULL▪ Unsuccessful: returns NULL (0) and sets errno

void free(void *p)▪ Returns the block pointed at by p to the pool of available memory▪ p must come from a previous call to malloc, calloc or realloc

Other functions▪ calloc: Version of malloc that initializes allocated block to zero.

▪ realloc: Changes the size of a previously allocated block.

▪ sbrk: Used internally by allocators to grow or shrink the heap

5

malloc#include <stdio.h>#include <stdlib.h>

void foo(int n) { int i, *p;

/* Allocate a block of n ints */ p = (int *) malloc(n * sizeof(int)); if (p == NULL) { perror("malloc"); exit(0); }

/* Initialize allocated block */ for (i=0; i<n; i++)

p[i] = i;

/* Return allocated block to the heap */ free(p);}

6

⬛ Memory is word addressed.⬛ Words are int-sized.

7

p1 = malloc(4)

p2 = malloc(5)

p3 = malloc(6)

free(p2)

p4 = malloc(2)

8

Page 3: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

⬛ Applications▪ Can issue arbitrary sequence of malloc and free requests▪ free request must be to a malloc’d block

⬛ Allocators▪ Can’t control number or size of allocated blocks▪ Must respond immediately to malloc 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▪ Must align blocks so they satisfy all alignment requirements

▪ 8-byte (x86) or 16-byte (x86-64) alignment on Linux boxes▪ Can manipulate and modify only free memory▪ Can’t move the allocated blocks once they are malloc’d

▪ i.e., compaction is not allowed

9

⬛ malloc free▪

▪▪

▪ malloc free

10

⬛ malloc free▪

▪ malloc(p) p▪

⬛▪

▪ sbrk

⬛▪

11

▪▪

12

Page 4: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

⬛ For a given block, internal fragmentation occurs if payload is smaller than block size

⬛ Caused by ▪ Overhead of maintaining heap data structures▪ Padding for alignment purposes▪ Explicit policy decisions

(e.g., to return a big block to satisfy a small request)▪

⬛ Depends only on the pattern of previous requests▪ Thus, easy to measure

13

p1 = malloc(4)

p2 = malloc(5)

p3 = malloc(6)

free(p2)

p4 = malloc(6)

14

⬛15

▪▪

p0 = malloc(4)

p0

free(p0)

16

Page 5: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

⬛ Method 1: Implicit list using length—links all blocks

⬛ Method 2: Explicit list among the free blocks using pointers

⬛ Method 3: Segregated free list▪ Different free lists for different size classes

⬛ Method 4: Blocks sorted by size▪ Can use a balanced binary tree with pointers within each free block, and the length used as a

key

5

5

17

Implicit Free List

18

⬛ For each block we need both size and allocation status▪ Could store this information in two words: wasteful!▪

⬛ Standard trick▪ If blocks are aligned, some low-order address bits are always 0▪ Instead of storing an always-0 bit, use it as a allocated/free flag▪ When reading size word, must mask out this bit

19 20*Assume 8-byte (2 word) align boundary.

Page 6: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

⬛ 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 list

⬛ Next fit:▪ Like first fit, but search list starting where previous search finished▪ Should often be faster than first fit: avoids re-scanning unhelpful blocks▪ Some research suggests that fragmentation is worse

⬛ Best fit:▪ Search the list, choose the best free block: fits, with fewest bytes left over▪ Keeps fragments small—usually improves memory utilization▪ Will typically run slower than first fit

21

addblock(p, 4)

22

free(p) p

malloc(5)

There is enough free space, but the allocator won’t be able to find it (since it sees a block of 4 and block of 2, not a block of 5).

23

free(p) p

24

Page 7: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

▪▪▪

25 26

27 28

What do we do, if the next block is free as well? ● Not possible if we always coalesce.

Page 8: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

29 30

⬛ Placement policy:▪ First-fit, next-fit, best-fit, etc.▪ Trades off lower throughput for less fragmentation▪ Interesting observation: segregated free lists (next lecture) approximate a best fit placement

policy without having to search entire free list

⬛ Splitting policy:▪ When do we go ahead and split free blocks?▪ How much internal fragmentation are we willing to tolerate?

⬛ Coalescing policy:▪ Immediate coalescing: coalesce each time free is called ▪ Deferred coalescing: try to improve performance of free by deferring coalescing until

needed. Examples:▪ Coalesce as you scan the free list for malloc▪ Coalesce when the amount of external fragmentation reaches some threshold

31

⬛ Implementation: very simple

⬛ Allocate cost: ▪ linear time worst case

⬛ Free cost: ▪ constant time worst case▪ even with coalescing

⬛ Memory usage: ▪ will depend on placement policy▪ First-fit, next-fit or best-fit

⬛ Not used in practice for malloc/free because of linear-time allocation▪ used in many special purpose applications

⬛ However, the concepts of splitting and boundary tag coalescing are general to all allocators

32

Page 9: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

Explicit Free List

33

⬛ Method 1: Implicit list using length—links all blocks

⬛ Method 2: Explicit list among the free blocks using pointers

⬛ Method 3: Segregated free list▪ Different free lists for different size classes

⬛ Method 4: Blocks sorted by size▪ Can use a balanced binary tree with pointers within each free block, and the length used as a

key

5

5

34

▪▪

▪▪

35

36

Page 10: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

= malloc(…)37

▪▪▪

▪▪

38

free( )

39

free( )

40

Page 11: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

free( )

41

free( )

42

▪▪

▪▪

43

⬛ Method 1: Implicit list using length—links all blocks

⬛ Method 2: Explicit list among the free blocks using pointers

⬛ Method 3: Segregated free list▪ Different free lists for different size classes

⬛ Method 4: Blocks sorted by size▪ Can use a balanced tree with pointers within each free block, and the length used as a key

5

5

44

Page 12: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

Segregated Free List

45

46

⬛▪▪

▪▪

⬛▪ sbrk()▪▪

47

▪▪

▪▪

48

Page 13: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

Garbage Collection

49

void foo() { int *p = malloc(128); return; /* p block is now garbage */}

50

⬛▪

▪▪

int

51

▪⬛

▪⬛

▪⬛

▪▪

52

Page 14: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

Memory Related Bugs

53

54

int *p

int *p[13]

int *(p[13])

int **p

int (*p)[13]

int *f()

int (*f)()

int (*(*f())[13])()

int (*(*x[3])())[5]

55

scanf

int val;

...

scanf("%d", val);

56

Page 15: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

/* return y = Ax */int *matvec(int **A, int *x) { int *y = malloc(N*sizeof(int)); int i, j;

for (i=0; i<N; i++) for (j=0; j<N; j++) y[i] += A[i][j]*x[j]; return y;}

57

int **p;

p = malloc(N*sizeof(int));

for (i=0; i<N; i++) { p[i] = malloc(M*sizeof(int));}

58

int **p;

p = malloc(N*sizeof(int *));

for (i=0; i<=N; i++) { p[i] = malloc(M*sizeof(int));}

59

char s[8];int i;

gets(s); /* reads “123456789” from stdin */

60

Page 16: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

int *search(int *p, int val) { while (*p && *p != val) p += sizeof(int);

return p;}

61

int * heap_delete(int **binheap, int *size) { int *packet; packet = binheap[0]; binheap[0] = binheap[*size - 1]; *size--; heapify(binheap, *size, 0); return(packet);}

62

int *foo () { int val;

return &val;}

63

x = malloc(N*sizeof(int)); <manipulate x>free(x);

y = malloc(M*sizeof(int)); <manipulate y>free(x);

64

Page 17: Applications - New York University⬛Programmers use dynamic memory allocators (such as malloc) to acquire VM at run time. For data structures whose size is only known at runtime

x = malloc(N*sizeof(int)); <manipulate x>free(x); ...y = malloc( M*sizeof(int) );for (i=0; i < M; i++) y[i] = x[i]++;

65

foo() { int *x = malloc(N*sizeof(int)); ... return;}

66

struct list { int val; struct list *next;};

foo() { struct list *head = malloc(sizeof(struct list)); head->val = 0; head->next = NULL; <create and manipulate the rest of the list> ... free(head); return;}

67

⬛ gdb▪▪

▪▪

⬛ valgrind▪▪▪

▪ setenv MALLOC_CHECK_ 3 (see the manual page for mallopt)

68