使用 Scala/Akka 在 JVM 中进行高频交易
Posted
技术标签:
【中文标题】使用 Scala/Akka 在 JVM 中进行高频交易【英文标题】:High Frequency Trading in the JVM with Scala/Akka 【发布时间】:2012-04-14 15:24:23 【问题描述】:让我们想象一个 Java 中的假设 HFT 系统,需要(非常)低延迟,由于不变性(Scala?),有许多短命的小对象,每秒数千个连接,以及大量的消息传递围绕在事件驱动的架构中(akka 和 amqp?)。
对于那里的专家来说,(假设)什么是 JVM 7 的最佳调优?什么类型的代码会让它开心? Scala 和 Akka 会为这种系统做好准备吗?
注意: 有一些类似的问题,例如 one,但我还没有找到一个涵盖 Scala(它在 JVM 中有自己的特殊足迹)的问题。
【问题讨论】:
还有一个问题,如果JVM是正确的选择?也许 C++ 会提供更可预测的延迟。 我听说过 Scala 用于生成 C 代码执行实际的 HFT,但我不记得任何细节。由于链接问题中提到的 1-3 秒对于 HFT 来说太多了,我认为在 JVM 上编写 HFT 软件不是一个好主意。 问题很笼统。 我只是不明白为什么人们在垃圾收集语言中尝试低延迟。为什么 C 不是更常用的? 您可能在一秒钟内有数千条消息进出,但在 HFT 系统中您肯定不会有数千条连接。 【参考方案1】:在 Java 中实现非常好的性能是可能的。但是,问题需要更具体才能提供可信的答案。您的主要延迟来源将来自以下非详尽列表:
您创建了多少垃圾以及 GC 的工作来收集和 推广它。根据我的经验,不可变的设计不适合 低延迟。 GC 调优需要成为重点。
预热 JVM,以便加载类并且 JIT 有时间 做它的工作。
将您的算法设计为 O(1) 或至少 O(log2 n),并且具有 断言这一点的性能测试。
您的设计需要无锁并遵循“Single Writer Principle”。
需要付出巨大的努力来理解整体 堆栈并在其使用中表现出机械同情。
将您的算法和数据结构设计为对缓存友好。 如今,缓存未命中是最大的成本。这是密切 与进程关联相关,如果设置不正确,可能会导致 和严重的缓存污染。这会涉及到对操作系统的同情,在某些情况下甚至会涉及到一些 JNI 代码。
确保您有足够的内核,以便任何需要 run 有一个可用的核心,无需等待。
我最近在博客上写了一篇关于此类练习的 case study。
【讨论】:
【参考方案2】:在我的笔记本电脑上,Akka 2.3.7 参与者之间 ping 消息的平均延迟为 ~300ns,它远低于由于 JVM 上的 GC 暂停而导致的预期延迟。
英特尔酷睿 i7-2640M here 上 Akka 和其他参与者的代码(包括 JVM 选项)和测试结果。
附:您可以在 Dmitry Vyukov 的 site 和 Martin Thompson 的 blog 中找到许多低延迟计算的原则和技巧。
【讨论】:
仅供参考,改进现已解决,是 JDK 7 较新版本的一部分。 注意:平均延迟实际上只是吞吐量的倒数。您想根据应该发送消息的时间而不是发送消息的时间来了解延迟的分布。即你想避免坐标遗漏。 azulsystems.com/sites/default/files/images/… 我在 typesafe 博客上删除了对吞吐量测试的引用,以避免误解 1/latency = 吞吐量。【参考方案3】:您可能会发现使用环形缓冲区进行消息传递将超过使用 Akka 所能做的。人们在 JVM 上用于金融应用程序的主要环形缓冲区实现是一种称为 Disruptor,它针对效率(两倍大小的幂)、JVM(无 GC、无锁)和现代 CPU(无虚假共享缓存行)。
这是从 Scala 的角度进行的介绍演示 http://scala-phase.org/talks/jamie-allen-sdisruptor/index.html#1,最后一张幻灯片上有指向原始 LMAX 内容的链接。
【讨论】:
非常有趣!谢谢分享。以上是关于使用 Scala/Akka 在 JVM 中进行高频交易的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Shiro 在 Scala + Akka + Spray 环境中工作
在 Scala Akka 期货中,map 和 flatMap 有啥区别?
如何在scala akka(spray)中为rest服务编写测试用例