I'm working on a performance issue that occurred when switching current project to Akka stream.
After simplify the problems, it seems that Akka stream was passing much lesser messages then I was expected.
Here I have two very simple pieces of code, both just writing 10 bytes a time to a file on disk.
The first one uses two threads and a ArrayBlockingQueue connecting them:
val bw = Files.newBufferedWriter(Paths.get("test.txt"))
val target = "0123456789".toCharArray
val abq = new ArrayBlockingQueue[Array[Char]](10000)
new Thread(new Runnable {
override def run(): Unit = {
while (true) {
bw.write(abq.take())
}
}
}).start()
while (true) {
abq.put(target)
}
The second one uses Akka stream:
implicit val system: ActorSystem = ActorSystem("TestActorSystem")
implicit val materializer: ActorMaterializer = ActorMaterializer()
// Source & Sink runs in two actors
// Both output of Source & input of Sink were buffered
Source
.repeat(ByteString("0123456789"))
.buffer(8192, OverflowStrategy.backpressure)
.async
.runWith(
FileIO
.toPath(Paths.get("test.txt"))
.withAttributes(Attributes.inputBuffer(8192, 8192))
)
And I have found out that the first one writes file at a speed of 27.4MB/s while the second one only writes file at a speed of 3.4MB/s on my testing machine. The thread-with-arrayBlockingQueue one was 8 times faster then the Akka one.
I have tried to change the Sink from FileIO to a hand written Sink that writes to a BufferedWriter. This let the second one's speed increases to 5.5MB/s but still 5x slower than the first one.
In my understanding, the Akka stream would have a much better performance comparing it reaches now.
Is there something that I've done was wrong in this scenario?