Checkpoints and Continuations instead of Nested Transactions Eric Koskinen Brown University Joint work with Maurice Herlihy Brown University
Partial Aborts Early TMs aborted entire transactions Useful to partially abort Performance: resolve conflict, without unnecessary rollback Semantic constructs: conditional and or- else synchronization, priority
But what about Nesting? TM literature is a nest of nested txns Claim that nesting gives you partial aborts Let’ s take a closer look ...
Example 1 atomic { Object x = swap(htA, key, y); HashTable.Insert(htB, key, x); Nesting for Modularity! } Object swap(HashTable ht, int key , Object newVal) { atomic { Object r = HashTable Remove(ht,key); HashTable Insert ( ht , key , newVal); return r ; } }
Example 2 global int list[10]; atomic { int x = list[0]; list[1] = x + 1; atomic { list[2] = x + 3; } Conflict! ... } Defend against abort!
Two Reasons for Nesting 1. Code Modularity (sub-routines) 2.Defend against aborts (emulate partial abort)
The Problem Nesting is too coarse-grained On abort, return to start of (a nested) txn To defend, must nest! Complex implementation: Layers of activation records (read/write sets) If you have a mechanism Partial abort by popping records for partial aborts, nesting is unneeded
The Key Idea Partial Aborts . . . without nested transactions Simpler syntax: new keyword checkpoint Place a checkpoint anywhere in a transaction Don’ t have to make everything “nested” Fine-grained rollback Simpler implementation (no r/w act. records)
Syntax Checkpoints in useful locations Doesn’ t have to be nested Example Example Example Example atomic { void foo() { atomic { void foo() { int x = list[0]; if (_txn) int x = list[0]; atomic { ... } list[1] = x + 1; { checkpoint; ... } list[1] = x + 1; } checkpoint ; else atomic { list[2] = x + 3; atomic { ... } list[2] = x + 3; atomic { ... } ... foo(); } } } atomic { } foo(); }
Mechanism To return to a checkpoint, we must: continuations Save/restore program counter capture Save/restore stack Save/restore thread-local heap Save/restore shared heap mark in the log
Mechanism Thread A Example ◆ read(list[0]) ◆ ctx 0 atomic { write(list[1]) read(list[0]) read(list[0]) int x = list[0]; write(list[2]) write(list[1]) write(list[1]) list[1] = x + 1; checkpoint ; read(list[9]) ◆ ctx 1 ◆ full abort list[2] = x + 3; write(list[2]) write(list[2]) int y = list[9]; read(list[9]) read(list[9]) ... partial ... ... } ctx i = 〈 pc A ,s A ,h A 〉
Continuations Most languages have facilities to capture PC and stack We implemented a simple facility to save/restore any thread-local heap data Prototype implementation is in C Could also work in Java
Conclusion A Partially abort a transaction No nesting needed Next: Applications. But first, what’ s boosting?
Txn’l Boosting (PPoPP’08) • Safe alternative to Open Nesting • No read/write sets, • Synchronize with abstract locks, • recovery via inverses Concurrent global ConcurrentSet l; Data Structure w Thread A atomic { AbstactLock(3); x if(l.insert(3)) LogInverse(l.remove(3)); y checkpoint; AbstactLock(7); if(l.remove(7)) z LogInverse(l.add(7)); }
Boosting Traditional Log Boosting Log w Thread Thread ◆ ctx 0 ◆ ctx 0 x read(list[0]) lock(w) write(list[1]) foo -1 (w) y ◆ ctx 1 ◆ ctx 1 write(list[2]) lock(x) z read(list[9]) bar -1 (x) ... ...
Conditional Sync. List inbound, outbound; retry AbstractLock inL, outL; Object in = NULL; atomic { with(inL.lock()) { Prepare(inbound); } checkpoint; in = with(inL.lock()) { Dequeue(inbound); } if ( !in.isSpecial() ) retry ; with(outL.lock()) { Enqueue(outbound. in); } }
Conditional Sync. HashTable htA, htB, htC; orElse AbstractLock alA, alB, alC; atomic { Object result = with(alA.lock(key)) { Remove(htA, key); } checkpoint ; { with(alB.lock(key)) { Remove(htB, key); } with(alB.lock(key)) { Add(htB, key, result); } } orElse { with(alC.lock(key)) { Remove(htC, key); } with(alC.lock(key)) { Add(htC, key, result); } } }
Implementation Base implementation is TL2 (in C) Added Boosting (PPoPP’08) Added support for Checkpoints setjmp and longjmp for capturing stack Priority experiment . . .
Application: Priority Preferred threads take priority How: “high” threads abort “low” threads May harm low priority throughput Partially abort low priority threads Roll back just far enough Let high priority threads commit
Application: Priority Concurrent w Data Structure HP Txn x y LP Txn z Conflict!
Application: Priority Simple benchmark, engineered to produce HP/LP contention
Evaluation vacation vacation kmeans kmeans (flat) (checkpoints) (flat) (checkpoints)
Related Work Moravan et al. Supporting Nested Transactional Memory in LogTM. ASPLOS-XII. Harris. Abstract Nested Transactions. 2007 . Ni et al. Open Nesting in Software Transactional Memory. PPoPP 2007 . This paper: Herlihy, Koskinen. Checkpoints and Continuations instead of Nested Transactions. Transact 2008.
Conclusion B Partially abort a transaction No nesting needed Applies to read/write TMs Applies to transactional boosting
Thanks! Questions?
Recommend
More recommend