Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why adding async boundary in Akka Streams costs a lot of CPU?

I've found that my Akka Streams program had unexpected CPU usage.

Here is a simple example:

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Sink, Source}

implicit val system: ActorSystem = ActorSystem.create("QuickStart")
implicit val materializer: ActorMaterializer = ActorMaterializer()

Source.repeat(Unit)
  .to(Sink.ignore)
  .run()

The code piece above will let source and sink runs in the same actor.

It uses about 105% CPU usage on my laptop. Works as expected.

And after I was added an async boundary:

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Sink, Source}

implicit val system: ActorSystem = ActorSystem.create("QuickStart")
implicit val materializer: ActorMaterializer = ActorMaterializer()

Source.repeat(Unit)
  .async // <------ async boundary here
  .to(Sink.ignore)
  .run()

This code piece now will use about 600% of CPU usage on my 4c8t laptop.

I was expecting by adding an async boundary this stream will run in 2 separate actors and will cost a little more than 200% CPU. But it costs a lot more than 200%.

What may causes async boundary to use that much CPU?

like image 986
lxohi Avatar asked Oct 19 '18 05:10

lxohi


1 Answers

Default akka.actor.default-dispatcher parameter is Java's ForkJoinPool. It's initialized via call to ThreadPoolConfig.scaledPoolSize. Thus it defaults to starting pool of size (number of processors * 3) and max = parallelism-max (64).

like image 77
expert Avatar answered Nov 15 '22 07:11

expert