The Memory Fragmentation Problem: Solved? Mark S. Johnstone Paul R. Wilson Presented by David Oren...

Post on 20-Dec-2015

216 views 1 download

Tags:

Transcript of The Memory Fragmentation Problem: Solved? Mark S. Johnstone Paul R. Wilson Presented by David Oren...

The Memory Fragmentation Problem: Solved?

Mark S. JohnstonePaul R. Wilson

Presented by David Oren (doren@math.tau.ac.il)

Dynamic Memory Allocation

Memory is Allocated by the running process Freed when no longer needed

The allocator handles those requests, and keeps track of used and unused memory

No garbage collection, no compaction

What Is Fragmentation?

Inefficient use of memory, or…The inability to use free memoryThere are two types of

fragmentation: External fragmentation Internal fragmentation

External Fragmentation

Arises when free blocks are available, but cannot be used to hold objects of the sizes requested

This can have several reasons: The free blocks are too small The allocator is unable to split larger

blocks

Internal Fragmentation

Arises when a block is allocated, but it is larger than needed: the rest is wasted

This can have several reasons: Architecture constraints Allocator policy

Allocator policies

Policies fall into three basic categories: Sequential fits Segregated free lists Buddy systems

Sequential fit

Classic implementations: Doubly linked linear or circular list FIFO, LIFO or address order First, next of best fit

Instances of policiesThere are more efficient

implementations

First fit

Search the list of free blocks from the beginning

Use first large enough block, split if needed

Easy to implement Lots of small blocks at the beginning

Next fit

A common optimization on first fitEach search begins where the

previous one ended No accumulation of small blocks Generally increases fragmentation

Best fit

Use the smallest block large enough Minimize the amount of wasted

space Sequential best-fit is inefficient

Segregated free lists

Use a set of lists of free blocksEach list hold blocks of a given size

A freed block is pushed onto the relevant list

When a block is needed, the relevant list is used

Simple segregated storage

All blocks in the list are of the same size

Large free blocks are not splitSmaller blocks are not coalesced Efficient implementation Internal fragmentation

Segregated fit algorithms

Free list contain several sizesWhen memory is requested

The relevant list is (sequentially) searched

If no block is found, the other lists are searched, and the block is split

Freed blocks are coalesced Approximates best-fit

Buddy systems

Memory is conceptually split into “buddies”

Only “buddies” may be coalesced Very easy coalescing Internal fragmentation

(but may use several buddy-systems to reduce it)

Test Method

Allocators were traditionally tested with synthetically generated allocations

However, we cannot be certain that they resemble real programs

Therefore, the test was conducted using real programs

Test Program Criterions

Allocation intensive programsPrograms with large amount of live

dataA wide variety of program typesAvoiding over-representation of one

typeNon-leaking programs

Test Programs

In the end, eight programs were chosen

They present a variety of different memory usage requirements

It can still be argued whether they are representative of real-life problems

Test Programs

Espressogcc (2.5.1)GhostscriptGrobner

HyperLRUsimP2CPerl

Program Statistics

Program Mem alloc’d Num. objects Live mem Live objects

Espresso 104, 388 1,672,889 263 4,390

GCC 17,972 721,353 2,320 86,872

Ghostscript 48,993 566,542 1,110 15,376

Grobner 3,986 163,310 145 15,376

Hyper 7,378 108,720 2,049 297

LRUsim 1,397 39,103 1,380 39,039

P2C 4,641 194,997 393 12,652

Perl 33,041 1,600,560 69 1,971

Testing Methods

The goal is to test policy, not implementation

The allocators were tested offline, not incorporated into running programs

Runtime was not tested

Testing Methods (Cont.)

Testing was done in three steps: Replacing memory allocation functions with

new ones, which create a trace of calls Reading the trace, and extracting statistics

about the program Reading the trace, and calling the allocation

functions of the policy being tested (keeping track of allocation from the OS)

Removing Overhead

Header and footer overhead Less memory was allocated in the

simulation than the program requestedAlignment overhead

The amount of allocated memory was multiplied by 16

The amount requested from the OS was divided by 16

Defining Fragmentation

There are different definitions of fragmentation

We define it as percentages over and above the amount of live data

Fragmentation can be measured in several ways

Measuring Fragmentation

We have chosen two methods: Maximum amount of memory used by

the allocator, relative to the amount requested by the program, at the point of maximum memory usage

Maximum amount of memory used by the allocator, relative to the maximum amount of live memory

Other Measures

Other measures are also interestingThere is no “right” way to measure

fragmentationFragmentation should be measured

for those conditions under which it is a problem

Experimental Error

Generally, memory was requested from the OS in blocks of 4kb

The measurement of the heap size can be an over-estimate by no more than 4kb

This amount should be divided by 16, yielding 256 bytes

Results

2.3 2.288.04

53.4

73.6

2.23

01020304050607080

Fra

g.

(%)

Strategy

There is a relation between the successful policies They all immediately coalesce memory They reallocate objects that have died

recentlyThis can be called a good strategy

Best fit

Tries to use small free blocksThis gives neighbors of large blocks

time to dieThey are merged into yet larger

blocksWhen a large block is split, it is likely

to be used again

AO first-fit

Allocate blocks from one end of the heap

Blocks at the other end have more time to die and merge into larger blocks

This is obviously not true for next-fit policies

Lifetime

Objects allocated at the same time tend to die at the same time

On average, after 2.5Kb of allocation, 90% of all objects have both neighbors free

It pays to wait a short time after an object is freed

Object size

On average 90% of allocated objects have 6 sizes

Many memory requests are for objects of the same size as freed ones

Good allocators should use this factThere is no reason to increase

internal fragmentation

Conclusions

“…we arrive at the conclusion that the fragmentation problem is a problem of recognizing that good allocation policies already exist, and have inexpensive implementations.”