I'm currently working on a project that extensively uses Akka and Akka Streams.
One question/problem keeps coming up while working with it: What is the best practice for the Materializer which is needed in all places where streams are used. Especially when I'm inside an Actor, where I only can access the ActorSystem, should I manually pass in an existing Materializer instance or just create one when I need it?
I'm especially worried about the resource usage and performance when instantiating Materializers on demand.
The creation of ActorMaterializer
s is fairly cheap and having a reasonable proliferation of them shouldn't be an issue in the majority of cases.
If you chase the chain of calls starting from ActorMaterializer.apply
(see source code) you'll find that ActorMaterializer
(or better, ActorMaterializerImpl
) is not performing anything significant at creation time.
Just to give you an idea of how it compares to an ActorSystem
creation, consider the following code
val sysStart = System.nanoTime()
val actorSystem = ActorSystem("mySystem")
val sysDuration = FiniteDuration(System.nanoTime() - sysStart, TimeUnit.NANOSECONDS)
println(s"System creation: ${sysDuration.toMillis} ms")
val matStart = System.nanoTime()
val materializer = ActorMaterializer()(actorSystem)
val matDuration = FiniteDuration(System.nanoTime() - matStart, TimeUnit.NANOSECONDS)
println(s"Materializer creation: ${matDuration.toMillis} ms")
outputs this on my laptop
System creation: 901 ms
Materializer creation: 14 ms
However, as Johan pointed out in the comments, it is important to add that materializers' lifecycle needs to be properly managed, invoking shutdown
whenever they stop being useful, to avoid leaking resources.
To recap, passing a materializer around whenever possible is a sound choice. Whenever this is not convenient though, its creation is cheap, but pay attention to shut it down properly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With