Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Deterministic Concurrency and Large-Scale Static Analysis

Philipp Haller
December 15, 2017
44

Deterministic Concurrency and Large-Scale Static Analysis

Philipp Haller

December 15, 2017
Tweet

Transcript

  1. Deterministic Concurrency and Large-Scale Static Analysis Philipp Haller KTH Royal

    Institute of Technology Stockholm, Sweden Joint work with: Simon Geries, Michael Eichberg, Guido Salvaneschi, and Alexandre Loiko
  2. Reactive Async: Expressive Deterministic Concurrency — Philipp Haller Have we

    solved concurrent programming, yet? The problem with concurrency: – It’s difficult: • Race conditions • Deadlocks • Livelocks • Fairness violations • … 2
  3. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Non-determinism

    • At the root of several hazards • Example 1: 3 @volatile var x = 0 def m(): Unit = { Future { x = 1 } Future { x = 2 } .. // does not access x } What’s the value of x when an invocation of m returns?
  4. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Reordering

    not always a problem! • Example 2: 4 val set = Set.empty[Int] Future { set.put(1) } set.put(2) Eventually, set contains both 1 and 2, always Bottom line: it depends on the datatype
  5. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller …

    and its operations! • Example 3: 5 val set = Set.empty[Int] Future { set.put(1) } Future { if (set.contains(1)) { .. } } set.put(2) Result depends on schedule!
  6. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Goal

    • Programming model providing static determinism guarantees • Starting from imperative, object-oriented language – pervasive aliasing – global state • Important concerns: expressivity and performance 6
  7. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Approach

    • Extend a future-style programming model with: – Lattice-based datatypes – Quiescence – Resolution of cyclic dependencies • Extend Scala's type system for static safety 7 Crucial for determinism! Increases expressivity!
  8. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Programming

    model Programming model based on two core abstractions:
 cells and cell completers – Cell = shared “variable” – Cell[K,V]: read-only interface; read values of type V – CellCompleter[K,V]: write values of type V to its associated cell – V must have an instance of a lattice type class 8 Monotonic updates
  9. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Example

    • Given a social graph – vertex = user • Traverse graph and collect IDs of “interesting” users • Graph large => concurrent traversal 9
  10. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Cell

    with user IDs (code simplified) 10 implicit object IntSetLattice extends Lattice[Set[Int]] { val empty = Set() def join(left: Set[Int], right: Set[Int]) = left ++ right } // add a user ID userIDs.putNext(Set(theUserID)) val userIDs = CellCompleter[Set[Int]] Bounded
 join-semilattice [1] Oliveira, Moors, and Odersky. Type classes as objects and implicits. OOPSLA 2010
  11. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Reading

    results • Problem: when reading a cell’s value, how do we know this value is not going to change any more? – There may still be ongoing concurrent activities – Manual synchronization (e.g., latches) error-prone 11
  12. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Freeze

    • Introduce operation to freeze cells • Attempting to mutate a frozen cell results in a failure • May only read from frozen cells – Ensures only unchangeable values are read – Weakens determinism guarantee 12 "All non-failing executions compute the same cell values." "Quasi- determinism"
  13. Reactive Async: Expressive Deterministic Concurrency — Philipp Haller Reading results:

    alternative approach • Problem: when reading a cell’s value, how do we know this value is not going to change any more? – There may still be ongoing concurrent activities • Alternative solution: Quiescence • Stronger than quasi-determinism 13
  14. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Quiescence

    • Intuitively: situation when values of cells are guaranteed not to change any more • Technically: – No concurrent activities ongoing or scheduled which could change values of cells – Detected by the underlying thread pool 14
  15. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Revisiting

    the example 15 // add a user ID userIDs.putNext(Set(theUserID)) .. val pool = new HandlerPool val userIDs = CellCompleter[Set[Int]](pool) // register handler // upon quiescence: read result value of cell pool.onQuiescent(userIDs.cell) { collectedIDs => .. } Safe to read from cell when pool quiescent!
  16. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Reactive

    threshold reads* 16 cell2.whenNext(cell1, Set(v1, v2, v3)) { v => // compute update for cell2 } • When value of a cell "crosses" a threshold set: update another cell – "Crosses" = new value greater than one of the values in the threshold set * non-reactive threshold reads:
 [2] Kuper, Turon, Krishnaswami, and Newton. Freeze after writing: Quasi-deterministic parallel programming with LVars. POPL 2014
  17. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Reactive

    threshold reads 17 cell2.whenNext(cell1, Set(Set(2), Set(2, 5))) { v => NextOutcome(v) } • Determinism requires restricting the threshold set • Example: powerset lattice Init state: cell1 = Set(0), cell2 = Set(0) • Permits non-deterministic executions cell1.putNext(Set(2)) cell1.putNext(Set(2, 5)) => handler sees Set(2) cell1.putNext(Set(2, 5)) cell1.putNext(Set(2)) => handler sees Set(2, 5)
  18. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Reactive

    threshold reads 18 • Determinism requires restricting the threshold set • Restriction:
 Incompatibility of elements of threshold set – v1, v2 incompatible iff LUB(v1, v2) = Top • Concurrent crossings of threshold set due to different elements yield failed executions – Turn potential non-determinism into failure, thus preserving quasi-determinism
  19. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Source

    of data races: variable capture 19 var x = 0 cell2.whenNext(cell1, Set(1)) { v => NextOutcome(x) } cell3.whenNext(cell1, Set(1)) { v => x = 1 NoOutcome } cell1.putNext(1) [3] Miller, Haller, and Odersky. Spores: a type-based foundation for closures in the age of concurrency and distribution. ECOOP 2014 Solution: use spores [2] to prevent • re-assigning captured variables • capturing mutable, shared data structures
  20. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Other

    sources of data races 20 class C { def set(x: Int): Unit = Global.f = x def get: Int = Global.f } object Global { var f: Int = 0 } cell2.whenNext(cell1, Set(1)) { v => val c = new C NextOutcome(c.get) } cell3.whenNext(cell1, Set(1)) { v => val c = new C c.set(1) NoOutcome } cell1.putNext(1)
  21. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Solution

    21 • Restrict instantiation within whenNext closures to classes conforming to the object capability model [3] • A class is conformant* ("ocap") iff – its methods only access parameters and this – its methods only instantiate ocap classes – types of fields and method parameters are ocap * simplified [4] Mark S. Miller. Robust Composition: Towards a Unified Approach to Access Control and Concurrency Control. PhD thesis, 2006
  22. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller How

    practical is the object capability requirement? 22 • How common is object-capability safe code in Scala? • Empirical study of >75,000 SLOC of open-source code
  23. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller How

    practical is the object capability requirement? 23 • Results:
  24. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller In

    the paper 24 • Formalization: object-oriented core languages • CLC1: type-based notion of object capabilities • CLC2: uniqueness via flow-insensitive permissions • CLC3: concurrent extension • Soundness proof • Isolation theorem for processes with shared heap [5] Haller and Loiko. LaCasa: Lightweight affinity and object capabilities in Scala. OOPSLA 2016
  25. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Dependency

    graphs Example: • Static analysis of JVM bytecode • Task:
 Determine purity of methods • Rules: – A method is impure if it accesses a non-final field – A method is impure if it calls an impure method – … 25 A B C “calls”
  26. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Cycle

    resolution • What if upon quiescence cells are empty and there is a dependency cycle? • Idea:
 Pluggable resolution policies • Example:
 Purity analysis should resolve all cells
 in cycle to “pure”, since no evidence of impurity 26 A B C
  27. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Specifying

    resolution policies • Role of the first type parameter of Cell[K,V] • Example: 27 object PurityKey extends Key[Purity] { def resolve[K <: Key[Purity]](cells: Seq[Cell[K, Purity]]) = cells.map(cell => (cell, Pure)) .. } closed strongly- connected component resolve all cells to Pure
  28. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Evaluation

    • Static analysis of JVM bytecode using the OPAL framework (OPen extensible Analysis Library) – New Scala-based, extensible bytecode toolkit – Fully concurrent • Rewrote purity analysis and immutability analysis • Ran analysis on JDK 8 update 45 (rt.jar) – 18’591 class files, 163’268 methods, 77’128 fields 28 http://www.opal-project.de
  29. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Results:

    immutability analysis • RA about 10x faster than FPCF • RA = 294 LOC, FPCF = 424 LOC (1.44x) 29 FPCF (secs.) 1.0 1.5 2.0 2.5 Reactive-Async (secs.) 0.1 0.2 0.3 1 Thread 2 Threads 4 Threads 8 Threads 16 Threads 2.15 2.20 2.25 2.30 2.35 1.15 1.20 1.25 1.30 1.35 0.290 0.295 0.300 0.105 0.110 0.115 box plot: whiskers = min/max
 top/bottom of box = 
 1st and 3rd quartile band in box: median FPCF = OPAL’s fixed point computation framework
  30. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Results:

    purity analysis • Best configs. (FPCF: 4 thr, RA: 16 thr): RA 1.75x faster • RA = 113 LOC, FPCF = 166 LOC (1.47x) 30 FPCF (secs.) 0.15 0.20 0.25 0.30 0.35 Reactive-Async (secs.) 0.1 0.2 0.3 0.4 0.5 1 Thread 2 Threads 4 Threads 8 Threads 16 Threads 0.43 0.44 0.45 0.09 0.10 0.11 0.335 0.340 0.345 0.165 0.170 0.175 0.180 0.185 0.18 0.19 0.20
  31. Reactive Async: Expressive Deterministic Concurrency — Philipp Haller Benchmarks: Monte

    Carlo simulation • Compute Net Present Value • 14-16 threads: Scala futures 23-36% faster than RA 31 Sequential Reactive Async Scala Futures 2.11.7 Runtime (ms) 0 1000 2000 3000 4000 5000 6000 Number of Threads 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 400 500 600 700 14 15 16
  32. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Benchmarks:

    parallel sum • Parallel sum of large collection of random ints • Performance competitive with Scala’s futures 32 Sequential Reactive Async Scala Futures 2.11.7 Runtime (ms) 0 50 100 150 200 250 300 Number of Threads 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  33. Deterministic Concurrency and Large-Scale Static Analysis — Philipp Haller Reactive

    Async: Conclusion • Deterministic concurrent programming model – Extension of imperative, object-oriented base language – Lattices and quiescence for determinism – Resolution of cyclic dependencies – Type system for object capabilities for safety • First experimental results • Ongoing and future work: – Complete formal development – Implement state-of-the-art static analyses 33 Thank you!