Diese Präsentation wurde erfolgreich gemeldet.

Scalaz 8 vs Akka Actors

12

Teilen

1 von 31
1 von 31

Scalaz 8 vs Akka Actors

12

Teilen

Herunterladen, um offline zu lesen

In this presentation, John A. De Goes looks at several concurrency and scalability problems similar to the ones all programmers have to face, and shows how purely functional solutions written using Scalaz 8 are shorter, faster, easier to test, and easier to understand than competing solutions written using Akka actors. Discover how functional programming can be your secret superpower when it comes to quickly building bullet-proof business applications!

In this presentation, John A. De Goes looks at several concurrency and scalability problems similar to the ones all programmers have to face, and shows how purely functional solutions written using Scalaz 8 are shorter, faster, easier to test, and easier to understand than competing solutions written using Akka actors. Discover how functional programming can be your secret superpower when it comes to quickly building bullet-proof business applications!

Weitere Verwandte Inhalte

Ähnliche Bücher

Kostenlos mit einer 30-tägigen Testversion von Scribd

Alle anzeigen

Ähnliche Hörbücher

Kostenlos mit einer 30-tägigen Testversion von Scribd

Alle anzeigen

Scalaz 8 vs Akka Actors

  1. 1. Scalaz 8 vs Akka Actors Scalar 2018 - Warsaw, Poland John A. De Goes @jdegoes - http://degoes.net
  2. 2. WARNING: The talk you are about to see was rejected from Scala Days 2018 due to extremely disturbing content. Attendee discretion is advised.
  3. 3. Ultimate Question of Software Development
  4. 4. Ultimate Question of Software Development How can we bend light so we can reactively build reactive microsystems that react to reacting reactivity???
  5. 5. Answer to the Ultimate Question of Software Development PartialFunction[Any, Unit] Input Message AKA “Actor”
  6. 6. Killer Use Cases for Actors 1. Parallelism 2. Concurrent State 3. Distributed Compute3. Persistence
  7. 7. 1. Parallelism sealed trait Message case class Chunk(v: Array[Byte]) class ChunkActor extends Actor { def receive = { case Chunk(v) => sender ! encrypt(v) } } val chunkActors = context.actorOf(Props[ChunkActor]. withRouter(RoundRobinPool(4)), name = "ChunkActors") … chunks.foreach (chunk => chunkActors forward (Chunk(chunk))) IO.concurrently(chunks.map(encrypt(_)))
  8. 8. Killer Use Cases for Actors 1. Parallelism 2. Concurrent State 3. Distributed Compute3. Persistence
  9. 9. 2. Concurrent State sealed trait Message case object Get extends Message case class Inc(value: Int) extends Message class Counter extends Actor { var counter: Int = 0 def receive = { case Get => sender ! counter case Inc(v) => counter += v sender ! counter } } ... val system = ActorSystem("counter") val counter = system.actorOf(Props[Counter], "counter") counter ! Inc(20) val counter = IORef(0) ... counter.modify(_ + 20)
  10. 10. Killer Use Cases for Actors 1. Parallelism 2. Concurrent State 3. Distributed Compute3. Persistence
  11. 11. 3. Persistence class MyProcessor extends Processor { def receive = { case Persistent(payload, sequence) => doWork(payload, sequence) case other => } } ... val processor = actorOf(Props[MyProcessor], name = "myProcessor") processor ! Persistent("foo") processor ! "bar" val processor = payload => for { sequence <- counter.modify(_ + 1) _ <- persist(payload) v <- doWork(payload, sequence) } yield v
  12. 12. Killer Use Cases for Actors 1. Parallelism 2. Concurrent State 3. Distributed Compute3. Persistence
  13. 13. 4. Distributed Compute class SimpleClusterListener extends Actor with ActorLogging { val cluster = Cluster(context.system) // subscribe to cluster changes, re-subscribe when restart override def preStart(): Unit = { cluster.subscribe(self, initialStateMode = InitialStateAsEvents, classOf[MemberEvent], classOf[UnreachableMember]) } override def postStop(): Unit = cluster.unsubscribe(self) def receive = { case MemberUp(member) => log.info("Member is Up: {}", member.address) case UnreachableMember(member) => log.info("Member detected as unreachable: {}", member) case MemberRemoved(member, previousStatus) => log.info( "Member is Removed: {} after {}", member.address, previousStatus) case _: MemberEvent => // ignore } } ¯_(ツ)_/¯
  14. 14. 4. Distributed Compute
  15. 15. Killer Use Cases for Actors 1. Parallelism 2. Concurrent State 3. Distributed Compute3. Persistence ✓
  16. 16. PartialFunction[Any, Unit]
  17. 17. Can We Do Better?
  18. 18. Next-Generation Purely Functional Actor Design A => B Input Message Output Message AKA “Function”
  19. 19. Next-Generation Purely Functional Actor Design A => F[B] Input Message Output Message Effectful Actor Output Effect
  20. 20. Next-Generation Purely Functional Actor Design G[A => F[B]] Input Message Output Message Effectfully-Created Effectful Actor Output Effect Creation Effect
  21. 21. Next-Generation Purely Functional Actor Design def increment(n: Int): IO[Void, Int] = ???
  22. 22. Next-Generation Purely Functional Actor Design def increment(n: Int): IO[Void, Int] = for { counter <- IORef(0) value <- counter.modify(_ + n) } yield value
  23. 23. Next-Generation Purely Functional Actor Design val makeActor: IO[Void, Int => IO[Void, Int]] = for { counter <- IORef(0) actor = (n: Int) => counter.modify(_ + n) } yield actor
  24. 24. Next-Generation Purely Functional Actor Design type Actor[E, I, O] = I => IO[E, O] val makeActor: IO[Void, Actor[Void, Int, Int]] = for { counter <- IORef(0) actor = (n: Int) => counter.modify(_ + n) } yield actor implicit class ActorSyntax[E, I, O](actor: Actor[E, I, O]) { def ! (i: I): IO[E, O] = actor(i) } ... for { v <- actor ! 20 } yield v
  25. 25. Next-Generation Purely Functional Actor Design val makeActor: IO[Void, Actor[Void, Int, Int]] = for { counter <- IORef(0) queue <- AsyncQueue.make[(Int, Promise[Void, Int])] worker <- queue.take.flatMap(t => counter.modify(_ + t._1).flatMap(t._2.complete)).forever.fork actor = (n: Int) => for { promise <- Promise.make[Void, Int] _ <- queue.offer((n, promise)) value <- promise.get } yield value } yield actor
  26. 26. Next-Generation Purely Functional Actor Design type Actor[E, I, O] = I => IO[E, O] def persistIn[E, I: EncodeJson, O](actor: Actor[E, I, O]): Actor[E, I, O] def persistOut[E, I, O: EncodeJson](actor: Actor[E, I, O]): Actor[E, I, O] def compose[E, I, O, U](l: Actor[E, I, O], r: Actor[E, O, U]): Actor[E, I, U] ...
  27. 27. Scalaz 8 1. Parallelism 2. Synchronization 3. Asynchronicity3. Signaling
  28. 28. Scalaz 8 Scalaz 8 Effect ✓ 195x faster* ✓ Type-safe ✓ Purely functional ✓ Resource-safe ✓ Compositional Akka Future & Actors ❌ 195x slower* ❌ Type-unsafe ❌ Dysfunctional ❌ Resource-unsafe ❌ Compostable *Up to, in some benchmarks.
  29. 29. Top Reasons to Choose Actors* 1. Your Code Is Way Too Fast 2. Your Code Is Too Composable 3. Your Code Is Too Easy to Understand *Actors are sometimes useful, like assembly language. But we can often do better.
  30. 30. Scalaz 8 vs Akka Actors THANK YOU TO SCALAR & SOFTWAREMILL! John A. De Goes @jdegoes - http://degoes.net

×