30.10.2014 Views

Free - Suif - Stanford University

Free - Suif - Stanford University

Free - Suif - Stanford University

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Jeffrey D. Ullman<br />

<strong>Stanford</strong> <strong>University</strong>


2<br />

• Programming is easier if the run-time system<br />

“garbage-collects” – makes space belonging to<br />

unusable data available for reuse.<br />

• Java does it; C does not.<br />

• But stack allocation in C gets some of the advantage.


1. Speed – low overhead for garbage collector.<br />

2. Little program interruption.<br />

• Many collectors shut down the program to hunt for<br />

garbage.<br />

3. Locality – data that is used together is placed<br />

together on pages, cache-lines.<br />

• If the garbage collector moves data, you have some<br />

choices where you put things.<br />

3


4<br />

• There is a root set of data that is a-priori<br />

reachable.<br />

• Example: In Java, root set = static class variables<br />

plus variables on run-time stack.<br />

• Reachable data: root set plus anything<br />

referenced by something reachable.<br />

• Question: Why doesn’t the notion of<br />

“reachability” make sense for C? Why is it<br />

OK for Java?


5<br />

• Things requiring space are “objects.”<br />

• Available space is in a heap – large area<br />

managed by the run-time system.<br />

• Allocator finds space for new objects.<br />

• Space for an object is a chunk.<br />

• Garbage collector finds unusable objects,<br />

returns their space to the heap, and maybe<br />

moves objects around in the heap.


6<br />

<strong>Free</strong> List<br />

. . .<br />

Object 1 Object 2<br />

Object 3


7<br />

1. Chunks are either allocated or free.<br />

2. <strong>Free</strong> chunks are linked in some sort of<br />

available space list.<br />

• Why do the links not waste space?<br />

3. Chunks record their length so you know where<br />

the next chunk begins.<br />

• Seems to waste space. Why needed?<br />

4. Adjacent free chunks may not be combined<br />

into one larger chunk.<br />

• Why would we let that happen?


8<br />

1. Via the free-space list.<br />

2. Following references in the objects that<br />

appear in the allocated chunks.<br />

3. In order through the heap.<br />

• That’s why it is useful to have the length of each<br />

chunk in the chunk itself.


• Typically a program needs chunks of various<br />

sizes.<br />

• Fragmentation problem: free chunks become<br />

small, disconnected pieces, so you can’t find<br />

space for a large object.<br />

• Allocation by best fit requires examination of<br />

the entire free list.<br />

• First fit is more efficient, but can give an object<br />

a much larger chunk than it needs.<br />

9


10<br />

• Option: keep many free lists, each with an<br />

exponentially growing range of sizes.<br />

• Then first-fit can’t waste more than 50% of the<br />

space.<br />

• If there are few classes, there will be few sizes of free<br />

chunks, so maybe no waste.<br />

• More extreme: allow only a fixed set of sizes,<br />

e.g., Fibonacci numbers.<br />

• Allocation is trivial since there is no decision.<br />

• But usually wastes space.


11<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based


12<br />

• The simplest (but imperfect) method is to<br />

give each object a reference count = number<br />

of references to this object.<br />

• Assumes objects have no internal references or<br />

these can be excluded.<br />

• Initially, object has one reference.<br />

• If reference count becomes 0, object is<br />

garbage and its space becomes available.


Integer i = new Integer(10);<br />

• Integer object is created with RC = 1.<br />

• Consider execution of j = k; (j, k are Integer<br />

references.)<br />

• Object referenced by j has RC--.<br />

• Object referenced by k has RC++.<br />

13


• If an object reaches RC=0, its chunk is garbagecollected<br />

(added to the free list), and the<br />

references within that object effectively<br />

disappear.<br />

• Follow these references and decrement RC in<br />

the objects reached.<br />

• That may result in more objects with RC=0,<br />

leading to recursive collection.<br />

14


15<br />

Root<br />

Object<br />

We remove<br />

this link during<br />

program<br />

execution<br />

A(1)<br />

B(2)<br />

E.g., object B has<br />

reference count 2,<br />

from A and D<br />

C(1)<br />

D(2)<br />

E(1)


16<br />

Root<br />

Object<br />

Reference count<br />

for A drops to zero<br />

A(0)<br />

B(2)<br />

C(1)<br />

D(2)<br />

E(1)


17<br />

Root<br />

Object<br />

So remove A.<br />

Reference count for C drops<br />

to zero, wile the count for<br />

B drops to 1.<br />

B(1)<br />

C(0)<br />

D(2)<br />

E(1)


18<br />

Root<br />

Object<br />

Remove C. Reference count<br />

for D drops to one<br />

B, D, and E are<br />

garbage, but their<br />

reference counts<br />

are all > 0. They<br />

never get collected.<br />

D(1)<br />

B(1)<br />

E(1)


19<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Basic


• Mark: Starting from the root set, search all<br />

references to discover reachable objects.<br />

• Sweep : Return all unreached objects to the free<br />

list.<br />

20


<strong>Free</strong> = not holding an object; available for<br />

allocation.<br />

Unreached = Holds an object, but has not yet<br />

been reached from the root set.<br />

Unscanned = Reached from the root set, but<br />

its references not yet followed.<br />

Scanned = Reached and references followed.<br />

21


1. Assume all objects in Unreached state.<br />

2. Start with the root set. Put them in state<br />

Unscanned.<br />

3. while Unscanned objects remain do<br />

examine one of these objects;<br />

make its state be Scanned;<br />

add all referenced objects to Unscanned<br />

list if they were previously Unreached;<br />

end;<br />

22


23<br />

• Place all objects still in the Unreached state into<br />

the <strong>Free</strong> state.<br />

• Question: how do we find all the chunks in the<br />

heap?<br />

• Place all objects in the Scanned state into the<br />

Unreached state.<br />

• To prepare for the next mark-and-sweep.


24<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Basic<br />

Baker’s


25<br />

• Problem: The basic algorithm takes time<br />

proportional to the heap size.<br />

• Because you must visit all objects to see if they are<br />

Unreached.<br />

• Baker’s algorithm keeps a list of all allocated<br />

chucks of memory, as well as the <strong>Free</strong> list.


26<br />

• Key change: In the sweep, look only at the<br />

list of allocated chunks.<br />

• Those that are not marked as Scanned are<br />

garbage and are moved to the <strong>Free</strong> list.<br />

• Those in the Scanned state are put in the<br />

Unreached state.<br />

• For the next collection.<br />

• Question: What is the downside to linking<br />

the allocated chunks?


27<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Basic Baker’s Basic


• Compact = move reachable objects to<br />

contiguous memory.<br />

1. Locality – fewer pages or cache-lines needed<br />

to hold the active data.<br />

2. Avoids fragmentation – after GC, the free<br />

space is one large chunk, so there is space to<br />

store large objects.<br />

28


29<br />

1. Mark reachable objects as before.<br />

2. Create a table (hash?) from reached chunks<br />

to new locations for the objects in those<br />

chunks.<br />

3. Scan chunks from low end of heap.<br />

4. Maintain pointer free that counts how much<br />

space is used by reached objects so far.<br />

• That is, free points to the first byte that has not<br />

been used for the reached objects so far.


30<br />

5. Move all reached objects to their new<br />

locations, and also retarget all references in<br />

those objects to the new locations.<br />

• Use the table of new locations.<br />

6. Retarget root references.


31<br />

Consider first chunk,<br />

but it is free, so skip<br />

over it<br />

free


32<br />

Enter into table that<br />

this is where the<br />

first object will go<br />

Consider first object<br />

free<br />

New address is<br />

current value of “free”


33<br />

Consider next chunk,<br />

but it is free<br />

free<br />

Advance “free” to<br />

next available byte


34<br />

Consider next chunk<br />

free<br />

New address is current “free”;<br />

enter that into table


35<br />

free<br />

Advance “free” to<br />

the next available byte


36<br />

Eventually advance to<br />

the next used chunk<br />

free<br />

New address is current “free”;<br />

enter that into table


37<br />

free<br />

Advance “free” to<br />

the next available byte


38<br />

Change internal pointer to<br />

second object to point to new<br />

location of second object<br />

Start the Compact phase.<br />

Move first object<br />

to its new location<br />

free


39<br />

Change internal pointer to<br />

third object to point to new<br />

location of third object<br />

Move second object<br />

to its new location<br />

free


40<br />

Change internal pointer to<br />

first object to point to new<br />

location of first object<br />

Move third object<br />

to its new location<br />

free


41<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Basic Baker’s Basic Cheney’s


• Uses 2 heaps.<br />

• Allocate space in one.<br />

• When the first is full, copy reachable objects<br />

to the second heap.<br />

• Then, swap roles.<br />

42


43<br />

• To copy: maintain table of new locations for<br />

the reachable objects.<br />

• As soon as an object is reached, give it the<br />

next available bytes in the second heap.<br />

• As you scan objects, adjust their references to<br />

point to second heap.<br />

• Trick: scan recursively, starting with the root<br />

objects, so by the time you finish with an object,<br />

all the objects it references have their new<br />

locations.


Object scan(Object: O) {<br />

select new location o for O in the other heap,<br />

and enter that location into table;<br />

for (each reference r in O to an object P)<br />

if (exists entry in the table for P)<br />

r = that entry;<br />

else<br />

r = scan(P);<br />

return o;<br />

}<br />

44


45<br />

• There is an analogy between program memory<br />

management and file-system disk<br />

management:<br />

• Heap :: volume or partition<br />

• Object :: file<br />

• Cache line or page :: track or cylinder


• A file system can also benefit from compaction,<br />

for faster file access, even if there is no need for<br />

GC.<br />

• Question: can you garbage collect a file system?<br />

• Modern distributed file systems replicate files in<br />

several places for availability and fault<br />

tolerance.<br />

• Consider a replicated volume holding many<br />

files.<br />

• Each copy of the volume holds the same files, but<br />

the location within the volume is unimportant.<br />

46


• Because the volume is replicated, we can take<br />

one copy “off-line” and compact it using the<br />

basic compaction algorithm.<br />

• Other copies are still available for reads and<br />

writes.<br />

• After the compacted copy of the volume comes<br />

back on-line, create within it copies of any files<br />

written to the other volume-copies while it was<br />

off-line.<br />

47


48<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Incremental<br />

Partial<br />

Basic Baker’s Basic Cheney’s


1. Incremental – run garbage collection in<br />

parallel with mutation (execution of the<br />

program).<br />

2. Partial – stop the mutation, but only briefly,<br />

to garbage collect a part of the heap.<br />

49


50<br />

• OK to mark garbage as reachable.<br />

• Not OK to GC a reachable object.<br />

• If a reference r within a Scanned object is<br />

mutated to point to an Unreached object,<br />

the latter may be garbage-collected anyway.<br />

• Subtlety: How can a reference be made to point<br />

to an Unreached object?<br />

• Answer: a new object O be created during the<br />

marking, and a scanned object may refer to O.


51<br />

• Intercept every write of a reference in a<br />

scanned object.<br />

• Place the new object referred to on the<br />

Unscanned list.<br />

• A trick: protect all pages containing Scanned<br />

objects.<br />

• A hardware interrupt will invoke the fixup.


52<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Incremental<br />

Partial<br />

Basic Baker’s Basic Cheney’s<br />

Generational


53<br />

• “Most objects die young.”<br />

• But those that survive one GC are likely to survive<br />

many.<br />

• Tailor GC to spend more time on regions of the<br />

heap where objects have just been created.<br />

• Gives a better ratio of reclaimed space per unit time.


54<br />

• We collect one part(ition) of the heap.<br />

• The target set.<br />

• Other objects are the stable set.<br />

• We maintain for each partition a remembered<br />

set of those objects in the stable set that refer<br />

to objects in the target set.<br />

• Write barriers can be used to maintain the<br />

remembered set.


55<br />

• To collect a part of the heap:<br />

1. Add the remembered set for that partition to the<br />

root set.<br />

2. Do a reachability analysis (mark) as before.<br />

• Note the resulting Scanned set may include<br />

garbage. Why?


56<br />

In the remembered set<br />

The target<br />

partition<br />

Not reached from<br />

the root set<br />

Stable set


57<br />

• Divide the heap into partitions P 0 , P 1 , …<br />

• Each partition holds older objects than the one before<br />

it.<br />

• Create new objects in P 0 , until it fills up.<br />

• Garbage collect P 0 only, and move the reachable<br />

objects to P 1 .<br />

• When P 1 fills, garbage collect P 0 and P 1 , and put<br />

the reachable objects in P 2 .<br />

• In general: When P i fills, collect P 0 , P 1 , … ,P i and<br />

put the reachable objects in P i +1 .


58<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Incremental<br />

Partial<br />

Basic Baker’s Basic Cheney’s<br />

Generational<br />

Train


59<br />

• Problem with generational GC:<br />

1. Occasional total collection (last partition).<br />

2. Long-lived objects move many times.<br />

• Train algorithm useful for long-lived objects.<br />

• Replaces higher-numbered partitions in<br />

generational GC.<br />

• I.e., first partition is not part of the “train,” and is used for<br />

new objects just as in the previous algorithm.


60<br />

Train 1<br />

Car 11<br />

Car 12<br />

Car 13<br />

Train 2<br />

.<br />

.<br />

.<br />

Car 21<br />

Car 22<br />

. . .<br />

Car 2k<br />

Train n<br />

Car n1<br />

Car n2


61<br />

• There can be any number of trains, and each<br />

train can have any number of cars.<br />

• You need to decide on a policy that gives a<br />

reasonable number of each.<br />

• Objects entering the system can:<br />

• Be placed in the last car of the last train,<br />

• Or start a new car at the end of the last train,<br />

• Or even start a new train (which becomes the last).


62<br />

• Each car has a remembered set of references<br />

from<br />

1. Higher-numbered trains and<br />

2. Higher-numbered cars of the same train.<br />

• Important: since we only garbage-collect first<br />

cars and first trains, we never need to worry<br />

about “forward” references (to later trains or<br />

later cars of the same train).


63<br />

1. Collect the first car of the first train.<br />

• Like we collect P 0 in generational GC.<br />

2. Collect the entire first train if there are no<br />

references from the root set or other trains.<br />

• This is how we find and eliminate large, cyclic<br />

garbage structures.


1. Do a partial collection as before, using<br />

every other car/train as the stable set.<br />

2. Move all Scanned (reachable) objects of<br />

the first car somewhere else.<br />

3. Get rid of the car.<br />

64


65<br />

• If object o has a reference from another train,<br />

pick one such train and move o to that train.<br />

• Same car as reference, if possible, else make new<br />

car.<br />

• If references only from root set or first train,<br />

move o to another car of first train, or create<br />

new car.


66<br />

• The problem: it is possible that when collecting<br />

the first car, nothing is garbage.<br />

• We may then create a new last car of the first<br />

train with the same objects as the old first car.<br />

• Situation is rare, but possible, requiring:<br />

1. A cyclic, but nongarbage structure in the first train.<br />

2. A mutator that changes references to the first train<br />

with perfect timing so that we never see anything<br />

in the remembered sets for the first car from<br />

outside the first train.


67<br />

• If that happens, we go into panic mode, which<br />

requires that:<br />

1. If a reference to any object in the first train is<br />

rewritten, we make the new reference a “dummy”<br />

member of the root set.<br />

2. During panic-mode GC, if we encounter a<br />

reference from the dummy “root set,” we move<br />

the referenced object to another train.<br />

• Eventually, all reachable objects will leave the<br />

first train, leaving cyclic garbage, and we can<br />

delete the first train.


68<br />

Garbage Collectors<br />

Reference-<br />

Counters<br />

Trace-<br />

Based<br />

Stop-the-World<br />

Short-Pause<br />

Mark-and-<br />

Sweep<br />

Mark-and-<br />

Compact<br />

Incremental<br />

Partial<br />

Basic Baker’s Basic Cheney’s<br />

Generational<br />

Train

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!