Concurrent Reference Countingmaon/teaching/2014-2015/seminar/... · Table of contents 1...
Transcript of Concurrent Reference Countingmaon/teaching/2014-2015/seminar/... · Table of contents 1...
Concurrent Reference Counting
Or Ostrovsky
13/1/15
Or Ostrovsky Concurrent Reference Counting 13/1/15 1 / 57
Table of contents
1 Introduction
2 Simple Reference Counting
3 Buffered Reference Counting
4 Sliding View Reference Counting
5 An Efficient On-the-Fly Cycle Collection
6 Summery
Or Ostrovsky Concurrent Reference Counting 13/1/15 2 / 57
The next 80 minutes in one slide
Goal - Applying reference counting to multithreaded scenariosTry use it out of the box, fail and understand whyImprove until we get it right
I Lock the whole objectI Lock a part of the objectI Log changes locally and apply them globallyI Snapshot the heap concurrentlyI Use single-threaded algorithms on the snapshot
Or Ostrovsky Concurrent Reference Counting 13/1/15 3 / 57
Table of contents
1 Introduction
2 Simple Reference Counting
3 Buffered Reference Counting
4 Sliding View Reference Counting
5 An Efficient On-the-Fly Cycle Collection
6 Summery
Or Ostrovsky Concurrent Reference Counting 13/1/15 4 / 57
Ground rules
The invariantAn object’s reference count is equal to the number of references to thatobject.
The weaker invariantIf an object has references, it’s reference count won’t be 0.If an object doesn’t have references, it’s reference count willeventually be 0.
DisclaimerWe are not concerned about mutator correctness. Only the heap matters!
Or Ostrovsky Concurrent Reference Counting 13/1/15 5 / 57
The old algorithm
Algorithm 1 Non-concurrent reference counting operations
1: Write(o, i, ref):2: addReference(ref)3: old ← o[i]4: deleteReference(old)5: o[i] ← ref6:
7: Read(o, i):8: ref ← o[i]9: addReference(ref)
10: return ref
Or Ostrovsky Concurrent Reference Counting 13/1/15 6 / 57
Faces new problems
Thread 1 Write(o,i,x) Thread 2 Write(o,i,y)
addReference(x) addReference(y)old ← o[i] old ← o[i]deleteReference(old) deleteReference(old)o[i] ← x o[i] ← y
o[i]
0x
1z
0y
old 1 old 2
Or Ostrovsky Concurrent Reference Counting 13/1/15 7 / 57
Faces new problems
Thread 1 Write(o,i,x) Thread 2 Write(o,i,y)addReference(x) addReference(y)
old ← o[i] old ← o[i]deleteReference(old) deleteReference(old)o[i] ← x o[i] ← y
o[i]
1x
1z
1y
old 1 old 2
Or Ostrovsky Concurrent Reference Counting 13/1/15 7 / 57
Faces new problems
Thread 1 Write(o,i,x) Thread 2 Write(o,i,y)addReference(x) addReference(y)old ← o[i] old ← o[i]
deleteReference(old) deleteReference(old)o[i] ← x o[i] ← y
o[i]
1x
1z
1y
old 1 old 2
Or Ostrovsky Concurrent Reference Counting 13/1/15 7 / 57
Faces new problems
Thread 1 Write(o,i,x) Thread 2 Write(o,i,y)addReference(x) addReference(y)old ← o[i] old ← o[i]deleteReference(old) deleteReference(old)
o[i] ← x o[i] ← y
o[i]
1x
-1z
1y
old 1 old 2
Or Ostrovsky Concurrent Reference Counting 13/1/15 7 / 57
Faces new problems
Thread 1 Write(o,i,x) Thread 2 Write(o,i,y)addReference(x) addReference(y)old ← o[i] old ← o[i]deleteReference(old) deleteReference(old)o[i] ← x
o[i] ← y
o[i]
1x
-1z
1y
old 1 old 2
Or Ostrovsky Concurrent Reference Counting 13/1/15 7 / 57
Faces new problems
Thread 1 Write(o,i,x) Thread 2 Write(o,i,y)addReference(x) addReference(y)old ← o[i] old ← o[i]deleteReference(old) deleteReference(old)o[i] ← x o[i] ← y
o[i]
1x
-1z
1y
old 1 old 2
Or Ostrovsky Concurrent Reference Counting 13/1/15 7 / 57
Let’s break it down
Updating a reference count requires:I Update the PointerI Decrement the old target’s ref. countI Increment the new target’s ref. countI All must be coordinated!
Pitfalls:I Premature releaseI Garbage remaining indefinitely
Or Ostrovsky Concurrent Reference Counting 13/1/15 8 / 57
Table of contents
1 Introduction
2 Simple Reference CountingLocksAtomic Memory Primitives
3 Buffered Reference Counting
4 Sliding View Reference Counting
5 An Efficient On-the-Fly Cycle Collection
6 Summery
Or Ostrovsky Concurrent Reference Counting 13/1/15 9 / 57
Motivation
ProblemMultiple threads are accessing the same object at the same time.
SolutionAllow only one thread to access each object at a given time.
MethodProtect the object using locks
Or Ostrovsky Concurrent Reference Counting 13/1/15 10 / 57
Motivation
ProblemMultiple threads are accessing the same object at the same time.
SolutionAllow only one thread to access each object at a given time.
MethodProtect the object using locks
Or Ostrovsky Concurrent Reference Counting 13/1/15 10 / 57
Motivation
ProblemMultiple threads are accessing the same object at the same time.
SolutionAllow only one thread to access each object at a given time.
MethodProtect the object using locks
Or Ostrovsky Concurrent Reference Counting 13/1/15 10 / 57
The old algorithm revisitedAlgorithm 2 Eager reference counting with locks
1: Read(src, i):2: lock(src)3: tgt ← src[i]4: addReference(tgt)5: unlock(src)6: return ref7:
8: Write(src, i, ref):9: addReference(ref)
10: lock(src)11: old ← src[i]12: src[i] ← ref13: deleteReference(old)14: unlock(src)
Or Ostrovsky Concurrent Reference Counting 13/1/15 11 / 57
Analysis
Pro.SimpleWorks
Con.Performance - locks the whole object
Or Ostrovsky Concurrent Reference Counting 13/1/15 12 / 57
Motivation
ProblemLocking the whole object impedes performance.
SolutionLock the bare minimum needed.
MethodUse atomic memory primitives.
Or Ostrovsky Concurrent Reference Counting 13/1/15 13 / 57
Motivation
ProblemLocking the whole object impedes performance.
SolutionLock the bare minimum needed.
MethodUse atomic memory primitives.
Or Ostrovsky Concurrent Reference Counting 13/1/15 13 / 57
Motivation
ProblemLocking the whole object impedes performance.
SolutionLock the bare minimum needed.
MethodUse atomic memory primitives.
Or Ostrovsky Concurrent Reference Counting 13/1/15 13 / 57
The same algorithm, but with a twist - writing
Algorithm 3 Eager reference counting with CompareAndSwap - write1: Write(src, i, ref)2: if ref 6= null3: AtomicIncrement(&rc(ref)) /*rc=reference counter*/4: loop5: old ← src[i]6: if CompareAndSet(&src[i], old, ref)7: deleteReference(old)8: return9:
10: deleteReference(ref)11: if ref 6= null12: AtomicDecrement(&rc(ref))13: if rc(ref) = 014: for each fld in Pointers(ref)15: deleteReference(*fld)16: free(ref)
Or Ostrovsky Concurrent Reference Counting 13/1/15 14 / 57
The same algorithm, but with a twist
Algorithm 4 Eager reference counting with CompareAndSwap - reading
1: Read(src, i, ref)2: tgt ← src[i]3: AtomicIncrement(&rc(tgt))4: return tgt
Or Ostrovsky Concurrent Reference Counting 13/1/15 15 / 57
The same algorithm, but with a twist
Algorithm 5 Eager reference counting with CompareAndSwap - reading
1: Read(src, i, ref)2: tgt ← src[i]
free(tgt)3: AtomicIncrement(&rc(tgt))4: return tgt
Or Ostrovsky Concurrent Reference Counting 13/1/15 15 / 57
The same algorithm, but with a twist
Algorithm 6 Eager reference counting with CompareAndSwap2
1: Read(src, i, ref)2: loop3: tgt ← src[i]4: if tgt = null5: return null6: rc ← rc(tgt)7: if CompareAndSet2(&src[i], &rc(tgt), tgt,
rc, tgt, rc+1)8: return tgt
Or Ostrovsky Concurrent Reference Counting 13/1/15 16 / 57
Analysis
Pro.Simple(ish)Better performance - block fields and not objects
Con.Not practical - no CompareAndSet2Performance issues:
I LocksI Spin locks are bad
Or Ostrovsky Concurrent Reference Counting 13/1/15 17 / 57
Table of contents
1 Introduction
2 Simple Reference Counting
3 Buffered Reference Counting
4 Sliding View Reference Counting
5 An Efficient On-the-Fly Cycle Collection
6 Summery
Or Ostrovsky Concurrent Reference Counting 13/1/15 18 / 57
Motivation
ProblemHeavy write barrier
SolutionLet another thread do all of the accounting
MethodBuffer all the ref. counting operations
Or Ostrovsky Concurrent Reference Counting 13/1/15 19 / 57
Motivation
ProblemHeavy write barrier
SolutionLet another thread do all of the accounting
MethodBuffer all the ref. counting operations
Or Ostrovsky Concurrent Reference Counting 13/1/15 19 / 57
Motivation
ProblemHeavy write barrier
SolutionLet another thread do all of the accounting
MethodBuffer all the ref. counting operations
Or Ostrovsky Concurrent Reference Counting 13/1/15 19 / 57
Implementation
Each mutator logs it’s operations using a write barrier.Each cycle:
I Collect logs from each threadI Apply reference count updatesI Reclaim memory
Time is divided into epochs.Deferred ref. counting is used.
Or Ostrovsky Concurrent Reference Counting 13/1/15 20 / 57
The new write barrier
Algorithm 7 Concurrent buffered reference counting - write
1: shared epoch2: shared updatesBuffer[] /*one per epoch*/3:
4: Write(src, i, ref)5: if src = Roots6: src[i] ← ref7: else8: old ← AtomicExchange(&src[i], ref)9: log(old, ref)
10:
11: log(old, new)12: append(myUpdates, 〈old, new〉)
Or Ostrovsky Concurrent Reference Counting 13/1/15 21 / 57
Collect - get local logs
Algorithm 8 Concurrent buffered reference counting - collect
1: collect()2: myStackBuffer ← []3: for each local ref in myStacks4: append(myStackBuffer, 〈ref, ref〉)5: atomic6: append(updatesBuffer[e], myStackBuffer)7: atomic8: append(updatesBuffer[e], myUpdates)9: myUpdates ← []
10: e ← e + 1
Or Ostrovsky Concurrent Reference Counting 13/1/15 22 / 57
Collect - apply changes
Algorithm 8 Concurrent buffered reference counting - collect
11: me ← myProcessorId12: if me < MAX PROCESSORS13: schedule(collect, me+1)14: else15: for each 〈old, new〉 in updatesBuffer[epoch]16: addReference(new)17: for each 〈old, new〉 in updatesBuffer[epoch - 1]18: deleteReference(old)19: release(updatesBuffer[epoch - 1])20: epoch ← epoch + 1
Or Ostrovsky Concurrent Reference Counting 13/1/15 23 / 57
Example
T1
T2
B
A
B
A 2
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 2
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 2
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 2
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 2
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 3
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 4
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 2
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 2
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 3
B 2
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 2
B 2
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 1
B 2
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Example
T1
T2
B
A
B
A 1
B 1
A A
T1
A A
T2
e-1
A A
T1
A A B
T2
e
B B
T1
A A
T2
e+1
Or Ostrovsky Concurrent Reference Counting 13/1/15 24 / 57
Analysis
Pro.Performance
I Thin write barrierI On the flyI Allows for an independent collector threadI Incorporates deferred ref. counting
Con.Circle handlingHigh memory requirementsLog each operation
Or Ostrovsky Concurrent Reference Counting 13/1/15 25 / 57
Table of contents
1 Introduction
2 Simple Reference Counting
3 Buffered Reference Counting
4 Sliding View Reference CountingCoalesced Reference CountingSliding View
5 An Efficient On-the-Fly Cycle Collection
6 Summery
Or Ostrovsky Concurrent Reference Counting 13/1/15 26 / 57
Motivation
ProblemCan’t use single-threaded algorithms concurrently
SolutionCreate a snapshot of the heap
MethodCreate a sliding view
Or Ostrovsky Concurrent Reference Counting 13/1/15 27 / 57
Motivation
ProblemCan’t use single-threaded algorithms concurrently
SolutionCreate a snapshot of the heap
MethodCreate a sliding view
Or Ostrovsky Concurrent Reference Counting 13/1/15 27 / 57
Motivation
ProblemCan’t use single-threaded algorithms concurrently
SolutionCreate a snapshot of the heap
MethodCreate a sliding view
Or Ostrovsky Concurrent Reference Counting 13/1/15 27 / 57
Coalesced reference counting - motivation
An observation:src[i ]← o1 rc(o0)−−, rc(o1) + +src[i ]← o2 rc(o1)−−, rc(o2) + +
. . . . . .src[i ]← on rc(on−1)−−, rc(on) + +
Redundancy?
Or Ostrovsky Concurrent Reference Counting 13/1/15 28 / 57
Coalesced reference counting - solution
Method:I Write barrier: log “clean” objects and mark them as “dirty”.I At the end of each cycle: rc(log(ref ))−−, rc(ref ) + +
Uses a snapshot of the heap - provided by the logs.The increments require the mutator to stop.Implementation
I Add a pointer to the object headerI The pointer points to the current log entryI Clean objects: getLogPointer(obj) = null
Or Ostrovsky Concurrent Reference Counting 13/1/15 29 / 57
Example
Colletor’slog
A
B C
Or Ostrovsky Concurrent Reference Counting 13/1/15 30 / 57
Example
Colletor’slog
A
B C
Or Ostrovsky Concurrent Reference Counting 13/1/15 30 / 57
Example
Colletor’slog
A
B C
Or Ostrovsky Concurrent Reference Counting 13/1/15 30 / 57
Sliding View
Levanoni and Petrank 2001Take an incremental, concurrent “snapshots” of the heap
I Each mutator logs writes on clean objects.I The collector collects the logs on mutator at a timeI The collector cleans dirty objectsI When the collector needs a object current heap
F If it’s clean - use itF Else - use a local log
Or Ostrovsky Concurrent Reference Counting 13/1/15 31 / 57
Final Result
Sliding view - taken at [ts , te]
A spread “snapshot” - statet(obj) s.t. t ∈ [ts , te]
heap
timets te
Or Ostrovsky Concurrent Reference Counting 13/1/15 32 / 57
Snooping
Problem - premature reclaimsI ref might be reclaimed
viewk
threads
time
collect o1
o1 = ref
ts te
Solution - “snoop” itI Keep it in a special bufferI Use it as a root in the current cycle
Or Ostrovsky Concurrent Reference Counting 13/1/15 33 / 57
Other Problems
Global log pointersI A race is possibleI Solution: The race has no effect.
Clean-modify conflictsI The mutator changes the object while it’s being cleanedI Solution: Reinforce dirty state if needed
Or Ostrovsky Concurrent Reference Counting 13/1/15 34 / 57
Building the local logsAlgorithm 9 Write barrier
1: Write(src, i, ref)2: if src = Roots3: src[i] ← ref4: else5: if not dirty(src)6: log(src)7: src[i] ← ref8: snoop(ref)9:
10: log(ref)11: for each fld in Pointers(ref)12: if *fld 6= null13: add(logs[me], *fld)14: if not dirty(ref)15: entry ← add(logs[me], ref)16: logPointer(ref) ← entry17:
18: snoop(ref)19: if snoopFlag[me] && ref 6= null20: append(mySnoopedBuffer, ref)
Or Ostrovsky Concurrent Reference Counting 13/1/15 35 / 57
Collect them
Algorithm 10 Sliding view collection1: collectSlidingView()2: for each t in threads /*handshake 1*/3: suspend(t)4: snoopFlag[t] ← true5: transfer t’s buffers to updates6: resume(t)7: clean modified and young objects8: for each t in threads /*handshake 2*/9: suspend(t)
10: find modify-clean conflicts11: resume(t)12: reinforce dirty objects13: for each t in threads /*handshake 3*/14: suspend(t)15: resume(t)
Or Ostrovsky Concurrent Reference Counting 13/1/15 36 / 57
Use them
Algorithm 11 Read sliding view1: readSlidingView(entry)2: obj ← objFromLog(entry)3: if not dirty(obj)4: replica ← copy(obj) /*read the current state*/5: if dirty(obj)6: replica ← getLogPointer(obj)7: else8: replica ← getLogPointer(obj)9: return replica
Or Ostrovsky Concurrent Reference Counting 13/1/15 37 / 57
Example
Mutators’slog
Collector’slog
A
B C
Snoopbuffer
Or Ostrovsky Concurrent Reference Counting 13/1/15 38 / 57
Example
Mutators’slog
Collector’slog
A
B C
Snoopbuffer
Or Ostrovsky Concurrent Reference Counting 13/1/15 38 / 57
Example
Mutators’slog
Collector’slog
A
B C
Snoopbuffer
Or Ostrovsky Concurrent Reference Counting 13/1/15 38 / 57
Example
Mutators’slog
Collector’slog
A
B C
Snoopbuffer
Or Ostrovsky Concurrent Reference Counting 13/1/15 38 / 57
Example
Mutators’slog
Collector’slog
A
B C
Snoopbuffer
Or Ostrovsky Concurrent Reference Counting 13/1/15 38 / 57
Example
Mutators’slog
Collector’slog
A
B C
Snoopbuffer
Or Ostrovsky Concurrent Reference Counting 13/1/15 38 / 57
Example
Mutators’slog
Collector’slog
A
B CSnoopbuffer
Or Ostrovsky Concurrent Reference Counting 13/1/15 38 / 57
Table of contents
1 Introduction
2 Simple Reference Counting
3 Buffered Reference Counting
4 Sliding View Reference Counting
5 An Efficient On-the-Fly Cycle CollectionOverviewConceptsThe big picture
6 Summery
Or Ostrovsky Concurrent Reference Counting 13/1/15 39 / 57
An Efficient On-the-Fly Cycle Collection
A “Big algorithm” - incorporates many techniquesI Mark & Sweep (Lecs. 2 & 10)I Generational GC (Lec. 5)I The Recycler (Lec. 3)I Coalesced reference countingI Sliding views
Relatively new - Paz et al. 2007We’ll handle it very carefullyNo full pseudocode
Or Ostrovsky Concurrent Reference Counting 13/1/15 40 / 57
Mark & Sweep
Mark all reachable objects and reclaim the rest.Algorithm:
I Trace memory from roots.I Mark reachable objects.I Release unmarked objects
Work - proportional to the number of live objectsSimpler version need a “fixed” heap
Or Ostrovsky Concurrent Reference Counting 13/1/15 41 / 57
Generational garbage collection
The weak generational hypothesis: most objects die youngYoung generation
I High mutation and death ratesI Use1 Mark & Sweep - trace only live objects
Old generationI Low mutation and death ratesI Use1 Reference counting - handle big live heaps
1For the current schemeOr Ostrovsky Concurrent Reference Counting 13/1/15 42 / 57
The Recycler
Proposed by Bacon & Rajan at 2001Reclaim unreachable circles using trial deletionAlgorithm:
I Build a set of candidatesI Decrement counts for each candidate (mark as gray)I Scan objects reachable from candidates with rc 6= 0
F Those items are marked blackF The rest are marked white
I Remove white objectsMany traversals are required - needs a “fixed” heap
Or Ostrovsky Concurrent Reference Counting 13/1/15 43 / 57
Pseudocode
Algorithm 12 Cycle collection
1: collectCycles()2: markCandidates()3: markLiveBlack()4: scan()5: collectWhite()6: processBuffers()
Or Ostrovsky Concurrent Reference Counting 13/1/15 44 / 57
The major scheme
Objects are created youngLog old objectsCollect logs from each thread (one at a time)Clean dirty objectsUpdate reference counts of old objectsM&S young objectsApply the Recycler on old objects
Or Ostrovsky Concurrent Reference Counting 13/1/15 45 / 57
Corner rounding & circle squaring
Inter-generational pointersI Mark & Sweep - old → youngI The Recycler - young → old
“Live” heapsI Mark & Sweep - See Lec. 10I The Recycler - Retracing the graph
Aging - correct the reference count to and from a young object
Or Ostrovsky Concurrent Reference Counting 13/1/15 46 / 57
Corner rounding & circle squaring
Inter-generational pointersI Mark & Sweep - old → youngI The Recycler - young → old
“Live” heapsI Mark & Sweep - See Lec. 10I The Recycler - Retracing the graph
Aging - correct the reference count to and from a young object
Or Ostrovsky Concurrent Reference Counting 13/1/15 46 / 57
Solutions
Inter-generational pointersI old → young - mark objects when processing logsI young → old - young objects are candidates for the Recycler
“Live” heaps - Use the sliding viewAging
I References from - increment using sliding windowI References to - are logged with the old objects
Or Ostrovsky Concurrent Reference Counting 13/1/15 47 / 57
Allocating objects
Algorithm 13 Object allocation
1: New()2: ref ← allocate()3: add(myYoungSet, ref)4: setDirty(ref)5: return ref
Or Ostrovsky Concurrent Reference Counting 13/1/15 48 / 57
Actual reference countingAlgorithm 14 Reference count updates
1: incrementNew(entry)2: replica ← readSlidingView(entry)3: for each fld in Pointers(replica)4: child ← *fld5: if child 6= null6: rc(child) ← rc(child) + 17: mark(child) /*for M&S*/8:
9: decrementOld(entry)10: for each fld in Pointer(entry)11: child ← *fld12: if child 6= null13: rc(child) ← rc(child) - 114: if rc(child) = 015: add(ztc, child)16:
17: processReferenceCounts()18: for each entry in updates19: decrementOld(entry)20: incrementNew(entry)
Or Ostrovsky Concurrent Reference Counting 13/1/15 49 / 57
The “main” method
Algorithm 15 Collection
1: collect()2: collectSlidingView()3: for each t in threads /*handshake 4*/4: suspend(t)5: scanStack(t)6: snoopFlag[t] ← false7: resume(t)8: processReferenceCounts()9: markNursery()
10: sweepNursery()11: sweepZCT()12: collectCycles()
Or Ostrovsky Concurrent Reference Counting 13/1/15 50 / 57
Example
Mutators’slog
Collector’slog A
B D E G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D E G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D E G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D E G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D E G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D E G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G0 2 1 0 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G1 1 1 1 0 0 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G1 1 1 1 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G1 0 0 1 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G1 1 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Example
Mutators’slog
Collector’slog A
B D
E
G
C F
Roots
Snoopbuffer
A B C D E F G0 1 0
Or Ostrovsky Concurrent Reference Counting 13/1/15 51 / 57
Analysis
Pro.Uses single-threaded algorithmsPerformance
I All the advantages of buffered reference countingI Fewer reference count changes
Handles circles
Con.Very complexRelatively new
Or Ostrovsky Concurrent Reference Counting 13/1/15 52 / 57
Table of contents
1 Introduction
2 Simple Reference Counting
3 Buffered Reference Counting
4 Sliding View Reference Counting
5 An Efficient On-the-Fly Cycle Collection
6 Summery
Or Ostrovsky Concurrent Reference Counting 13/1/15 53 / 57
Discussion
Sliding view limitationsImprovements for the on the fly collectorCombine algorithms with reference countingWhat is reference counting good for?
Or Ostrovsky Concurrent Reference Counting 13/1/15 54 / 57
Overview
Simple reference counting - both flavorsBuffered reference counting - let another thread do the accountingCoalesced reference counting - know what to ignoreSliding view - take a snapshot of the heap while it’s movingOn-the-Fly cycle collection - Sliding view usage example
Or Ostrovsky Concurrent Reference Counting 13/1/15 55 / 57
Any questions?
Or Ostrovsky Concurrent Reference Counting 13/1/15 56 / 57
Any comments?
Or Ostrovsky Concurrent Reference Counting 13/1/15 57 / 57