Checking Linearizability Using Hitting Families Burcu Kulahcioglu - - PowerPoint PPT Presentation

checking linearizability using hitting families
SMART_READER_LITE
LIVE PREVIEW

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


slide-1
SLIDE 1

Checking Linearizability
 Using Hitting Families

Burcu Kulahcioglu Ozkan1, Rupak Majumdar1, Filip Niksic2

1 Max Planck Institute for Software Systems (MPI-SWS) 2 University of Pennsylvania

slide-2
SLIDE 2

Linearizability as a correctness condition

Two execution histories on a concurrent list:

addAll(1, 2): true isEmpty(): true clear() 1: 2: addAll(1, 2): true toString(): “[1]” clear() 1: 2:

Linearizable history: Concurrent operations can be totally ordered in a consistent way Linearizable concurrent object: All of its execution histories are linearizable

slide-3
SLIDE 3

Linearizability as a correctness condition

Two execution histories on a concurrent list:

addAll(1, 2): true isEmpty(): true clear() 1: 2: addAll(1, 2): true toString(): “[1]” clear() 1: 2:

linearizable

Linearizable history: Concurrent operations can be totally ordered in a consistent way Linearizable concurrent object: All of its execution histories are linearizable

slide-4
SLIDE 4

Linearizability as a correctness condition

Two execution histories on a concurrent list:

addAll(1, 2): true isEmpty(): true clear() 1: 2: addAll(1, 2): true toString(): “[1]” clear() 1: 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

slide-5
SLIDE 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
slide-6
SLIDE 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
slide-7
SLIDE 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(knd-1) linearizations

  • Experiments on java.util.concurrent:


In most cases linearizability witnessed by strong d-hitting families with d ≤ 5!

slide-8
SLIDE 8

Linearizability

Execution history induces a partial order of operations

  • p1(args1): res1
  • p2(args2): res2
  • p1(args1): res1
  • p2(args2): res2
  • p1 happens before op2
  • p1 and op2 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

slide-9
SLIDE 9

Testing concurrent objects [Wing and Gong ’93]

Simulator Concurrent object Sequential object
 (specification) linearizable history1 linearizable non-linearizable history2 historym ⋮ ⋮

slide-10
SLIDE 10

Testing concurrent objects [Wing and Gong ’93]

Simulator Concurrent object Sequential object
 (specification) linearizable history1 linearizable non-linearizable history2 historym ⋮ ⋮ Jepsen (distributed systems) Violat (java.util.concurrent)

slide-11
SLIDE 11

Testing concurrent objects [Wing and Gong ’93]

Simulator Concurrent object Sequential object
 (specification) linearizable history1 linearizable non-linearizable history2 historym ⋮ ⋮ Jepsen (distributed systems) Violat (java.util.concurrent) Observation 1: Most histories are linearizable

slide-12
SLIDE 12

Execution history generated by Violat
 for ConcurrentLinkedQueue

toString(): “[]” size(): 0 poll(): null isEmpty(): true clear() addAll(1, 2): true removeAll(1, 0): false retainAll(2, 0): true retainAll(0, 0): false poll(): null toArray(): [] poll(): 2 containsAll(1, 1): false remove(0): false 1: 2: 3: 4: 5: 7: 6:

slide-13
SLIDE 13

Execution history generated by Violat
 for ConcurrentLinkedQueue

toString(): “[]” size(): 0 poll(): null isEmpty(): true clear() addAll(1, 2): true removeAll(1, 0): false retainAll(2, 0): true retainAll(0, 0): false poll(): null toArray(): [] poll(): 2 containsAll(1, 1): false remove(0): false 1: 2: 3: 4: 5: 7: 6:

total schedules:

  • lin. witnesses:

1,004,640 134,400

slide-14
SLIDE 14

Execution history generated by Violat
 for ConcurrentLinkedQueue

toString(): “[]” size(): 0 poll(): null isEmpty(): true clear()

addAll(1, 2): true

removeAll(1, 0): false retainAll(2, 0): true retainAll(0, 0): false poll(): null toArray(): [] poll(): 2 containsAll(1, 1): false remove(0): false 1: 2: 3: 4: 5: 7: 6:

total schedules:

  • lin. witnesses:

1,004,640 134,400

slide-15
SLIDE 15

Execution history generated by Violat
 for ConcurrentLinkedQueue

toString(): “[]” size(): 0 poll(): null isEmpty(): true clear()

addAll(1, 2): true

removeAll(1, 0): false retainAll(2, 0): true retainAll(0, 0): false poll(): null toArray(): [] poll(): 2 containsAll(1, 1): false remove(0): false 1: 2: 3: 4: 5: 7: 6:

total schedules:

  • lin. witnesses:

1,004,640 134,400

slide-16
SLIDE 16

Linearizability depth

Strong hitting:
 Given d ≥ 1, a schedule 𝛃 strongly hits a d-tuple of operations (op0, …, opd-1) if it

  • maximally delays each opi
  • while maintaining the relative order op0 <𝛃 … <𝛃 opd-1

d-Linearizable history:
 There exist operations op0, …, opd-1 such that every schedule that strongly hits
 (op0, …, opd-1) is a witness to linearizability Linearizability depth of a history:
 Smallest d ≥ 1 such that the history is d-linearizable

slide-17
SLIDE 17

History from the example has linearizability depth 1

toString(): “[]” size(): 0 poll(): null isEmpty(): true clear() addAll(1, 2): true removeAll(1, 0): false retainAll(2, 0): true retainAll(0, 0): false poll(): null toArray(): [] poll(): 2 containsAll(1, 1): false remove(0): false 1: 2: 3: 4: 5: 7: 6:

total schedules:

  • lin. witnesses:

1,004,640 134,400

slide-18
SLIDE 18

History from the example has linearizability depth 1

toString(): “[]” size(): 0 poll(): null isEmpty(): true clear() addAll(1, 2): true removeAll(1, 0): false retainAll(2, 0): true retainAll(0, 0): false poll(): null toArray(): [] poll(): 2 containsAll(1, 1): false remove(0): false 1: 2: 3: 4: 5: 7: 6:

total schedules:

  • lin. witnesses:

1,004,640 134,400

Observation 2: Most linearizable histories have small linearizability depth

slide-19
SLIDE 19

Checking d-linearizability

Recall: A history is d-linearizable if there exist operations op0, …, opd-1 such that every schedule that strongly hits (op0, …, opd-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

slide-20
SLIDE 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(nd)
  • There is a strong d-hitting family of size O(knd-1):


A single schedule can strongly hit all operations in a thread

slide-21
SLIDE 21

For the history from the example, 1-linearizability is shown by exploring 7 schedules!

toString(): “[]” size(): 0 poll(): null isEmpty(): true clear() addAll(1, 2): true removeAll(1, 0): false retainAll(2, 0): true retainAll(0, 0): false poll(): null toArray(): [] poll(): 2 containsAll(1, 1): false remove(0): false 1: 2: 3: 4: 5: 7: 6:

total schedules:

  • lin. witnesses:

1,004,640 134,400 strong 1-hit. family: 7

slide-22
SLIDE 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

  • n java.util.concurrent
slide-23
SLIDE 23

Breakdown of histories generated by Violat
 for ConcurrentLinkedQueue

non-linearizable: 3 linearizable: 616 sequential: 161 Total: 780 histories

slide-24
SLIDE 24

Breakdown of histories generated by Violat

ArrayBlockingQueue ConcurrentHashMap ConcurrentLinkedDeque ConcurrentLinkedQueue ConcurrentSkipListMap ConcurrentSkipListSet LinkedBlockingDeque LinkedBlockingQueue LinkedTransferQueue PriorityBlockingQueue Total number of histories 377 753 1130 1506 non-linearizable linearizable sequential

slide-25
SLIDE 25

Linearizable histories whose linearizability is shown by exploring strong d-hitting families

50% 62.5% 75% 87.5% 100%

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 ArrayBlockingQueue ConcurrentHashMap ConcurrentLinkedDeque ConcurrenLinkedQueue ConcurrentSkipListMap ConcurrentSkipListSet LinkedBlockingDeque LinkedBlockingQueue LinkedTransferQueue PriorityBlockingQueue d =

slide-26
SLIDE 26

Conclusion

Contributions

  • 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(knd-1) linearizations

  • Experiments on java.util.concurrent:


In most cases linearizability witnessed by strong d-hitting families with d ≤ 5! Future work

  • Optimized linearizability checker for Jepsen; experiments on distributed systems
  • Weaker correctness conditions like causal consistency