Optimize TCP stream writes, #23919 (#23920)

* This is an optimization of TcpStreamLogic to accumulating bytes in a buffer while waiting for
  acknoledgment of pending write. This improves throughput for small messages (frames)
  without sacrificing latency. While waiting for the ack the stage will eagerly pull
  from upstream until the buffer limit is exceeded. Accumulated bytes are written
  immediately when ack is received.
* Noticed 20x throughput improvement with Artery MaxThroughputSpec thanks to this buffer
  when working on the Artery TCP implementation. The small message (100 bytes) benchmark
  improved from 30k msg/s to 600k msg/s.
This commit is contained in:
Patrik Nordwall 2017-11-07 03:07:29 +01:00 committed by Konrad `ktoso` Malawski
parent d7330c3c72
commit f017f6a90a
6 changed files with 175 additions and 44 deletions

View file

@ -65,8 +65,10 @@ object Tcp extends ExtensionId[Tcp] with ExtensionIdProvider {
final class Tcp(system: ExtendedActorSystem) extends akka.actor.Extension {
import Tcp._
private val settings = ActorMaterializerSettings(system)
// TODO maybe this should be a new setting, like `akka.stream.tcp.bind.timeout` / `shutdown-timeout` instead?
val bindShutdownTimeout = ActorMaterializer()(system).settings.subscriptionTimeoutSettings.timeout
val bindShutdownTimeout = settings.subscriptionTimeoutSettings.timeout
/**
* Creates a [[Tcp.ServerBinding]] instance which represents a prospective TCP server binding on the given `endpoint`.
@ -103,7 +105,8 @@ final class Tcp(system: ExtendedActorSystem) extends akka.actor.Extension {
options,
halfClose,
idleTimeout,
bindShutdownTimeout))
bindShutdownTimeout,
settings.ioSettings))
/**
* Creates a [[Tcp.ServerBinding]] instance which represents a prospective TCP server binding on the given `endpoint`
@ -175,7 +178,8 @@ final class Tcp(system: ExtendedActorSystem) extends akka.actor.Extension {
localAddress,
options,
halfClose,
connectTimeout)).via(detacher[ByteString]) // must read ahead for proper completions
connectTimeout,
settings.ioSettings)).via(detacher[ByteString]) // must read ahead for proper completions
idleTimeout match {
case d: FiniteDuration tcpFlow.join(TcpIdleTimeout(d, Some(remoteAddress)))