Concurrency
the
Functional Way
V. N. Nikhil Anurag
Concurrency the Functional Way
Who are you?
- Curious about Concurrency & Parallelism
- Interested on how it fits with FP concepts
- Considering it for next project or job
Concurrency the Functional Way
Who am I?
- My name is Nikhil
- Working at Zalando SE
- Started as Python Developer
- Wrote a book, Distributed Computing with Go
- Currently working with FP-Scala/Cats
Concurrency the Functional Way
Call 1
Email 1/2
Prep Food
Call 2
Email 2/2
Eat Food
You
Call 1
Email 1/2
Eat Food
You
Call 2
Prep Food
Eat Food
Friend
Call 3
Email 2/2
Concurrency
Parallelism
Concurrency the Functional Way
Different types of Concurrency
- Single Threaded Concurrency
- Multicore Concurrency & Parallelism
- Concurrency in FP
Concurrency the Functional Way
Single Threaded Concurrency
Single Threaded Concurrency
- Only one task at a time
- Runs on a single core
- Uses an Event Loop
Call 1
Email 1/2
Prep Food
Call 2
Email 2/2
Eat Food
Event Loop
Single Threaded Concurrency
- Only one task at a time
- Runs on a single core
- Uses an Event Loop
- Only works with IO bound tasks
- Used by languages like Python, Ruby, Nodejs etc.
- Language isn't designed around Concurrency
def get_meaning_of_everything():
do_async() # Might never be run
return 42
Concurrency the Functional Way
Multicore Concurrency
&
Parallelism
Multicore Concurrency & Parallelism
- Tasks executed parallelly == number of CPU cores
- Uses modified/extended event loop
Call 1
Email 1/2
Prep Food
Call 2
Email 2/2
You: Core #1
Friend: Core #2
Global
Run
queue
Multicore Concurrency & Parallelism
- Works with IO bound & CPU bound tasks
- Language isn't designed around advanced Concurrency constructs
- Limit Concurrent tasks
- Fan Out strategy
- Fan In strategy
- Still possible to make mistakes.
- Tasks executed parallelly == number of CPU cores
- Uses modified/extended event loop
func get_meaning_of_everything() {
go do_async() // Might never run
return 42
}
Concurrency the Functional Way
Concurrency in FP
Concurrency in FP
FP is well suited for Concurrency
-
Execute Sequentially: tasks.mapN(...)
-
Execute by Composition: task1.flatMap{ res1 => task2.flatMap{...} }
-
Execute in Parallel: tasks.parMapN(...)
Concurrency in FP
No Side Effects
def get_meaning_of_everything_bad() = {
do_async() // Not conventional FP code!
Task(42)
}
def get_meaning_of_everything() = {
do_async().flatMap{ _ =>
Task(42)
}
}
Concurrency in FP
Be the change you want to see in the world
object Mutable {
var mutX = 0
def incrementX() = { mutX += 1 }
}
object Immutable {
val incrementX = State[Int, Int] { state =>
(state + 1, state)
}
}
val (state, oldState) = Immutable.incrementX.run(10).value
Concurrency the Functional Way
Concurrency on JVM
&
Tagless Final
Concurrency on JVM
# Cores
OS Threads
JVM Threads
Thread Pool
Fibers
Tasks
Concurrency & Tagless Final
Pick your Concurrency Implementation
- One thread for Task Set: Cats Effect
- Auto context shift to ensure fairness: Monix Task
- Honorary Mention: Scalaz Task
- Also, Akka Futures
def get_answer_to_everything[F[_]: Effect](): F[Int] = {
do_async().flatMap{ _ =>
Effect[F].pure(42)
}
}
Questions?
Concurrency the Functional Way
By last-ent
Concurrency the Functional Way
- 1,086