automatic garbage collection reference counting
play

Automatic Garbage Collection Reference counting Automatically free - PDF document

Automatic Garbage Collection Reference counting Automatically free dead objects For each heap-allocated object, maintain count of # of pointers to object no dangling pointers , no storage leaks (maybe) when create object, ref count = 0


  1. Automatic Garbage Collection Reference counting Automatically free dead objects For each heap-allocated object, maintain count of # of pointers to object • no dangling pointers , no storage leaks (maybe) • when create object, ref count = 0 • can have faster allocation, better memory locality • when create new ref to object, increment ref count • when remove ref to object, decrement ref count General styles: • if ref count goes to zero, then delete object • reference counting • tracing • mark/sweep, mark/compact proc foo() { • copying a := new Cons; b := new Blob; Adjectives: c := bar(a, b); • generational return c; • conservative } • incremental • parallel proc bar(x, y) { l := x; • distributed l.head := y; t := l.tail; return t; } Craig Chambers 183 CSE 501 Craig Chambers 184 CSE 501 Evaluation of reference counting Tracing collectors + local, incremental work Start with a set of root pointers + little/no language support required • global vars + local ⇒ feasible for distributed systems • contents of stack & registers − cannot reclaim cyclic structures Traverse objects transitively from roots − uses malloc/free back-end ⇒ heap gets fragmented • visits reachable objects − high run-time overhead (10-20%) • all unvisited objects are garbage • can delay processing of ptrs from stack (deferred reference counting [Deutsch & Bobrow 76]) − space cost Issues: − no bound on time to reclaim • how to identify pointers? • in what order to visit objects? • how to know an object is visited? • how to free unvisited objects? • how to allocate new objects? • how to synchronize collector and program ( mutator )? Craig Chambers 185 CSE 501 Craig Chambers 186 CSE 501

  2. Identifying pointers Mark/sweep collection “ Accurate ”: always know unambiguously where pointers are [McCarthy 60]: stop-the-world tracing collector Use some subset of the following to do this: • static type info & compiler support Stop the application when heap fills • run-time tagging scheme • run-time conventions about where pointers can be Trace reachable objects • set mark bit in each object • tracing control: Conservative [Bartlett 88, Boehm & Weiser 88]: • depth-first, recursively using separate stack assume anything that looks like a pointer might a pointer, • depth-first, using pointer reversal & mark target object reachable + supports GC of C, C++, etc. Sweep through all of memory • add unmarked objects to free list What “looks” like a pointer? • clear marks of marked objects • most optimistic: just aligned pointers to beginning of objects • what about interior pointers? Restart mutator off-the-end pointers? • allocate new objects using free list unaligned pointers? Miss encoded pointers (e.g. xor’d ptrs), ptrs in files, ... Craig Chambers 187 CSE 501 Craig Chambers 188 CSE 501 Evaluation of mark/sweep collection Some improvements + collects cyclic structures Mark/ compact collection: + simple to implement when sweeping through memory, compact rather than free • all free memory in one block at end of memory space; no free lists − “embarrassing pause” problem + reduces fragmentation − poor memory locality + fast allocation • when tracing, sweeping − slower to sweep • when allocating, dereferencing due to heap fragmentation − changes pointers − not suitable for distributed systems ⇒ requires accurate info about pointers Generational mark/ ∗ Incremental and/or parallel mark/ ∗ + (greatly) reduce embarrassing pause problem + may be suitable for real-time collection − more complex Craig Chambers 189 CSE 501 Craig Chambers 190 CSE 501

  3. Copying collection Evaluation of copying collection + collects cyclic structures [Cheney 70] + supports compaction, fast allocation automatically + no separate traversal stack required Divide heap into two equal-sized semi-spaces + only visits reachable objects, not all objects • mutator allocates in from-space • to-space is empty − requires twice the (virtual) memory, physical memory sloshes back and forth When from-space fills, do a GC: • could benefit from OS support • visit objects referenced by roots − “embarrassing pause” problem still • when visit object: − copying can be slow • copy to to-space − changes pointers • leave forwarding pointer in from-space version • if visit object again, just redirect pointer to to-space copy • scan to-space linearly to visit reachable objects • to-space acts like breadth-first-search work list • when done scanning to-space: • empty from-space • flip : swap roles of to-space and from-space • restart mutator Craig Chambers 191 CSE 501 Craig Chambers 192 CSE 501 An improvement Another improvement Add small nursery semi-space [Ungar 84] Add semi-space for large objects [Caudill & Wirfs-Brock 86] • nursery fits in main memory (or cache) • big objects slow to copy, so allocate them in separate space • mutator allocates in nursery • use mark/sweep in large object space + no copying of big objects • GC when nursery fills − more complex • copy nursery + from-space to to-space • flip: empty both nursery and from-space + reduces cache misses, page faults • most heap memory references satisfied in nursery? − nursery + from-space can overflow to-space − more complex Craig Chambers 193 CSE 501 Craig Chambers 194 CSE 501

  4. Generational GC Generation scavenging Observation: A generational copying GC [Ungar 84] most objects die soon after allocation • e.g. closures, cons cells, stack frames, numbers, ... 2 generations: new-space and old-space • new-space managed as a 3-space copying collector Idea: • old-space managed using mark/sweep concentrate GC effort on young objects • new-space much smaller than old-space • divide up heap into 2 or more generations • GC each generation with different frequencies, algorithms Apply copy collection ( scavenging ) to new-space frequently If object survives many scavenges, then copy it to old-space Original idea: Peter Deutsch • tenuring (a.k.a. promotion ) Generational mark/sweep: [Lieberman & Hewitt 83] • need some representation of object’s age Generational copying GC: [Ungar 84] If old-space (nearly) full, do a full GC Craig Chambers 195 CSE 501 Craig Chambers 196 CSE 501 Tracking old → new pointers Roots for generational GC Must include pointers from old-space to new-space as roots How to remember pointers? when scavenging new-space • individual words containing pointers [Hosking & Moss 92] How to find these? • remembered set of objects possibly containing pointers [Ungar 84] Option 1: scan old-space at each scavenge • card marking [Wilson 89] Option 2: track pointers from old-space to new-space How to update table? • functional languages: easy! • imperative languages: need a write barrier • specialized hardware • standard page protection hardware • in software, inserting extra checking code at stores Craig Chambers 197 CSE 501 Craig Chambers 198 CSE 501

  5. Evaluation of generation scavenging Extensions + scavenges are short: fraction of a second Multiple generations + low run-time overhead • e.g. Ephemeral GC: 8 generations [Moon 84] • 2-3% in Smalltalk interpreter • many generations obviates need for age fields • 5-15% in optimized Self code + less VM space than pure copying Feedback-mediated tenuring policy [Ungar & Jackson 88] + better memory locality than pure mark/sweep Large object space − requires write barrier − still have infrequent full GC’s − need space for age fields • some solutions in later work Craig Chambers 199 CSE 501 Craig Chambers 200 CSE 501 Incremental & parallel GC Implementing Functional Languages e.g. Lisp, Scheme, ML, Haskell, Miranda Avoid long pause times by running collector & mutator in parallel • physical or simulated parallelism Lisp and Scheme: dynamic typing ⇒ uniform “boxed” representation of all data objects, tagged pointers to encode some types (e.g. ints) cheaper Main issue: how to synchronize collector & mutator? ML, Haskell, Miranda: polymorphic static typing • read barrier [Baker 78, Moon 84] ⇒ uniform “boxed” representation.... • write barrier [Dijkstra 78; Appel, Ellis & Li 88] • “unboxing”: choose better data layout where possible First-class, lexically-nested functions • static scoping of nested functions ⇒ closures to represent function values • functions can outlive defining scope ⇒ heap-allocated environments • calls of computed expressions ⇒ (fancier) call graph analysis Heavy use of recursion instead of iteration ⇒ tail call, tail recursion elimination Immutable update-by-copy data structures ⇒ version arrays, compile-time reference counting Miranda & Haskell: lazy evaluation ⇒ strictness analysis Craig Chambers 201 CSE 501 Craig Chambers 202 CSE 501

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend