Memory Management

50
Old-skool (and small embedded systems) with some generalizations Memory Management

Transcript of Memory Management

Page 1: Memory Management

Old-skool (and small embedded systems) with some generalizations

Memory Management

Page 2: Memory Management

An Example Memory Hierarchy

registers

on-chip L1cache (SRAM)

main memory(DRAM)

local secondary storage(local disks)

Larger, slower, and

cheaper (per byte)storagedevices

remote secondary storage(distributed file systems, Web servers)

Local disks hold files retrieved from disks on remote network servers.

Main memory holds disk blocks retrieved from local disks.

on-chip L2cache (SRAM)

L1 cache holds cache lines retrieved from the L2 cache memory.

CPU registers hold words retrieved from L1 cache.

L2 cache holds cache lines retrieved from main memory.

L0:

L1:

L2:

L3:

L4:

L5:

Smaller,faster,and

costlier(per byte)storage devices

Operating System must manage the hierarchy

Page 3: Memory Management

Memory Management

What is the programmers view of memory?

What memory abstraction is implemented by the operating system and exported to the user?

Page 4: Memory Management

No Memory Abstraction

What you see is what you get!

User Program

OS in RAM

0

0xFFF…

User Program

OS in ROM

0

User Program

Device Drivers

ROM

0

OS in RAM

Page 5: Memory Management

Multi-tasking with No Absraction

kernel memory

0

Process A

Process B

Process C

Page 6: Memory Management

Relocating Code?

JMP 8 04

MUL

JMP 8 048ADD8

12 12

Process A

Process B

04812

JMP 8

MUL

JMP 8

ADD

163801638416388

Static relocation tries to fix code when it is loaded

Page 7: Memory Management

Address Spaces

Create simple address space abstraction

Implement mechanism to map address space to physical memory location

Programmer writes code oblivious to memory location (and the world in general)

OS maps code to real addresses

Page 8: Memory Management

Base and Limit

Special registers

Set on context switch

Every address must be offset by the base

Every address must be checked by the limit

Hardware supported

Every address translated

kernel memory

0

Process A

Process B

Process C

Base Register

Limit Register

Page 9: Memory Management

Swapping

Operating System0

Process C

Process B

Process AProcess D

Process A

Memory can fragmentCompaction may be necessary (though

costly)

Page 10: Memory Management

Room to grow

Operating System

Process B

Process A

Operating System

B Program

A ProgramA heap

B heap

B Stack

A Stack

Page 11: Memory Management

Harsh Reality

Memory Matters

Memory is not unbounded It must be allocated and managed Many applications are memory dominated

Especially those based on complex, graph algorithms

Memory referencing bugs especially pernicious Effects are distant in both time and space

Memory performance is not uniform Cache and virtual memory effects can greatly affect program

performance Adapting program to characteristics of memory system can

lead to major speed improvements

Page 12: Memory Management

Dynamic Memory Allocation

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

Allocation In both cases the memory allocator provides an abstraction of

memory as a set of blocks Doles out free memory blocks to application

Will discuss simple explicit memory allocation by OS for processes

Application

Dynamic Memory Allocator

Heap Memory

Page 13: Memory Management

Memory Image

kernel memory

0

OS manages memory for process placement and growth

Process A

Process B

Process C

Book covers external data structure memory management

We’re covering managing memory using the free memory space itself (optimization in book)

Page 14: Memory Management

Malloc Package (for the OS)

#include <stdlib.h>

void *malloc(size_t size) If successful:

Returns a pointer to a memory block of at least size bytes, (typically) aligned to 8-byte boundary.

If size == 0, returns NULL If unsuccessful: returns NULL (0) and sets errno.

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 or realloc.

void *realloc(void *p, size_t size) Changes size of block p and returns pointer to new block. Contents of new block unchanged up to min of old and new size.

Page 15: Memory Management

Malloc Examplevoid foo(int n, int m) { int i, *p; /* allocate a block of n ints */ if ((p = (int *) malloc(n * sizeof(int))) == NULL) { perror("malloc"); exit(0); } for (i=0; i<n; i++) p[i] = i;

/* add m bytes to end of p block */ if ((p = (int *) realloc(p, (n+m) * sizeof(int))) == NULL) { perror("realloc"); exit(0); } for (i=n; i < n+m; i++) p[i] = i;

/* print new array */ for (i=0; i<n+m; i++) printf("%d\n", p[i]);

free(p); /* return p to available memory pool */}

Page 16: Memory Management

Assumptions

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

Page 17: Memory Management

Allocation Examplesp1 = malloc(4)

p2 = malloc(5)

p3 = malloc(6)

free(p2)

p4 = malloc(2)

Page 18: Memory Management

Constraints

Operating System Issues arbitrary sequence of allocation and free requests Free requests must correspond to an allocated block

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 Must align blocks so they satisfy all alignment requirements Can only manipulate and modify free memory Cannot compact

Page 19: Memory Management

Goals of Good malloc/free

Primary goals Good time performance for malloc and free

Ideally should take constant time (not always possible)Should certainly not take linear time in the number of blocks

Good space utilizationAllocated structures should be large fraction of the heap.Want to minimize “fragmentation”.

Some other goals Robust

Can check that free(p1) is on a valid allocated object p1Can check that memory references are to allocated space

Page 20: Memory Management

Internal FragmentationPoor memory utilization caused by fragmentation.

Comes in two forms: internal and external fragmentation

Internal fragmentation For some block, internal fragmentation is the difference between

the block size and the payload size.

Caused by overhead of maintaining memory management 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.

payloadInternal fragmentation

block

Internal fragmentation

Page 21: Memory Management

External Fragmentation

p1 = malloc(4)

p2 = malloc(5)

p3 = malloc(6)

free(p2)

p4 = malloc(6)oops!

Occurs when there is enough aggregate memory, but no singlefree block is large enough

External fragmentation depends on the pattern of future requests, andthus is difficult to measure.

Page 22: Memory Management

Implementation Issues How do we know how much memory to free just

given a pointer?

How do we keep track of the free blocks?

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 a freed block?

p1 = malloc(1)

p0

free(p0)

Page 23: Memory Management

Knowing How Much to FreeStandard method

Keep the length of a block in the word preceding the block.This word is often called the header field or header

Requires an extra word for every allocated block

free(p0)

p0 = malloc(4) p0

Block size data

5

Page 24: Memory Management

Keeping Track of Free Blocks

Method 1: Implicit list using lengths -- links all blocks

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

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

Method 4: Blocks sorted by size Can use a balanced tree (e.g. Red-Black tree) with pointers

within each free block, and the length used as a key

5 4 26

5 4 26

Page 25: Memory Management

Method 1: 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 two (mask out low order bit when reading size).

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

Page 26: Memory Management

Implicit List: Finding a Free BlockFirst 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 from location of end of previous search Research suggests that fragmentation is worse

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

p = start; while ((p < end) || \\ not passed end (*p & 1) || \\ already allocated (*p <= len)); \\ too small

Page 27: Memory Management

Implicit List: Allocating in Free Block

Allocating in a free block - splitting Since allocated space might be smaller than free space, we

might want to split the block

void addblock(ptr p, int len) { int newsize = ((len + 1) >> 1) << 1; // add 1 and round up int oldsize = *p & -2; // mask out low bit *p = newsize | 1; // set new length if (newsize < oldsize) *(p+newsize) = oldsize - newsize; // set length in remaining} // part of block

4 4 26

4 24

p

24

addblock(p, 2)

Page 28: Memory Management

Implicit List: Freeing a Block

Simplest implementation: Only need to clear allocated flag

void free_block(ptr p) { *p = *p & -2} 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)Oops!

Page 29: Memory Management

Implicit List: Coalescing

Join (coelesce) 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

void free_block(ptr p) { *p = *p & -2; // clear allocated flag next = p + *p; // find next block if ((*next & 1) == 0) *p = *p + *next; // add to this block if} // not allocated

Page 30: Memory Management

Implicit List: Bidirectional Coalescing 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!

size

1 word

Format ofallocated andfree blocks

payload andpadding

a = 1: allocated block a = 0: free block

size: total block size

payload: application data(allocated blocks only)

a

size aBoundary tag (footer)

4 4 4 4 6 46 4

Header

Page 31: Memory Management

Constant Time Coalescing

allocated

allocated

allocated

free

free

allocated

free

free

block beingfreed

Case 1 Case 2 Case 3 Case 4

Page 32: Memory Management

m1 1

Constant Time Coalescing (Case 1)

m1 1

n 1

n 1

m2 1

m2 1

m1 1

m1 1

n 0

n 0

m2 1

m2 1

Page 33: Memory Management

m1 1

Constant Time Coalescing (Case 2)

m1 1

n+m2 0

n+m2 0

m1 1

m1 1

n 1

n 1

m2 0

m2 0

Page 34: Memory Management

m1 0

Constant Time Coalescing (Case 3)

m1 0

n 1

n 1

m2 1

m2 1

n+m1 0

n+m1 0

m2 1

m2 1

Page 35: Memory Management

m1 0

Constant Time Coalescing (Case 4)

m1 0

n 1

n 1

m2 0

m2 0

n+m1+m2 0

n+m1+m2 0

Page 36: Memory Management

Summary of Key Allocator PoliciesPlacement 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 the 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 adjacent blocks each time free is

called Deferred coalescing: try to improve performance of free by

deferring coalescing until needed. e.g., Coalesce as you scan the free list for malloc. Coalesce when the amount of external fragmentation reaches some

threshold.

Page 37: Memory Management

Implicit Lists: Summary Implementation: very simple

Allocate: linear time worst case

Free: 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 allocate. Used in many special purpose applications.

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

Page 38: Memory Management

Keeping Track of Free Blocks Method 1: Implicit list using lengths -- links all blocks

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

Method 3: Segregated free lists Different free lists for different size classes

Method 4: Blocks sorted by size (not discussed) Can use a balanced tree (e.g. Red-Black tree) with pointers

within each free block, and the length used as a key

5 4 26

5 4 26

Page 39: Memory Management

Explicit Free Lists

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

A B C

4 4 4 4 66 44 4 4

Forward links

Back links

A B

C

Page 40: Memory Management

Allocating From Explicit Free Lists

free block

pred succ

free block

pred succ

Before:

After:(with splitting)

Page 41: Memory Management

Freeing With Explicit Free Lists

Insertion policy: Where in the free list do you put a newly freed block? LIFO (last-in-first-out) policy

Insert freed block at the beginning of the free listPro: simple and constant timeCon: studies suggest fragmentation is worse than address

ordered. 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

Page 42: Memory Management

Freeing With a LIFO Policy

Case 1: a-a-a Insert self at beginning of

free list

Case 2: a-a-f Splice out next, coalesce

self and next, and add to beginning of free list

pred (p) succ (s)

selfa a

p s

selfa f

before:

p s

faafter:

Page 43: Memory Management

Freeing With a LIFO Policy (cont)

Case 3: f-a-a Splice out prev, coalesce

with self, and add to beginning of free list

Case 4: f-a-f Splice out prev and next,

coalesce with self, and add to beginning of list

p s

selff a

before:

p s

f aafter:

p1 s1

selff f

before:

fafter:

p2 s2

p1 s1 p2 s2

Page 44: Memory Management

Explicit List Summary

Comparison to implicit list: Allocate is linear time in number of free blocks instead of

total blocks -- much faster allocates when most of the memory is full

Slightly more complicated allocate and free since needs to splice blocks in and out of the list

Some extra space for the links (2 extra words needed for each block)

Main use of linked lists is in conjunction with segregated free lists Keep multiple linked lists of different size classes, or

possibly for different types of objects

Page 45: Memory Management

Keeping Track of Free Blocks

Method 1: Implicit list using lengths -- links all blocks

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

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

Method 4: Blocks sorted by size Can use a balanced tree (e.g. Red-Black tree) with pointers

within each free block, and the length used as a key

5 4 26

5 4 26

Page 46: Memory Management

Segregated Storage

Each size class has its own collection of blocks

1-2

3

4

5-8

9-16

Often have separate size class for every small size (2,3,4,…)

For larger sizes typically have a size class for each power of 2

Page 47: Memory Management

Simple Segregated StorageSeparate 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, request chunk of data, divide into the desired

size blocks, and add to the list Constant time

To free a block: Add to free list

Tradeoffs: No header or footer Fast, but can fragment badly because there is no coalescing

Page 48: Memory Management

Segregated FitsArray of free lists, each one for some size class

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

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

Page 49: Memory Management

For More Info on Allocators

D. Knuth, “The Art of Computer Programming, Second Edition”, Addison Wesley, 1973 The classic reference on dynamic storage allocation

Wilson et al, “Dynamic Storage Allocation: A Survey and Critical Review”, Proc. 1995 Int’l Workshop on Memory Management, Kinross, Scotland, Sept, 1995. Comprehensive survey Available from CS:APP student site (csapp.cs.cmu.edu)

Page 50: Memory Management

Conclusion

No memory abstraction great for purpose-built systems: static, non-changing, and single-task

Basic relocation needed for dynamic systems

Base+limit works for small embedded devices or very simple somewhat general purpose systems

Let the OS manage free space in memory

Many embedded OS and application specific OSs still use these techniques --- not dead yet!

More advanced memory abstraction needed for desktop systems and advanced embedded systems