在JVM中使用Scala/Akka进行高频交易

21

假设有一款使用Java编写的高频交易系统,需要(非常)低延迟,由于不可变性而产生了许多短暂的小对象(是否考虑使用Scala?),每秒连接数达到数千个,在事件驱动的架构中传递了大量的消息(使用akka和amqp?)。

对于专业人士来说,理论上最好的JVM 7调优方法是什么?哪种类型的代码可以让它更快?Scala和Akka是否能够胜任这种系统?

注意:已经有了一些类似的问题,比如这个,但我还没有找到一个涵盖Scala的问题(因为它在JVM中具有自己的特点)。


3
问题是JVM是否是正确的选择?也许C++会提供更可预测的延迟。 - usr
我听说过Scala被用来生成实际的HFT C代码,但我无法回忆起任何细节。由于链接问题中提到的1-3秒对于HFT来说太长了,我认为在JVM上编写HFT软件不是一个好主意。 - Rafał Rawicki
1
这个问题太笼统了。 - moodywoody
我就是不明白为什么人们要在一个垃圾回收语言中尝试低延迟。为什么不普遍使用C语言呢? - user82238
从我的经验来看,我可以说Scala不适合高性能低延迟的场景,因为它底层有很多魔法操作。Akka也不是最快的东西,比Disruptor慢得多。 - Stas
2
你的高频交易系统可能每秒钟有成千上万条信息进出,但你肯定不会有成千上万个连接。 - Ted Graham
4个回答

38

在Java中可以实现非常好的性能。但是,为了提供可信的答案,问题需要更加具体。以下是可能导致延迟的主要因素,但不限于此:

  1. 你产生的垃圾量以及GC收集和推广它的工作。根据我的经验,不可变设计不适合低延迟。GC调优需要成为一个重点。

  2. 预热JVM以便加载类并让JIT有时间进行编译。

  3. 将算法设计为O(1)或至少O(log2 n),并具有断言其性能的性能测试。

  4. 您的设计需要无锁并遵循“单写原则”。

  5. 需要投入大量精力来理解整个堆栈,并在使用中表现出机械同情。

  6. 将算法和数据结构设计为缓存友好型。如今,缓存未命中是最大的成本。这与进程亲和力密切相关,如果设置不正确,可能会导致显着的缓存污染。这将涉及对操作系统的同情,甚至在某些情况下需要一些JNI代码。

  7. 确保您拥有足够的核心,以便任何需要运行的线程都有可用的核心而无需等待。

我最近写了一篇关于这种练习的案例研究的博客。


26
在我的笔记本电脑上,Akka 2.3.7演员之间ping消息的平均延迟为~300ns,远低于JVM GC暂停所期望的延迟。
Intel Core i7-2640M上的Akka和其他演员的代码(包括JVM选项)和测试结果在此处
P.S. 您可以在Dmitry Vyukov的网站和Martin Thompson的博客中找到许多低延迟计算的原则和技巧。

2
请注意,该改进现已得到解决,并成为JDK 7新版本的一部分。 - Sanjay T. Sharma
请注意:平均延迟实际上只是吞吐量的倒数。您想要根据消息本应发送的时间而不是实际发送时间来了解延迟的分布情况。即,您需要避免坐标省略。http://www.azulsystems.com/sites/default/files/images/HowNotToMeasureLatency_LLSummit_NYC_12Nov2013.pdf - Peter Lawrey
我在Typesafe博客中删除了吞吐量测试的参考,以避免误解1/延迟=吞吐量。 - Andriy Plokhotnyuk

11
您可能会发现,使用环形缓冲区进行消息传递将超越Akka所能实现的范围。人们在JVM上用于金融应用程序的主要环形缓冲区实现是一种称为Disruptor的实现,它经过精心调整以提高效率(大小为2的幂),适用于JVM(无GC、无锁)和现代CPU(不会出现缓存行的虚假共享)。
以下是一个来自Scala的介绍性演示,其中包含有关原始LMAX内容的链接,请参考最后一页: http://scala-phase.org/talks/jamie-allen-sdisruptor/index.html#1

0

有很多用Java编写的HFT系统,但我从未听说过有一个用Scala编写的。为什么?

  1. JVM语言中,垃圾收集器是常见的,但对于HFT来说并不是一个好选择。但Java是一种垃圾收集语言。那么诀窍是什么呢?诀窍在于人们在编写HFT时像使用C一样使用Java,我的意思是:他们通过更高的内存分配控制来交换Java提供的一些好处。这个技巧基本上是通过将JCF(Java Collections Framework)替换为预先分配在内存中的平凡数组或其他创造性解决方案。

  2. Scala是一种功能强大的编程语言,它促进了大量使用函数式编程技术,其中大部分都由集合框架支持。问题在于:如果你要摆脱集合框架(通过第1点),那么你基本上就没有使用Scala内置的FP基本构建块。如果你一开始就不这样做,那么使用Scala有什么意义呢?

  3. Akka似乎不是一个好的选择,因为...嗯...它是用Scala编写的。所以,通过第(1)和(2)项,我们也可以排除Akka。

重点是:自2012年提出这个问题以来,技术已经发展了。我的答案现在距离未来已经有10年了。我们有比2012年时唯一可能的C或C++更有趣的选择。
好吧...也许不是选择(复数)...而是一个选择:Rust。
Rust不是垃圾回收语言,它是一种安全的编程语言,它具有生产力,提供了丰富的异步库,并且速度相当快。
Rust唯一的“问题”是,负责指导大型银行和金融机构技术的人们通常对创新持反感态度,更喜欢他们长期职业生涯以来已经熟悉的东西。因此,简而言之,需要一些时间才能看到用Rust编写的HFT系统。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接