Transactional memory with data Transactional memory with data - - PowerPoint PPT Presentation
Transactional memory with data Transactional memory with data - - PowerPoint PPT Presentation
Transactional memory with data Transactional memory with data invariants: or putting the C back putting the C back invariants: or in ACID in ACID Tim Harris, Simon Peyton Jones Tim Harris, Simon Peyton Jones Introduction
Introduction Introduction
Time
- “
“List XYZ remains in sorted order List XYZ remains in sorted order” ”
[] [10,20] [10] [5,10,20] [20,10,5]
thread1 thread1 thread2 thread2 thread3 thread3
URK! But how to detect this: Find and instrument all updates? Distinguish sorted/unsorted lists in the type system?
Transactions to the rescue Transactions to the rescue
- Write
Write executable invariants executable invariants to check the to check the properties we properties we’ ’re interested in re interested in
- Invariants fit in really nicely with transactions:
Invariants fit in really nicely with transactions:
– – Of course, the DB folk knew this long ago :-) Of course, the DB folk knew this long ago :-) – – Every transaction must preserve every invariant Every transaction must preserve every invariant – – Transactions define updates between Transactions define updates between consistent consistent states states – – Invariants can (must!) be broken within transactions Invariants can (must!) be broken within transactions – – It doesn It doesn’ ’t matter if an update is to the spine of the list t matter if an update is to the spine of the list
- r to a key that it contains (unlike much related work,
- r to a key that it contains (unlike much related work,
e.g. Eiffel and Spec#) e.g. Eiffel and Spec#)
A sorted list using invariants A sorted list using invariants
newSortedList newSortedList = do { = do { r <- r <- newList newList(); (); check ( check (isSorted isSorted r); r); return r; return r; } }
Defining a function ‘newSortedList’ in Haskell-ish pseudo-code Construct an ordinary mutable list as usual Assert that the list is sorted now, and every update to the list must keep it sorted Return the list we created
- The runtime system keeps track of the invariant
The runtime system keeps track of the invariant and ensures transactions don and ensures transactions don’ ’t violate it t violate it – – the type the type system treats it as any other list system treats it as any other list
Semantics Semantics
- The invariant is an STM action
The invariant is an STM action… … so [in so [in Haskell] it Haskell] it’ ’s guaranteed not to do I/O s guaranteed not to do I/O
– – But what if it loops? But what if it loops? – – What if it updates or allocates transactional state? What if it updates or allocates transactional state? – – What if it calls What if it calls check check to add yet another invariant? to add yet another invariant? – – What if it uses condition synchronization and blocks What if it uses condition synchronization and blocks the transaction? the transaction?
First design choice: overview First design choice: overview
- Run invariants in [closed] nested
Run invariants in [closed] nested tx tx (so they see (so they see the tentative updates), check they succeed (don the tentative updates), check they succeed (don’ ’t t throw an exception), then roll back each nested throw an exception), then roll back each nested tx tx
- All this happens atomically with the user
All this happens atomically with the user tx tx
User’s transaction Nested tx check invariants and are then aborted (so no interference with user tx) Whole lot occurs atomically
Time
First design choice: semantics First design choice: semantics
- The invariant is an arbitrary STM action
The invariant is an arbitrary STM action… …
– – What if it loops? What if it loops? – – What if it updates trans state? What if it updates trans state? – – What if it calls What if it calls check check? ? – – What if it blocks? What if it blocks?
Can use them internally, but updates discarded Checked at that call, but then discarded The user’s tx blocks until the invariant can complete Your program loops…
STM Haskell STM Haskell
newTVar newTVar :: a -> STM ( :: a -> STM (TVar TVar a) a) readTVar readTVar :: :: TVar TVar a -> STM a a -> STM a writeTVar writeTVar :: :: TVar TVar a -> a -> STM () a -> a -> STM () atomic :: STM a -> IO a atomic :: STM a -> IO a incT incT :: :: TVar TVar Int Int ->
- > STM
STM () () incT incT r = do { v <- r = do { v <- readTVar readTVar r r ; ; writeTVar writeTVar r (v+1) } r (v+1) } main = do { r <- atomic ( main = do { r <- atomic (newTVar newTVar 0) 0) ; fork (atomic ( ; fork (atomic (incT incT r)) r)) ; atomic ( ; atomic (incT incT r) r) ; ... } ; ... }
Transactional state is held in TVars The type system distinguishes transactional code (types like “STM a”) from general imperative code (types like “IO a”) Sequential composition of STM actions
Second design choice: restrict to reads Second design choice: restrict to reads
- We can distinguish between STM actions that just
We can distinguish between STM actions that just read from the heap from STM actions that perform read from the heap from STM actions that perform updates / create updates / create TVars TVars / block / add invariants / block / add invariants
data data ReadOnly ReadOnly data Effect data Effect type STM e a = type STM e a = … … readTVar readTVar :: :: TVar TVar a -> STM e a a -> STM e a writeTVar writeTVar :: a -> :: a -> TVar TVar a -> STM Effect a a -> STM Effect a atomic :: STM e a -> IO a atomic :: STM e a -> IO a check :: STM check :: STM ReadOnly ReadOnly a -> STM Effect () a -> STM Effect ()
An STM action where “e” may be forced to be unified with phantom types “Pure” or “Effect”. Sequencing “STM e a” and “STM f b” defined to require a==b. writeTVar forces “e” to be unified with “Effect” readTVar can be sequentially composed with any kind of STM action Combinators express their constraints (if any)
Invariants over state pairs Invariants over state pairs
- Exciting observation from the Spec# group
Exciting observation from the Spec# group
- Suppose we want invariants over state pairs
Suppose we want invariants over state pairs rather than single states rather than single states
– – “ “Value of x never decreases Value of x never decreases” ” – – versus versus “ “Value of x is always positive Value of x is always positive” ”
- ld :: STM
- ld :: STM ReadOnly
ReadOnly a -> STM e a a -> STM e a
Take an STM action and run it in the pre- transactional state
check (do { cur <- check (do { cur <- readTVar readTVar x; x; prev prev <- old ( <- old (readTVar readTVar x); x); assert ( assert (prev prev <= cur); } ) <= cur); } )
Implementation Implementation
- Isn
Isn’ ’t it slow checking every invariant upon every t it slow checking every invariant upon every transaction? transaction?
– – It would be if we actually checked them all It would be if we actually checked them all – – When invariant checking is enabled we dynamically track When invariant checking is enabled we dynamically track dependencies from dependencies from TVars TVars to invariants that depend on them to invariants that depend on them – – “ “Pay for play Pay for play” ” (same wake-up mechanism we use for condition (same wake-up mechanism we use for condition synchronization) synchronization) – – These are the only references to the data structures used to These are the only references to the data structures used to represent invariants: the GC reclaims these structures when represent invariants: the GC reclaims these structures when they are unreachable they are unreachable – – (But note that the extra links may extend the lifetime of (But note that the extra links may extend the lifetime of individual objects individual objects – – the invariant and everything reachable the invariant and everything reachable from it will be retained while at least one from it will be retained while at least one TVar TVar it depends on is it depends on is reachable) reachable)
Implementation (2) Implementation (2)
TVar TVar’ ’s s contents contents v123 v123 TVar TVar’ ’s s contents contents v75 v75 Next wait-q entry Next wait-q entry Invariant Invariant’ ’s closure s closure Tx Tx record from last execution record from last execution Next wait-q entry Next wait-q entry
Conclusions Conclusions
- First system to integrate invariants with
First system to integrate invariants with transactional memory transactional memory
- “
“Putting the C back in ACID Putting the C back in ACID” ”
- Many of the ideas have a long history; both
Many of the ideas have a long history; both semantically and in the implementation semantically and in the implementation
- Do we want some kind of
Do we want some kind of “ “trigger trigger” ”-like
- like
construct too? construct too?
- Workloads
Workloads workloads workloads workloads workloads
Papers Papers
- “
“Transactional memory with data invariants Transactional memory with data invariants” ” TRANSACT TRANSACT 2006 2006
- “
“Lock-free data structures using STM in Haskell Lock-free data structures using STM in Haskell” ” FLOPS FLOPS 2006 2006 – – larger examples and SMP performance larger examples and SMP performance eval eval
- “
“Composable memory transactions Composable memory transactions” ” PPoPP PPoPP 2005 2005 – – software software transactions in Haskell transactions in Haskell
- “
“Haskell on a shared-memory multiprocessor Haskell on a shared-memory multiprocessor” ” Haskell 2005 Haskell 2005 – – parallel parallel thunk thunk evaluation evaluation
- “
“Exceptions and side-effects in atomic blocks Exceptions and side-effects in atomic blocks” ” CSJP 2004 CSJP 2004 – – integration of transactional memory and external resource integration of transactional memory and external resource managers managers
- “
“Optimizing memory transactions Optimizing memory transactions” ” PLDI 2006 PLDI 2006 – – C# work C# work with MSR Redmond with MSR Redmond
- “
“Concurrent programming without locks Concurrent programming without locks” ” under submission under submission – – algorithmic gore for scalable STM algorithmic gore for scalable STM
Backup slides
STM Haskell STM Haskell
retry :: STM a retry :: STM a tryDecT tryDecT :: :: TVar TVar Int Int ->
- > STM
STM () () tryDecT tryDecT r = do { r = do { v <- v <- readTVar readTVar r; r; if (v == 0) if (v == 0) retry retry else else writeTVar writeTVar r (v-1); } r (v-1); }
- “
“retry retry” ” for condition synchronization for condition synchronization
- Semantics: abort the
Semantics: abort the tx tx (all the way out), re- (all the way out), re- execute it execute it
- Implementation: smarter, block the thread until
Implementation: smarter, block the thread until it it’ ’s worth trying re-execution s worth trying re-execution
(Some axes of) the design space (Some axes of) the design space
Checked automatically Refer to arbitrary data Always Maintained
SPEC# – invariants can refer to state of ‘rep’ objects Eiffel – invariants checked on entry/exit to public methods Euclid – invariants intended for checks by formal methods Our goal: all three properties, “better assertions”
- YMMV: e.g. another axis would be