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?

Github: github.com/last-ent

LinkedIn:   Link

Twitter: @last_ent

www: last-ent.com

Concurrency the Functional Way

By last-ent

Concurrency the Functional Way

  • 1,086