lxohi
lxohi

Reputation: 350

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?

Upvotes: 6

Views: 522

Answers (1)

expert
expert

Reputation: 30095

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).

Upvotes: 3

Related Questions