Monix in practice Ilya Murzinov https://twitter.com/ilyamurzinov - - PowerPoint PPT Presentation

monix in practice
SMART_READER_LITE
LIVE PREVIEW

Monix in practice Ilya Murzinov https://twitter.com/ilyamurzinov - - PowerPoint PPT Presentation

Monix in practice Ilya Murzinov https://twitter.com/ilyamurzinov https://github.com/ilya-murzinov Slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 1 / 30 Monix in practice - Ilya Murzinov, slides:


slide-1
SLIDE 1

Monix in practice

Ilya Murzinov

https://twitter.com/ilyamurzinov https://github.com/ilya-murzinov Slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 1 / 30

slide-2
SLIDE 2

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 2 / 30

slide-3
SLIDE 3

Referential transparency

def goodFunction() = 2 + 2

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 3 / 30

slide-4
SLIDE 4

Referential transparency

def goodFunction() = 2 + 2 def badFunction() = { sendMessage() 2 + 2 }

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 3 / 30

slide-5
SLIDE 5

Monix

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 4 / 30

slide-6
SLIDE 6

Monix modules

monix-eval - Task, Coeval, MVar etc. monix-reactive - Observable, Observer (push-based streaming) monix-tail - Iterant (pull-based streaming) monix-execution - Scheduler & bunch of performance hacks Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 5 / 30

slide-7
SLIDE 7

Task[A]

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 6 / 30

slide-8
SLIDE 8

Task vs Future

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-9
SLIDE 9

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-10
SLIDE 10

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Not cancellable Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-11
SLIDE 11

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Not cancellable Always asyncronous Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-12
SLIDE 12

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Not cancellable Always asyncronous Not stack-safe Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-13
SLIDE 13

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Not cancellable Always asyncronous Not stack-safe monix.Task: Lazy (ref. transparent) Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-14
SLIDE 14

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Not cancellable Always asyncronous Not stack-safe monix.Task: Lazy (ref. transparent) Cancellable Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-15
SLIDE 15

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Not cancellable Always asyncronous Not stack-safe monix.Task: Lazy (ref. transparent) Cancellable Not always asyncronous Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-16
SLIDE 16

Task vs Future

scala.concurrect.Future: Eager (thus not ref. transparent) Not cancellable Always asyncronous Not stack-safe monix.Task: Lazy (ref. transparent) Cancellable Not always asyncronous Stack (and heap) safe Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 7 / 30

slide-17
SLIDE 17

Scheduler

Schedule delayed execution Schedule periodic execution Provide cancellation token Use different execution models Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 8 / 30

slide-18
SLIDE 18

ExecutionModel

AlwaysAsyncExecution SynchronousExecution BatchedExecution Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 9 / 30

slide-19
SLIDE 19

Scheduler

Scheduler.computation(name = "my-computation") Scheduler.io(name = "my-io")

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 10 / 30

slide-20
SLIDE 20

Scheduler

Scheduler.computation(name = "my-computation") Scheduler.io(name = "my-io") Scheduler.fixedPool("my-fixed-pool", 10) Scheduler.singleThread("my-single-thread")

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 10 / 30

slide-21
SLIDE 21

Creating a task

import monix.eval.Task // eagerly evaluates the argument Task.now(42) Task.now(println(42)) // suspends argument evaluation Task.eval(println(42)) // suspends evaluation + makes it asynchronous Task(println(42)) ... Task.evalOnce(...) Task.defer(...) Task.deferFuture(...) Task.deferFutureAction(...) ...

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 11 / 30

slide-22
SLIDE 22

Thread shifting

val t = Task.eval(println(42)) t.executeAsync t.executeOn(io) t.asyncBoundary(io)

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 12 / 30

slide-23
SLIDE 23

Thread shifting

import monix.execution.Scheduler import monix.execution.Scheduler.Implicits.global lazy val io = Scheduler.io(name = "my-io") val source = Task.eval(println( s"Running on thread: ${Thread.currentThread.getName}")) val async = source.executeAsync val forked = source.executeOn(io) val onFinish = Task.eval(println( s"Ends on thread: ${Thread.currentThread.getName}")) source // executes on main .flatMap(_ => source) // executes on main .flatMap(_ => async) // executes on global .flatMap(_ => forked) // executes on io .asyncBoundary // switch back to global .doOnFinish(_ => onFinish) // executes on global .runAsync

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 13 / 30

slide-24
SLIDE 24

Composing tasks

val extract: Task[Seq[String]] = ??? val transform: Seq[String] => Task[Seq[WTF]] = ??? val load: Seq[WTF] => Task[Unit] = ??? for { strings <- extract transformed <- transform(strings) _ <- load(transformed) } yield ()

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 14 / 30

slide-25
SLIDE 25

Composing tasks

val extract: Task[Seq[String]] = ??? val transform: Seq[String] => Task[Seq[WTF]] = ??? val load: Seq[WTF] => Task[Unit] = ??? for { strings <- extract transformed <- transform(strings) _ <- load(transformed) } yield () val extract1: Task[Seq[String]] = ??? val extract2: Task[Seq[String]] = ??? val extract3: Task[Seq[String]] = ??? val extract = Task.parMap3(extract1, extract2, extract3)(_ :+ _ :+ _)

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 14 / 30

slide-26
SLIDE 26

Composing tasks

val tasks: Seq[Task[A]] = Seq(task1, task2, ...) // Seq[Task[A]] => Task[Seq[A]] Task.sequence(tasks) Task.gather(tasks) Task.gatherUnordered(tasks)

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 15 / 30

slide-27
SLIDE 27

Composing tasks

val tasks: Seq[Task[A]] = Seq(task1, task2, ...) // Seq[Task[A]] => Task[Seq[A]] Task.sequence(tasks) Task.gather(tasks) Task.gatherUnordered(tasks) // Seq[Task[A]] => Task[A] Task.raceMany(tasks)

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 15 / 30

slide-28
SLIDE 28

Task cancellation

val task = ??? val f: CancelableFuture[Unit] = t.runAsync f.cancel()

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 16 / 30

slide-29
SLIDE 29

Task cancellation

val task = ??? val f: CancelableFuture[Unit] = t.runAsync f.cancel() Task { Thread.sleep(100); println(42) } .doOnCancel(Task.eval(println("On cancel"))) .runAsync .cancel() Thread.sleep(1000)

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 16 / 30

slide-30
SLIDE 30

Task cancellation

import monix.execution.Scheduler.Implicits.global val sleep = Task(Thread.sleep(100)) val t = sleep.flatMap(_ => Task.eval(println(42))) t.runAsync.cancel() Thread.sleep(1000)

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 17 / 30

slide-31
SLIDE 31

Task cancellation

import monix.execution.Scheduler.Implicits.global val sleep = Task(Thread.sleep(100)).cancelable val t = sleep.flatMap(_ => Task.eval(println(42))) t.runAsync.cancel() Thread.sleep(1000)

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 18 / 30

slide-32
SLIDE 32

Observable[A]

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 19 / 30

slide-33
SLIDE 33

Observable[A]

Lazy (ref. transparent) Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 20 / 30

slide-34
SLIDE 34

Observable[A]

Lazy (ref. transparent) Cancellable Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 20 / 30

slide-35
SLIDE 35

Observable[A]

Lazy (ref. transparent) Cancellable Safe (doesn't expose unsafe or blocking operations) Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 20 / 30

slide-36
SLIDE 36

Observable[A]

Lazy (ref. transparent) Cancellable Safe (doesn't expose unsafe or blocking operations) Allows fine-grained control over execution Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 20 / 30

slide-37
SLIDE 37

Observable[A]

Lazy (ref. transparent) Cancellable Safe (doesn't expose unsafe or blocking operations) Allows fine-grained control over execution Models single producer - multiple consumers communication Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 20 / 30

slide-38
SLIDE 38

Observable[A]

Lazy (ref. transparent) Cancellable Safe (doesn't expose unsafe or blocking operations) Allows fine-grained control over execution Models single producer - multiple consumers communication Non-blocking back-pressure Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 20 / 30

slide-39
SLIDE 39

Monix vs Akka streams

Monix has Simpler API Lighter (no dependency on actor framework) Better execution control Easier to understand internals Faster Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 21 / 30

slide-40
SLIDE 40

Performance

private[this] val list = 1 to 100 @Benchmark def monixMerge: Int = { val observables = list .map(_ => Observable.fromIterable(list).executeAsync) Observable .merge(observables: _*)(OverflowStrategy.BackPressure(10)) .foldL .runSyncUnsafe(1.seconds) } @Benchmark def akkaMerge: Int = { val source: Source[Int, NotUsed] = Source(list) val f = list .map(_ => source) .fold(Source.empty)(_.merge(_)) .runWith(Sink.fold(0)(_ + _)) Await.result(f, 1.second) }

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 22 / 30

slide-41
SLIDE 41

Performance

# Run complete. Total time: 00:06:45 Do not assume the numbers tell you what you want them to tell. Benchmark Mode Cnt Score Error Units MonixBenchmark.akkaMerge thrpt 10 46.207 ± 0.849 ops/s MonixBenchmark.monixMerge thrpt 10 531.182 ± 37.332 ops/s

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 23 / 30

slide-42
SLIDE 42

Example

Server Event source Client 1 Client 2 Client 3 Client N

...

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 24 / 30

slide-43
SLIDE 43

Example

val acceptClient: Task[(Long, Data)] = ??? def handleClientJoin(id: Long, data: Data, state: State): Task[State] = ??? def clientSubscriber(mState: MVar[State]) = Observable.repeat(()) .doOnSubscribe(() => println(s"Client subscriber started")) .mapTask(_ => acceptClient) .mapTask { case (id, s) => for { state <- mState.take newState <- handleClientJoin(id, s, state) _ <- mState.put(newState) } yield () } .completedL

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 25 / 30

slide-44
SLIDE 44

Example

val acceptEventSource: Task[Iterator[Event]] = ??? def handleEvent(event: Event, state: State): Task[State] def eventSourceProcessor(mState: MVar[State]) = Observable.repeat(()) .doOnSubscribe(() => println(s"Event processor started")) .mapTask(_ => acceptEventSource) .flatMap(it => Observable.fromIterator(it) .mapTask(e => for { state <- mState.take newState <- handleEvent(e, state) _ <- mState.put(newState) } yield ())) .headL

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 26 / 30

slide-45
SLIDE 45

Example

val io = Scheduler.io() val computation = Scheduler.computation() for { initialState <- MVar(State()) c = clientSubscriber(initialState).executeOn(io) e = eventSourceProcessor(initialState).executeOn(computation) _ <- Task.gatherUnordered(Seq(c, e)) } yield ()

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 27 / 30

slide-46
SLIDE 46

References

Monix (https://monix.io) Monix vs Cats-Effect Scalaz 8 IO vs Akka (typed) actors vs Monix @ SoftwareMill Solution of the example (https://github.com/ilya-murzinov/seuraajaa) Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 28 / 30

slide-47
SLIDE 47

Questions?

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 29 / 30

slide-48
SLIDE 48

Thanks!

Monix in practice - Ilya Murzinov, slides: https://ilya-murzinov.github.io/slides/scalaspb2018.pdf 30 / 30