Administrivia. Dynamic memory allocation. More abstractly. Why is it hard? What is fragmentation really? Important decisions

Similar documents
Administrivia. Project 2 due Friday at noon Midterm Monday. Midterm review section Friday Section for Project 3 next Friday

Administrivia. - Open book, open notes (but not open notebook computer) - Covers first 10 lectures of course (including today)

Administrivia. Project 2 due Friday at 12pm (noon) Midterm Monday 2/12

Administrivia. Reminder: My office hours for midterm - Today after class - Extra office hours Friday (check web site)

CS61C : Machine Structures

Run-time Environments -Part 3

CS 162 Operating Systems and Systems Programming Professor: Anthony D. Joseph Spring Lecture 13: Address Translation

Motivation for Dynamic Memory. Dynamic Memory Allocation. Stack Organization. Stack Discussion. Questions answered in this lecture:

! What is main memory? ! What is static and dynamic allocation? ! What is segmentation? Maria Hybinette, UGA. High Address (0x7fffffff) !

A.Arpaci-Dusseau. Mapping from logical address space to physical address space. CS 537:Operating Systems lecture12.fm.2

CS 31: Intro to Systems Virtual Memory. Kevin Webb Swarthmore College November 15, 2018

Simple idea 1: load-time linking. Our main questions. Some terminology. Simple idea 2: base + bound register. Protection mechanics.

Review! Lecture 5 C Memory Management !

CS61C : Machine Structures

Dynamic Memory Allocation

The Art and Science of Memory Allocation

Dynamic Memory Allocation

Run-Time Environments/Garbage Collection

Recall from Tuesday. Our solution to fragmentation is to split up a process s address space into smaller chunks. Physical Memory OS.

Past: Making physical memory pretty

Lecture 13: Garbage Collection

Memory Management. q Basic memory management q Swapping q Kernel memory allocation q Next Time: Virtual memory

Heap Management portion of the store lives indefinitely until the program explicitly deletes it C++ and Java new Such objects are stored on a heap

Lecture 7 More Memory Management Slab Allocator. Slab Allocator

Memory management. Johan Montelius KTH

Recall: Address Space Map. 13: Memory Management. Let s be reasonable. Processes Address Space. Send it to disk. Freeing up System Memory

ECE 598 Advanced Operating Systems Lecture 10

Dynamic Memory Allocation. Gerson Robboy Portland State University. class20.ppt

CS61C : Machine Structures

10.1. CS356 Unit 10. Memory Allocation & Heap Management

Introduction to Computer Systems /18 243, fall th Lecture, Oct. 22 th

Memory Management. To do. q Basic memory management q Swapping q Kernel memory allocation q Next Time: Virtual memory

CS162 Operating Systems and Systems Programming Lecture 11 Page Allocation and Replacement"

CS 241 Honors Memory

Page 1. CS162 Operating Systems and Systems Programming Lecture 14. Caching and Demand Paging

CS61C : Machine Structures

ECE 598 Advanced Operating Systems Lecture 12

CS162 Operating Systems and Systems Programming Lecture 12. Address Translation. Page 1

Virtual Memory. Kevin Webb Swarthmore College March 8, 2018

Memory Management. COMP755 Advanced Operating Systems

Virtual Memory Primitives for User Programs

Requirements, Partitioning, paging, and segmentation

CMSC 330: Organization of Programming Languages

CS61C : Machine Structures

CS61C : Machine Structures

Memory Allocation. Copyright : University of Illinois CS 241 Staff 1

Requirements, Partitioning, paging, and segmentation

Page 1. Goals for Today" TLB organization" CS162 Operating Systems and Systems Programming Lecture 11. Page Allocation and Replacement"

Optimizing Dynamic Memory Management

3/3/2014! Anthony D. Joseph!!CS162! UCB Spring 2014!

Lectures 13 & 14. memory management

Princeton University. Computer Science 217: Introduction to Programming Systems. Dynamic Memory Management

16 Sharing Main Memory Segmentation and Paging

CS162 Operating Systems and Systems Programming Lecture 14. Caching and Demand Paging

Run-time Environments - 3

15 Sharing Main Memory Segmentation and Paging

Operating Systems (1DT020 & 1TT802) Lecture 9 Memory Management : Demand paging & page replacement. Léon Mugwaneza

Memory Allocation II. CSE 351 Autumn Instructor: Justin Hsia

CS399 New Beginnings. Jonathan Walpole

CSCI-UA /2. Computer Systems Organization Lecture 19: Dynamic Memory Allocation: Basics

Chapter 8 & Chapter 9 Main Memory & Virtual Memory

Preview. Memory Management

Lecture Notes on Garbage Collection

Virtual Memory Management

Dynamic Memory Allocation: Basic Concepts

CS252 S05. Main memory management. Memory hardware. The scale of things. Memory hardware (cont.) Bottleneck

Memory Management. Disclaimer: some slides are adopted from book authors slides with permission 1

Operating System Labs. Yuanbin Wu

Dynamic Memory Allocation I Nov 5, 2002

Memory Management. Disclaimer: some slides are adopted from book authors slides with permission 1

Lecture 15 Garbage Collection

Princeton University Computer Science 217: Introduction to Programming Systems. Dynamic Memory Management

CS 31: Intro to Systems Pointers and Memory. Kevin Webb Swarthmore College October 2, 2018

Memory Management. Today. Next Time. Basic memory management Swapping Kernel memory allocation. Virtual memory

Today. Dynamic Memory Allocation: Basic Concepts. Dynamic Memory Allocation. Dynamic Memory Allocation. malloc Example. The malloc Package

Dynamic Memory Allocation: Basic Concepts

Dynamic Memory Allocation I

CMSC 330: Organization of Programming Languages

CSE506: Operating Systems CSE 506: Operating Systems

CIS Operating Systems Memory Management. Professor Qiang Zeng Fall 2017

Paging. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

Process s Address Space. Dynamic Memory. Backing the Heap. Dynamic memory allocation 3/29/2013. When a process starts the heap is empty

Memory Allocation I. CSE 351 Autumn Instructor: Justin Hsia

CS61C : Machine Structures

Today. Dynamic Memory Allocation: Basic Concepts. Dynamic Memory Allocation. Dynamic Memory Allocation. malloc Example. The malloc Package

Acknowledgements These slides are based on Kathryn McKinley s slides on garbage collection as well as E Christopher Lewis s slides

Page Replacement. (and other virtual memory policies) Kevin Webb Swarthmore College March 27, 2018

Virtual Memory. Chapter 8

Robust Memory Management Schemes

Memory Management william stallings, maurizio pizzonia - sistemi operativi

Dynamic Memory Management

Paging. Jinkyu Jeong Computer Systems Laboratory Sungkyunkwan University

CS162 Operating Systems and Systems Programming Lecture 14. Caching (Finished), Demand Paging

COSC Software Engineering. Lectures 14 and 15: The Heap and Dynamic Memory Allocation

EECS 482 Introduction to Operating Systems

CS140 Operating Systems Final December 12, 2007 OPEN BOOK, OPEN NOTES

Operating Systems. Memory Management. Lecture 9 Michael O Boyle

CS61C Midterm Review on C & Memory Management

CMSC 330: Organization of Programming Languages. Memory Management and Garbage Collection

Engine Support System. asyrani.com

Transcription:

Administrivia Project 2 due right now - As before, free extension if you are here - For SCPD students, put this at top of design doc: caf656 - For non-scpd students, put this: Midterm Tuesday - Open book, open notes (but not open notebook computer) - Covers first 10 lectures of course (including today) Midterm review section tomorrow Section for Project 3 next Friday I will monitor newsgroup/list for questions - Please put [midterm] in subject of questions about midterm Dynamic memory allocation Almost every useful program uses it - Gives wonderful functionality benefits Don t have to statically specify complex data structures Can have data grow as a function of input size Allows recursive procedures (stack growth) - But, can have a huge impact on performance Today: how to implement it - Lecture draws on [Wilson] (good survey from 1995) Some interesting facts: - Two or three line code change can have huge, non-obvious impact on how well allocator works (examples to come) - Proven: impossible to construct an always good allocator - Surprising result: after 35 years, memory management still poorly understood 1/36 2/36 Why is it hard? Satisfy arbitrary set of allocation and free s. Easy without free: set a pointer to the beginning of some big chunk of memory ( heap ) and increment on each allocation: More abstractly What an allocator must do: - Track which parts of memory in use, which parts are free - Ideal: no wasted space, no time overhead What the allocator cannot do: - Control order of the number and size of requested blocks - Change user ptrs = (bad) placement decisions permanent Problem: free creates holes ( fragmentation ) Result? Lots of free space but cannot satisfy request! The core fight: minimize fragmentation - App frees blocks in any order, creating holes in heap - Holes too small? cannot satisfy future requests 3/36 4/36 What is fragmentation really? Inability to use memory that is free Two factors required for fragmentation - Different lifetimes if adjacent objects die at different times, then fragmentation: - If they die at the same time, then no fragmentation: - Different sizes: If all requests the same size, then no fragmentation (that s why no external fragmentation w. paging): Important decisions Placement choice: where in free memory to put a requested block? - Freedom: can select any memory in the heap - Ideal: put block where it won t cause fragmentation later (impossible in general: requires future knowledge) Split free blocks to satisfy smaller requests? - Fights internal fragmentation - Freedom: can choose any larger block to split - One way: choose block with smallest remainder (best fit) Coalescing free blocks to yield larger blocks 5/36 - Freedom: when to coalesce (deferring can be good) fights external fragmentation 6/36

Impossible to solve fragmentation If you read allocation papers to find the best allocator - All discussions revolve around tradeoffs - The reason? There cannot be a best allocator Theoretical result: - For any possible allocation algorithm, there exist streams of allocation and deallocation requests that defeat the allocator and force it into severe fragmentation. How much fragmentation should we tolerate? - Let M = bytes of live data, n min = smallest allocation, n max = largest How much gross memory required? - Bad allocator: M (n max /n min ) (only ever uses a memory location for a single size) - Good allocator: M log(n max /n min ) Pathological examples Given allocation of 7 20-byte chunks - What s a bad stream of frees and then allocates? - Free every other chunk, then alloc 21 bytes Given a 128-byte limit on malloced space - What s a really bad combination of mallocs & frees? - Malloc 128 1-byte chunks, free every other - Malloc 32 2-byte chunks, free every other (1- & 2-byte) chunk - Malloc 16 4-byte chunks, free every other chunk... Next: two allocators (best fit, first fit) that, in practice, work pretty well - pretty well = 20% fragmentation under many workloads 7/36 8/36 Pathological examples Given allocation of 7 20-byte chunks Pathological examples Given allocation of 7 20-byte chunks - What s a bad stream of frees and then allocates? - Free every other chunk, then alloc 21 bytes Given a 128-byte limit on malloced space - What s a really bad combination of mallocs & frees? - Malloc 128 1-byte chunks, free every other - Malloc 32 2-byte chunks, free every other (1- & 2-byte) chunk - Malloc 16 4-byte chunks, free every other chunk... Next: two allocators (best fit, first fit) that, in practice, work pretty well - pretty well = 20% fragmentation under many workloads - What s a bad stream of frees and then allocates? - Free every other chunk, then alloc 21 bytes Given a 128-byte limit on malloced space - What s a really bad combination of mallocs & frees? - Malloc 128 1-byte chunks, free every other - Malloc 32 2-byte chunks, free every other (1- & 2-byte) chunk - Malloc 16 4-byte chunks, free every other chunk... Next: two allocators (best fit, first fit) that, in practice, work pretty well - pretty well = 20% fragmentation under many workloads 8/36 8/36 Best fit Best fit gone wrong Strategy: minimize fragmentation by allocating space from block that leaves smallest fragment - Data structure: heap is a list of free blocks, each has a header holding block size and pointers to next Simple bad case: allocate n, m (n < m) in alternating orders, free all the ns, then try to allocate an n + 1 Example: start with 100 bytes of memory - alloc 19, 21, 19, 21, 19 - Code: Search freelist for block closest in size to the request. (Exact match is ideal) - During free (usually) coalesce adjacent blocks Problem: Sawdust - Remainder so small that over time left with sawdust everywhere - Fortunately not a problem in practice - free 19, 19, 19: - alloc 20? Fails! (wasted space = 57 bytes) However, doesn t seem to happen in practice (though the way real programs behave suggest it easily could) 9/36 10/36

First fit Subtle pathology: LIFO FF Strategy: pick the first block that fits - Data structure: free list, sorted lifo, fifo, or by address - Code: scan list, take the first one LIFO: put free object on front of list. - Simple, but causes higher fragmentation - Potentially good for cache locality Address sort: order free blocks by address - Makes coalescing easy (just check if next block is free) - Also preserves empty/idle space (locality good when paging) FIFO: put free object at end of list - Gives similar fragmentation as address sort, but unclear why Storage management example of subtle impact of simple decisions LIFO first fit seems good: - Put object on front of list (cheap), hope same size used again (cheap + good locality) But, has big problems for simple allocation patterns: - E.g., repeatedly intermix short-lived 2n-byte allocations, with long-lived (n + 1)-byte allocations - Each time large object freed, a small chunk will be quickly taken, leaving useless fragment. Pathological fragmentation 11/36 12/36 First fit: Nuances First fit: Nuances First fit sorted by address order, in practice: - Blocks at front preferentially split, ones at back only split when no larger one found before them - Result? Seems to roughly sort free list by size - So? Makes first fit operationally similar to best fit: a first fit of a sorted list = best fit! Problem: sawdust at beginning of the list - Sorting of list forces a large requests to skip over many small blocks. Need to use a scalable heap organization Suppose memory has free blocks: - If allocation ops are 10 then 20, best fit wins - When is FF better than best fit? 13/36 First fit sorted by address order, in practice: - Blocks at front preferentially split, ones at back only split when no larger one found before them - Result? Seems to roughly sort free list by size - So? Makes first fit operationally similar to best fit: a first fit of a sorted list = best fit! Problem: sawdust at beginning of the list - Sorting of list forces a large requests to skip over many small blocks. Need to use a scalable heap organization Suppose memory has free blocks: - If allocation ops are 10 then 20, best fit wins - When is FF better than best fit? - Suppose allocation ops are 8, 12, then 12 = first fit wins 13/36 First/best fit: weird parallels Some worse ideas Both seem to perform roughly equivalently In fact the placement decisions of both are roughly identical under both randomized and real workloads! - No one knows why - Pretty strange since they seem pretty different Possible explanations: - First fit like best fit because over time its free list becomes sorted by size: the beginning of the free list accumulates small objects and so fits tend to be close to best - Both have implicit open space hueristic try not to cut into large open spaces: large blocks at end only used when have to be (e.g., first fit: skips over all smaller blocks) Worst-fit: - Strategy: fight against sawdust by splitting blocks to maximize leftover size - In real life seems to ensure that no large blocks around Next fit: - Strategy: use first fit, but remember where we found the last thing and start searching from there - Seems like a good idea, but tends to break down entire list Buddy systems: - Round up allocations to power of 2 to make management faster - Result? Heavy internal fragmentation 14/36 15/36

Slab allocation [Bonwick] Kernel allocates many instances of same structures - E.g., a 1.7 KB task struct for every process on system Often want contiguous physical memory (for DMA) Slab allocation optimizes for this case: - A slab is multiple pages of contiguous physical memory - A cache contains one or more slabs - Each cache stores only one kind of object (fixed size) Each slab is full, empty, or partial E.g., need new task struct? - Look in the task struct cache - If there is a partial slab, pick free task struct in that - Else, use empty, or may need to allocate new slab for cache Known patterns of real programs So far we ve treated programs as black boxes. Most real programs exhibit 1 or 2 (or all 3) of the following patterns of alloc/dealloc: - Ramps: accumulate data monotonically over time - Peaks: allocate many objects, use briefly, then free all - Plateaus: allocate many objects, use for a long time Advantages: speed, and no internal fragmentation 16/36 17/36 Pattern 1: ramps Pattern 2: peaks In a practical sense: ramp = no free! - Implication for fragmentation? - What happens if you evaluate allocator with ramp programs only? Peaks: allocate many objects, use briefly, then free all - Fragmentation a real danger - What happens if peak allocated from contiguous memory? - Interleave peak & ramp? Interleave two different peaks? 18/36 19/36 Exploiting peaks Pattern 3: Plateaus Peak phases: alloc a lot, then free everything - So have new allocation interface: alloc as before, but only support free of everything - Called arena allocation, obstack (object stack), or alloca/procedure call (by compiler people) Arena = a linked list of large chunks of memory - Advantages: alloc is a pointer increment, free is free No wasted space for tags or list pointers Plateaus: allocate many objects, use for a long time - What happens if overlap with peak or different plateau? 20/36 21/36

Fighting fragmentation Simple, fast segregated free lists Segregation = reduced fragmentation: - Allocated at same time freed at same time - Different type freed at different time Implementation observations: - Programs allocate small number of different sizes - Fragmentation at peak use more important than at low - Most allocations small (< 10 words) - Work done with allocated memory increases with size - Implications? Array of free lists for small sizes, tree for larger - Place blocks of same size on same page - Have count of allocated blocks: if goes to zero, can return page Pro: segregate sizes, no size tag, fast small alloc Con: worst case waste: 1 page per size even w/o free, after pessimal free waste 1 page per object 22/36 23/36 Typical space overheads Free list bookkeeping + alignment determine minimum allocatable size: - Store size of block - Pointers to next and previous freelist element Getting more space from OS On Unix, can use sbrk - E.g., to activate a new zero-filled page: - Machine enforced overhead: alignment. Allocator doesn t know type. Must align memory to conservative boundary - Minimum allocation unit? Space overhead when allocated? For large allocations, sbrk a bad idea - May want to give memory back to OS - Can t with sbrk unless big chunk last thing allocated - So allocate large chunk using mmap s MAP ANON 24/36 25/36 Faults + resumption = power Resuming after fault lets us emulate many things - every problem can be solved with layer of indirection Example: sub-page protection To protect sub-page region in paging system: - Set entire page to weakest permission; record in PT - Any access that violates perm will cause an access fault - Fault handler checks if page special, and if so, if access allowed. Continue or raise error, as appropriate 26/36 More fault resumption examples Emulate accessed bits: - Set page permissions to invalid. - On any access will get a fault: Mark as accessed Avoid save/restore of FP registers - Make first FP operation fault to detect usage Emulate non-existent instructions: - Give inst an illegal opcode; OS fault handler detects and emulates fake instruction Run OS on top of another OS! - Slam OS into normal process - When does something privileged, real OS gets woken up with a fault. - If op allowed, do it, otherwise kill. - IBM s VM/370. Vmware (sort of) 27/36

Not just for kernels User-level code can resume after faults, too mprotect protects memory sigaction catches signal after page fault - Return from signal handler restarts faulting instruction Many applications detailed by Appel & Li Example: concurrent snapshotting of process - Mark all of process s memory read-only w. mprotect - One thread starts writing all of memory to disk - Other thread keeps executing - On fault write that page to disk, make writable, resume Distributed shared memory Virtual memory allows us to go to memory or disk - But, can use the same idea to go anywhere! Even to another computer. Page across network rather than to disk. Faster, and allows network of workstations (NOW) 28/36 29/36 Persistent stores Idea: Objects that persist across program invocations - E.g., object-oriented database; useful for CAD/CAM type apps Achieve by memory-mapping a file But only write changes to file at end if commit - Use dirty bits to detect which pages must be written out - Or emulate dirty bits with mprotect/sigaction (using write faults) On 32-bit machine, store can be larger than memory - But single run of program won t access > 4GB of objects - Keep mapping betw. 32-bit mem ptrs and 64-bit disk offsets - Use faults to bring in pages from disk as necessary - After reading page, translate pointers known as swizzling Garbage collection In safe languages, run time knows about all pointers - So can move an object if you change all the pointers What memory locations might a program access? - Any objects whose pointers are currently in registers - Recursively, any pointers in objects it might access - Anything else is unreachable, or garbage; memory can be re-used Example: stop-and-copy garbage collection - Memory full? Temporarily pause program, allocate new heap - Copy all objects pointed to by registers into new heap Mark old copied objects as copied, record new location - Start scanning through new heap. For each pointer: Copied already? Adjust pointer to new location Not copied? Then copy it and adjust pointer - Free old heap program will never access it and continue 30/36 31/36 Concurrent garbage collection Idea: Stop & copy, but without the stop - Mutator thread runs program, collector concurrently does GC When collector invoked: - Protect from space & unscanned to space from mutator - Copy objects in registers into to space, resume mutator - All pointers in scanned to space point to to space - If mutator accesses unscanned area, fault, scan page, resume 1 2 3 from space scanned area to space unscanned area 4 5 6 mutator faults = on access Heap overflow detection Many GCed languages need fast allocation - E.g., in lisp, constantly allocating cons cells - Allocation can be as often as every 50 instructions Fast allocation is just to bump a pointer char *next_free; char *heap_limit; void *alloc (unsigned size) { if (next_free + size > heap_limit) /* 1 */ invoke_garbage_collector (); /* 2 */ char *ret = next_free; next_free += size; return ret; } But would be even faster to eliminate lines 1 & 2! 32/36 33/36

Heap overflow detection 2 Mark page at end of heap inaccessible - mprotect (heap limit, PAGE SIZE, PROT NONE); Program will allocate memory beyond end of heap Program will use memory and fault - Note: Depends on specifics of language - But many languages will touch allocated memory immediately Invoke garbage collector - Must now put just allocated object into new heap Note: requires more than just resumption - Faulting instruction must be resumed - But must resume with different target virtual address - Doable on most architectures since GC updates registers Reference counting Seemingly simpler GC scheme: - Each object has ref count of pointers to it - Increment when pointer set to it - Decremented when pointer killed (C++ destructors handy for such smart pointers ) - ref count == 0? Free object Works well for hierarchical data structures - E.g., pages of physical memory 34/36 35/36 Reference counting pros/cons Circular data structures always have ref count > 0 - No external pointers means lost memory Can do manually w/o PL support, but error-prone Potentially more efficient than real GC - No need to halt program to run collector - Avoids weird unpredictable latencies Potentially less efficient than real GC - With real GC, copying a pointer is cheap - With reference counting, must write ref count each time 36/36