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

Programming with Futures, Lattices, and Quiescence

3b84657fdb075382e3781310ca8a9a70?s=47 Philipp Haller
June 16, 2016
410

Programming with Futures, Lattices, and Quiescence

3b84657fdb075382e3781310ca8a9a70?s=128

Philipp Haller

June 16, 2016
Tweet

Transcript

  1. Programming with Futures, Lattices, and Quiescence Philipp Haller KTH Royal

    Institute of Technology Sweden @philippkhaller 1
  2. 2

  3. Programming with Futures, Lattices, and Quiescence — Philipp Haller Have

    we solved concurrent programming, yet? There are promising concurrent programming models and abstractions! 3 • Monitors • Futures, promises • Async/await • STM • Actors • Join-calculus • Agents • CSP • Reactive streams • …
  4. Programming with Futures, Lattices, and Quiescence — Philipp Haller Background

    • Authored or co-authored: – Scala Actors – Scala futures and promises – Scala Async • Contributed to Akka • Akka.js project at Typesafe 4 More proposals and research projects: •Scala Joins •FlowPools •Spores ..
  5. Programming with Futures, Lattices, and Quiescence — Philipp Haller Why

    are there so many? The problem with concurrency: – It’s difficult! – Multiple hazards: • Race conditions • Deadlocks • Livelocks • Violation of fairness 5
  6. Programming with Futures, Lattices, and Quiescence — Philipp Haller Non-Determinism

    • At the root of several hazards • Example 1: 6 @volatile var x = 0 def m(): Unit = { Future { x = 1 } .. // does not access x x = 2 } What’s the value of x • when m returns? • when the future is completed?
  7. Programming with Futures, Lattices, and Quiescence — Philipp Haller Non-Determinism

    • At the root of several hazards • Example 2: 7 @volatile var x = 0 def m(): Unit = { Future { x = 1 } Future { x = 2 } .. // does not access x } What’s the value of x • when m returns? • when the futures are completed?
  8. Programming with Futures, Lattices, and Quiescence — Philipp Haller Reordering

    not always a problem! • Example 3: 8 import scala.collection.concurrent.TrieMap val set = new TrieMap[Int, Int] Future { set.put(1, 0) } set.put(2, 0) Eventually, set contains both 1 and 2, always Bottom line: it depends on the datatype
  9. Programming with Futures, Lattices, and Quiescence — Philipp Haller …

    and its operations! • Example 4: 9 val set = new TrieMap[Int, Int] Future { set.put(1, 0) } Future { if (set.contains(1)) { .. } } set.put(2, 0) Result depends on schedule!
  10. Programming with Futures, Lattices, and Quiescence — Philipp Haller Important

    questions Q1:
 How do we know we have written a deterministic concurrent program? – What about Heisenbugs? • No race in 1’000’000 runs, race in run 1’000’001 10 Goal: simple criteria that guarantee determinism
  11. Programming with Futures, Lattices, and Quiescence — Philipp Haller Important

    questions Q2:
 How do we ensure expressivity while providing determinism? – Draconian restrictions undesired! 11 Goal: reconcile determinism and expressivity
  12. Programming with Futures, Lattices, and Quiescence — Philipp Haller Approach

    • Extend futures and promises with: – Lattice-based operations – Quiescence – Resolution of cyclic dependencies • Evaluation in terms of expressivity and performance – Case study: static analysis of JVM bytecode 12 Crucial for determinism! Increases expressivity!
  13. Programming with Futures, Lattices, and Quiescence — Philipp Haller Enter

    Reactive Async Programming model based on two core abstractions:
 cells and cell completers – Cell[K,V] extends Future[V] – CellCompleter[K,V] extends Promise[V] – V must have an instance of a lattice type class • Monotonic updates 13
  14. Programming with Futures, Lattices, and Quiescence — Philipp Haller Example

    • Given a social graph – vertex = user • Traverse graph and collect IDs of “interesting” users • Graph large => concurrent traversal 14
  15. Programming with Futures, Lattices, and Quiescence — Philipp Haller Solution

    • Collect IDs of interesting users in a cell • Cell contains set of integers 15 OK: subsets of the set of all integers form a lattice
  16. Programming with Futures, Lattices, and Quiescence — Philipp Haller Cell

    with user IDs (code simplified) 16 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
  17. Programming with Futures, Lattices, and Quiescence — Philipp Haller Reading

    the result • 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 • Solution: 17 Koyaanisqatsi Quiescence
  18. Programming with Futures, Lattices, and Quiescence — 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 18
  19. Programming with Futures, Lattices, and Quiescence — Philipp Haller Revisiting

    the example 19 // 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!
  20. Programming with Futures, Lattices, and Quiescence — Philipp Haller Handler

    pools Execution context with extensions: – Event-driven quiescence API – Resolution of dependencies between cells 20 Dependency resolution?
  21. Programming with Futures, Lattices, and Quiescence — Philipp Haller Expressing

    concurrent dataflow • Cells provide non-blocking interface – Low level: callbacks – High level: combinators • Important purpose: express concurrent dataflow • Problem: 21 What if the dataflow graph is cyclic? Like futures fut fun fut’ pred fut’’ fut.map(fun).filter(pred) Futures
  22. Programming with Futures, Lattices, and Quiescence — Philipp Haller Dataflow

    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 – … 22 A B C “calls”
  23. Programming with Futures, Lattices, and Quiescence — 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 could not show impurity 23 A B C
  24. Programming with Futures, Lattices, and Quiescence — Philipp Haller Specifying

    resolution policies • Role of the first type parameter of Cell[K,V] • Example: 24 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
  25. Programming with Futures, Lattices, and Quiescence — Philipp Haller Purity

    analysis: set up 25 for { classFile <- project.allProjectClassFiles method <- classFile.methods } { val methodCompleter = CellCompleter(pool, PurityKey) pool.execute { analyze(project, methodCompleter, classFile, method) } } val analysisDoneFuture = pool.quiescentResolveCells()
  26. Programming with Futures, Lattices, and Quiescence — Philipp Haller Evaluation

    • Static analysis of JVM bytecode using the OPAL framework (OPen extensible Analysis Library) – Newly developed, highly adaptable bytecode toolkit – Fully concurrent • Rewrote purity analysis and immutability analysis • Ran analysis on JDK 8 (rt.jar) – 18’591 class files, 163’268 methods, 77’128 fields 26 http://www.opal-project.de
  27. Programming with Futures, Lattices, and Quiescence — Philipp Haller Preliminary

    results • RA’s implementation not yet optimized 27 RA 15% faster than OPAL’s implementation with • code size reduced by a factor of two • determinism properties
  28. Programming with Futures, Lattices, and Quiescence — Philipp Haller Ongoing

    and future work • Benchmarking and optimization • Determinism as an effect – Determinism guaranteed by type checker – Effect system for Dotty • Macro support à la Async? 28
  29. Programming with Futures, Lattices, and Quiescence — Philipp Haller Reactive

    Async: conclusion • New concurrent programming model – Lattices and quiescence for determinism – Resolution of cyclic dependencies • Promising preliminary results • Future: static checking of determinism via effects 29 https://github.com/phaller/reactive-async Thank you!
  30. 30

  31. 31