在对Akka Classic有了基本的了解之后,我转向Typed,并注意到我的代码的类型化版本明显比Classic的慢。
任务是按商品汇总“价格点”(包含商品名称、时间戳和价格)。
在经典代码中,我动态地为每个乐器创建一个actor,并在actor系统之外保留一个Map〈Instrument,ActorRef〉,以将传入的tick委托给它。
在类型化代码中,需要一个“parent”,因此我将带有Map的路由逻辑移到了这个父执行元中,所以我在这里得到了两个Actors类(实际的tick执行元和路由父执行元)。
除此之外,代码几乎是一样的,只是一次通过经典api实现,一次类型化。
在测试这两种逻辑时(基本上),我发现使用经典逻辑的版本处理1,000,000个滴答需要不到1.5秒的时间,而类型化的版本需要3.5秒多一点的时间。
显而易见的第一个原因是将监护父进程(也是路由器)移到它自己的PinnedDispatcher中,这样它就可以在自己的线程上运行,而所有其他参与者使用默认的线程池。这大大提高了性能,处理1,000,000个tick大约需要2.1秒。
我的问题是:有人知道剩下的性能(0.6秒)可能会在哪里丢失吗?
1条答案
按热度按时间y0u0uwnf1#
类型化在经典的基础上运行(类型化的
Behavior<T>
被有效地 Package 在一个函数中,该函数将消息转换为T
;一旦被 Package ,则可以将其基本上视为经典的Receive
),因此它引入了一些每个消息的开销。我猜想,通过将路由父节点放在固定的调度程序上的改进,类型化实现通过父节点发送每个tick,因此请注意,您将导致两次开销。根据相对于tick数的
Instrument
的数量,通过对父节点使用类似SpawnProtocol
的代码,可以使类型化代码更像经典代码。因此ActorSystem
外部的代码将在高层:Map<Instrument, ActorRef<Tick>>
(或其他)ActorRef
,则向该ActorRef
发送报价单ActorRef<Tick>
;然后将得到的ActorRef
保存在本地Map
中,并将分笔成交点发送到该ActorRef
这更像经典中的情形:消息的数量(忽略内部系统消息)现在是1百万加上2倍的X1 M13 N1 X的数量,而不是2百万。