Spring 2009 6.172 — Performance Engineering of Software Systems Lecture 9 MIT OpenCourseWare Dynamic Storage Allocation Stack allocation: LIFO (last-in-first-out) • Array and pointer A unused used P after P before Figure 1: A diagram of the stack (Image by MIT OpenCourseWare.) Allocate x bytes: q = p; p += x; return q; O (1) time Few operations and good cache behavior (temporal and spatial) Free: p = q; O (1) time Issues: • Inline (especially for small allocations) • May want to round up to word (or cache block) boundary • Must free consistent with stack discipline ⇒ limited applicability, but fast when it works. Can sometimes use call stacks, e.g. alloca() (free free() ) alloca() is depreciated [hard to control stack size in some environments and compiler is more efficient with fixedsize function activation records (frames)] Heap allocation (not heap data structure) C: malloc() and free() C++: new and delete Unlike Java and Python, C/C++ has no garbage collector. Storage that is allocated must be freed explicitly by programmer. Otherwise, memory leak! Also watch for dangling pointers and double frees. 1
Lecture 9 6.172, Fall 2009 Fixed-size allocation nil A freelist Figure 2: A diagram of a free list (Image by MIT OpenCourseWare.) Allocation: remove head of free list — O (1) time Free: add block to free list — O (1) time Few ops and good locality Problem. External fragmentation: blocks distributed across memory ⇒ loss of spatial locality Variable-size allocation Idea : Leverage efficiency of fixedsize allocation. Accept some internal fragmentation. Binned free lists Allocator supports a reduced set of canonical sizes, typically { 1 , 2 , 4 , 8 , 16 , . . . } (or slightly larger for book- keeping info, cache alignment) 0 1 2 largest requested r block size Figure 3: A diagram of a binnedfree list (Image by MIT OpenCourseWare.) Allocate x : • look in bin � lg x � • if empty, find block in larger bin and split • No larger blocks, allocate new address space. 2
Lecture 9 6.172, Fall 2009 stack dynamically allocated heap uninitialized initialized to 0 at programstart data bss initialized read from program file data code high addr low addr Figure 4: The typical storage layout of a program(Image by MIT OpenCourseWare.) Question : 64bit virtual memory (VM) ⇒ never run out of address space. Why not just allocate what you need and never free? Answer : VM is backed up by physical memory, e.g. disk. Also, severe external fragmentation. Goal : use as little VM as possible. Theorem. Let M be the maximum amount of memory in use at any time by a program. Then binned free lists uses at most O ( M lg M ) VM address space. Proof. No bin ever contains more than 2 M memory. At most lg(2 M ) bins. ���� round up Theorem. Let M be the VM address space used by the optimal allocator (with no coalescing). Then binned free lists uses at most 6 M VM address space. Coalescing • Splice adjacent blocks together to make larger blocks 3
Lecture 9 6.172, Fall 2009 • Ameliorates external fragmentation • No good bounds on effectiveness • Works in practice, because storage tends to be deallocated as a stack (LIFO) or in batches. • Clever schemes for finding adjacent blocks, e.g. ”‘buddy”’ system Garbage collection Idea : Rather than user freeing storage, runtime does it. Builtin (Java, Python) (or build by hand) Roots : storage directly accessible (global vars, stack). Objects not reachable from roots through pointers can be recycled. Key issues: • Identify pointers in objects (strong typing) • Prohibit pointer arithmetic may slow down some codes. Reference counting • Keep count of number of pointers to each object. If pointer count drops to 0, put in free list. 3 1 1 Figure 5: A diagram of reference counting garbage collection (Image by MIT OpenCourseWare.) Problem. Cycle never garbage collected. Nevertheless, good scheme for acyclic structures. 4
Lecture 9 6.172, Fall 2009 Abstraction Objects form a directed graph. Garbage Collected objects not reachable from roots. ⇒ graph searching (e.g., DFS or BFS) Recall BFS: Mark roots and put into FIFO Q; (a bitfield) while (Q not empty) { u = dequeue(Q); for (each (u,v) incident on u) { if (v unmarked) { mark v; enqueue(Q,V); } } } Example. a b f g r e i c h d j Figure 6: A diagram of a BFS (Image by MIT OpenCourseWare.) �� Q : � � g r � cd ef � � Observation : All reachable objects are placed in contiguous storage in Q . Copying GC: dead From space next allocation live Tospace live next allocation Figure 7: A diagram of a copying garbage collector (Image by MIT OpenCourseWare.) When From space is full, copy to To space. 5
Lecture 9 6.172, Fall 2009 Issue : Since To address is different than the From address, pointers must be updated. I. When object copied to To space, store forwarding pointer in From object, which implicitly marks it as moved. II. When object removed from Q in To space, update all its pointers. Example. Before From To head tail After From To head tail Figure 8: A diagram of a copying garbage collector (Image by MIT OpenCourseWare.) • Linear time • After copying, allocate new unused space equal to (or constant fraction of) used space ⇒ amortize GC time, keep VM address space small. From To used unused Figure 9: A diagram of a copying garbage collector (Image by MIT OpenCourseWare.) • Old To becomes new From • New To allocated at start if room, otherwise after new From ⇒ VM address space ≤ constant optimal 6
Lecture 9 6.172, Fall 2009 Other GC Strategies • mark and sweep • generational 7
MIT OpenCourseWare http://ocw.mit.edu 6.172 Performance Engineering of Software Systems Fall 2009 For information about citing these materials or our Terms of Use, visit: http://ocw.mit.edu/terms.
Recommend
More recommend