230 likes | 369 Vues
This paper presents a novel method for implementing nondeferred reference counting (RC) garbage collection, focusing on optimizing performance in object-oriented systems. The work addresses challenges in converting applications to use nondeferred techniques while ensuring efficient memory management. Key contributions include high-level processes for inserting RC updates, treating modern language features, and maintaining system performance during conversion. The approach maintains the critical invariants of nondeferred RC and minimizes impact on the runtime system, making it practical for general use.
E N D
A Principled Approach to Nondeferred Reference-Counting Garbage Collection† Pramod G. Joisha HP Labs, Palo Alto †This work was done when the author was at Microsoft Research. VEE’08 (ACM SIGPLAN/SIGOPS International Conference on Virtual Execution Environments) March 7, 2008
Classic RC Instrumentation local references global reference
Unique Advantages • Prompt reuse • Cache effect gives performance benefits • Low footprint • Can run in a smaller heap • Useful in memory-constrained environments • Incremental in time and space • No repeated traversals of long-lived data • Spatial locality usually no worse than mutator • Can present simpler overall designs • No stack maps needed, at least in single-thread case
What is “Nondeferred” RC Collection? • Three invariants should always hold: • All live data have positive reference counts • Reference count is zero when last reference disappears • Zero reference count implies dead data • Classic reference counting is nondeferred • Deutsch & Bobrow’s reference counting is not • There are subtleties in the definition • “Last reference” is from mutator’s standpoint • Reference count could be zero even before
Approximate reference counts Only heap references tallied Zero-Count Table (ZCT) Threads paused to reconcile Stacks scanned to purge ZCT Remaining entries garbage Nondeferred invariants might not always hold .g 1 a f x b 0 stack c y 1 z heap Deutsch & Bobrow’s Reference Counting globals
What is Different from Previous Efforts? • Past work addressed optimizations: • Given a nondeferred app, how to make it faster? • 2006 & 2007 ACM International Symposium on Memory Management • This work addresses a different obstacle: • How to convert object-oriented apps to use nondeferred? • The line of work has an overarching goal: • Making nondeferred RC garbage collection practical • Making general reference counting more efficient
Contributions of This Work • Addresses main problems to conversion: • How to handle object-oriented instruction sets uniformly? • How to insert RC updates to achieve early reclamation? • How to do this in the midst of modern language features? • Exceptions, object pinning, interior pointers • How to treat the run-time system? • Interaction of conversion with other phases • Impact on downstream phases should be minimal • Conversion has implications on inlining
Talk Outline • The RC update insertion phase • High-level process • Code templates • Trading code quality with eagerness • The scope of the insertion phase • How does the technique fare? • Summary • Some Further Thoughts
array object 1 2 3 4 5 6 7 8 9 10 interior ptr shadow Preprocessing Stage • Motivation: Normalize the IR • Key step: Subsume interior pointers • Interior pointers similar to conventional pointers • But can only be used in a few well-defined ways • Should be honored by the garbage collector • Approach: Shadow interior pointer accesses
Analysis Stage • Find dying references using liveness analysis • Supplementary decrements may be needed • If references are both defined and live on entry to the statement s • If other references could be defined in s • Liveness modified for pinned references
Injection Stage • Three kinds of RC updates inserted • RC increment, standard and eager RC decrement • Operates in three steps • Insert RC updates against definitions and deaths • Insert RC increments against explicit intrafunction throws • Insert standard RC decrements into exception headers • Injection guided by code templates • Based on classifying a statement as call or “non-call”
Everything Shouldn’t be Converted! • All code in the run-time isn’t converted • Presently, C# attributes flag special code • [PreInitRefCounts] • Bootstrap memory allocation, and static initializers • [RecursiveRefCounts] • Code transitively reachable from addref and release • [ManualRefCounts] • Methods that directly manipulate reference counts • [ZombieRefCounts] • Code accessing zombie objects • Affixation rules can be mechanized
Related Work • The use of liveness in GC isn’t new • But past work considers it for a tracing collector • This work considers reference deaths • Important distinction: Arises from a basic difference between tracing and reference counting • One looks at live matter and the other at matter that is dead (see Bacon et al. OOPSLA’04). • Certain complications are unique here • E.g. exceptions
How does Nondeferred Fare? Xlisp interpreter (SPEC CINT95 port)
Summary • A systematic conversion algorithm • Instructions are treated in a uniform manner • Modern language features handled • Degree of eagerness can be varied • Conversion has implications on other parts • Has been implemented in a compiler • Many large programs have been successfully compiled
Some Further Thoughts • What remains for primetime? • Optimizing single-thread heap reference counting • Concurrent nondeferred reference counting • Cycle reclamation • Fragmentation • An ecosystem of supporting tools required • Presently, a memory leak verifier and profiler exist • But more needed! decreasing importance