Akka Typed 比 Classic 慢

Akka Typed slower than Classic

在对 Akka classic 有了基本的了解后,我转到了 Typed 并注意到,我的代码的 typed 版本比经典版本慢得多。

任务是汇总每个工具的“报价”(包含工具名称、时间戳和价格)。

在经典代码中,我为每个乐器动态创建一个演员,并在演员系统外部保留一个 Map 以将传入的滴答委托给。

在键入的代码中,需要一个“父级”,因此我将带有 Map 的路由逻辑移到了这个父级 actor 中,所以我在这里得到了两个 Actors 类(实际的 tick actor 和路由父角色)。

除此之外,代码几乎相同,只是一次通过经典 api 实现并输入一次。

当(原始地)测试这两种逻辑时,我发现使用经典逻辑的版本处理 1,000,000 个报价需要不到 1.5 秒,而键入的版本需要 3.5 秒多一点。

第一个明显的原因是将守护父级(也是路由器)移动到它自己的 PinnedDispatcher,因此它可以 运行 在它自己的线程上,而所有其他参与者都使用默认线程池。这大大提高了性能,导致处理 1,000,000 个滴答声大约需要 2.1 秒。

我的问题是:有谁知道剩余性能(0.6 秒)可能会丢失的地方?

Typed 在 classic 之上运行(typed Behavior<T> 被有效地包装在一个将消息转换为 T 的函数中;一旦被包装,它就可以被视为基本上是 classic Receive), 所以它引入了一些开销 per-message.

我从将路由 parent 放在固定调度程序上的改进中猜测,类型化实现通过 parent 发送每个滴答声,所以请注意,您会产生两次开销.根据相对于刻度数的 Instrument 的数量,通过使用 parent 之类的 SpawnProtocol 之类的东西,可以使键入的代码更像经典代码,所以ActorSystem 之外的代码会在 high-level:

  • 检查本地 Map<Instrument, ActorRef<Tick>>(或其他)
  • 如果有一个 ActorRef 用于有问题的工具,请将标记发送到 ActorRef
  • 否则,向 parent 演员索取与所讨论乐器相对应的 ActorRef<Tick>;然后将生成的 ActorRef 保存在本地 Map 并将勾号发送到那个 ActorRef

这更像是经典中的情况:消息数量(忽略内部系统消息)现在是 100 万加上 Instrument 数量的 2 倍,而不是 200 万。