checking linearizability using hitting families
play

Checking Linearizability Using Hitting Families Burcu Kulahcioglu - PowerPoint PPT Presentation

Checking Linearizability Using Hitting Families Burcu Kulahcioglu Ozkan 1 , Rupak Majumdar 1 , Filip Niksic 2 1 Max Planck Institute for Software Systems (MPI-SWS) 2 University of Pennsylvania Linearizability as a correctness condition Two


  1. Checking Linearizability 
 Using Hitting Families Burcu Kulahcioglu Ozkan 1 , Rupak Majumdar 1 , Filip Niksic 2 1 Max Planck Institute for Software Systems (MPI-SWS) 2 University of Pennsylvania

  2. Linearizability as a correctness condition Two execution histories on a concurrent list: addAll(1, 2): true isEmpty(): true clear() toString(): “[1]” 1: 1: clear() addAll(1, 2): true 2: 2: Linearizable history: Concurrent operations can be totally ordered in a consistent way Linearizable concurrent object: All of its execution histories are linearizable

  3. Linearizability as a correctness condition Two execution histories on a concurrent list: addAll(1, 2): true isEmpty(): true clear() toString(): “[1]” 1: 1: clear() addAll(1, 2): true 2: 2: linearizable Linearizable history: Concurrent operations can be totally ordered in a consistent way Linearizable concurrent object: All of its execution histories are linearizable

  4. Linearizability as a correctness condition Two execution histories on a concurrent list: addAll(1, 2): true isEmpty(): true clear() toString(): “[1]” 1: 1: clear() addAll(1, 2): true 2: 2: linearizable non-linearizable Linearizable history: Concurrent operations can be totally ordered in a consistent way Linearizable concurrent object: All of its execution histories are linearizable

  5. Checking linearizability Linearizability of a concurrent object • Pertains to verification • Undecidable • Approaches: Program logics, proof rules, semi-automated procedures Linearizability of a single execution history • Pertains to testing • NP-complete • Approaches: Exhaustive search for a linearizability witness with space-time trade-offs

  6. Checking linearizability Linearizability of a concurrent object • Pertains to verification • Undecidable • Approaches: Program logics, proof rules, semi-automated procedures Linearizability of a single execution history • Pertains to testing • NP-complete • Approaches: Exhaustive search for a linearizability witness with space-time trade-offs

  7. Our contribution In a nutshell: • Prioritize the search space to quickly find linearizability witnesses (if they exist) In more detail: • Introduce linearizability depth of a history • For a history of linearizability depth d , with n operations on k threads: 
 Suffices to explore a strong d -hitting family of at most O(kn d-1 ) linearizations • Experiments on java.util.concurrent : 
 In most cases linearizability witnessed by strong d -hitting families with d ≤ 5 !

  8. Linearizability Execution history induces a partial order of operations op 1 (args 1 ): res 1 op 1 (args 1 ): res 1 op 2 (args 2 ): res 2 op 2 (args 2 ): res 2 op 1 happens before op 2 op 1 and op 2 are concurrent Schedule: A total order of operations that extends the happens-before relation Linearizability witness: A schedule in which the results of operations satisfy the sequential specification Linearizable history: A history that has a linearizability witness

  9. Testing concurrent objects [Wing and Gong ’93] Sequential object 
 Concurrent object (specification) history 1 linearizable Simulator history 2 linearizable ⋮ ⋮ history m non-linearizable

  10. Testing concurrent objects [Wing and Gong ’93] Sequential object 
 Concurrent object (specification) history 1 linearizable Simulator history 2 linearizable Jepsen (distributed systems) ⋮ ⋮ Violat ( java.util.concurrent ) history m non-linearizable

  11. Testing concurrent objects [Wing and Gong ’93] Sequential object 
 Concurrent object (specification) Observation 1: history 1 linearizable Simulator Most histories are linearizable history 2 linearizable Jepsen (distributed systems) ⋮ ⋮ Violat ( java.util.concurrent ) history m non-linearizable

  12. Execution history generated by Violat 
 for ConcurrentLinkedQueue toString(): “[]” poll(): null 1: size(): 0 isEmpty(): true 2: clear() addAll(1, 2): true 3: removeAll(1, 0): false retainAll(2, 0): true 4: retainAll(0, 0): false poll(): null 5: poll(): 2 toArray(): [] 6: remove(0): false containsAll(1, 1): false 7:

  13. Execution history generated by Violat 
 for ConcurrentLinkedQueue toString(): “[]” poll(): null 1: total schedules: 1,004,640 lin. witnesses: 134,400 size(): 0 isEmpty(): true 2: clear() addAll(1, 2): true 3: removeAll(1, 0): false retainAll(2, 0): true 4: retainAll(0, 0): false poll(): null 5: poll(): 2 toArray(): [] 6: remove(0): false containsAll(1, 1): false 7:

  14. Execution history generated by Violat 
 for ConcurrentLinkedQueue toString(): “[]” poll(): null 1: total schedules: 1,004,640 lin. witnesses: 134,400 size(): 0 isEmpty(): true 2: addAll(1, 2): true clear() 3: removeAll(1, 0): false retainAll(2, 0): true 4: retainAll(0, 0): false poll(): null 5: poll(): 2 toArray(): [] 6: remove(0): false containsAll(1, 1): false 7:

  15. Execution history generated by Violat 
 for ConcurrentLinkedQueue toString(): “[]” poll(): null 1: total schedules: 1,004,640 lin. witnesses: 134,400 size(): 0 isEmpty(): true 2: addAll(1, 2): true clear() 3: removeAll(1, 0): false retainAll(2, 0): true 4: retainAll(0, 0): false poll(): null 5: poll(): 2 toArray(): [] 6: remove(0): false containsAll(1, 1): false 7:

  16. Linearizability depth Strong hitting: 
 Given d ≥ 1 , a schedule 𝛃 strongly hits a d -tuple of operations (op 0 , …, op d-1 ) if it • maximally delays each op i • while maintaining the relative order op 0 < 𝛃 … < 𝛃 op d-1 d-Linearizable history: 
 There exist operations op 0 , …, op d-1 such that every schedule that strongly hits 
 (op 0 , …, op d-1 ) is a witness to linearizability Linearizability depth of a history: 
 Smallest d ≥ 1 such that the history is d -linearizable

  17. History from the example has linearizability depth 1 toString(): “[]” poll(): null 1: total schedules: 1,004,640 lin. witnesses: 134,400 size(): 0 isEmpty(): true 2: clear() addAll(1, 2): true 3: removeAll(1, 0): false retainAll(2, 0): true 4: retainAll(0, 0): false poll(): null 5: poll(): 2 toArray(): [] 6: remove(0): false containsAll(1, 1): false 7:

  18. History from the example has linearizability depth 1 toString(): “[]” poll(): null 1: total schedules: 1,004,640 lin. witnesses: 134,400 size(): 0 isEmpty(): true 2: clear() addAll(1, 2): true 3: Observation 2: removeAll(1, 0): false retainAll(2, 0): true 4: Most linearizable histories have small linearizability depth retainAll(0, 0): false poll(): null 5: poll(): 2 toArray(): [] 6: remove(0): false containsAll(1, 1): false 7:

  19. Checking d-linearizability Recall: A history is d -linearizable if there exist operations op 0 , …, op d-1 such that every schedule that strongly hits (op 0 , …, op d-1 ) is a witness to linearizability Strong d-hitting family: A set of schedules 𝓖 is a strong d -hitting family if it strongly hits every d -tuple of operations Conclusion: To check d -linearizability, it suffices to explore schedules from 
 a strong d -hitting family

  20. Size of strong hitting families [OOPSLA ’18] Given a history of n operations on k threads, and d ≥ 1 : • There is a strong d -hitting family of size O(n d ) • There is a strong d -hitting family of size O(kn d-1 ) : 
 A single schedule can strongly hit all operations in a thread

  21. For the history from the example, 1-linearizability is shown by exploring 7 schedules! toString(): “[]” poll(): null total schedules: 1,004,640 1: lin. witnesses: 134,400 size(): 0 isEmpty(): true 2: strong 1-hit. family: 7 clear() addAll(1, 2): true 3: removeAll(1, 0): false retainAll(2, 0): true 4: retainAll(0, 0): false poll(): null 5: poll(): 2 toArray(): [] 6: remove(0): false containsAll(1, 1): false 7:

  22. Experiments Observation 1: Most execution histories are linearizable Observation 2: Most linearizable histories have small linearizability depth Goal: Validate the observations for the histories generated by Violat on java.util.concurrent

  23. Breakdown of histories generated by Violat 
 for ConcurrentLinkedQueue non-linearizable: 3 linearizable: 616 sequential: 161 Total: 780 histories

  24. Breakdown of histories generated by Violat non-linearizable linearizable sequential ArrayBlockingQueue ConcurrentHashMap ConcurrentLinkedDeque ConcurrentLinkedQueue ConcurrentSkipListMap ConcurrentSkipListSet LinkedBlockingDeque LinkedBlockingQueue LinkedTransferQueue PriorityBlockingQueue 0 377 753 1130 1506 Total number of histories

  25. Linearizable histories whose linearizability is shown by exploring strong d-hitting families 100% 87.5% 75% 62.5% 50% 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 d = ArrayBlockingQueue ConcurrentHashMap ConcurrentLinkedDeque ConcurrenLinkedQueue ConcurrentSkipListMap ConcurrentSkipListSet LinkedBlockingDeque LinkedBlockingQueue LinkedTransferQueue PriorityBlockingQueue

Recommend


More recommend