概述
高频交易的最佳解决方案是什么?对于这个问题,观点一直比较冲突,部分原因是人们不知道什么叫高频交易并且与人们想象的总是存在差异,其次是速度问题,用哪种语言开发速度会快点,本文作者拿当今非常流行的C 和Java这两种语言进行比较。
如果你是一个典型的Java和C 程序员,并且用这两种语言编写过典型的面向对象程序。在相同的时间下面编写高频解决方案,Java程序员有可能会提前完成程序并且有时间调整应用程序。在这种情形下,恕我直言,Java应用程序的速度会快些。
以我的经验,Java在执行上会好于C ,因为Java进行微基准测试,其实它没有做什么事情。但是如果没有时间限制,对Java和C 程序进行调优,那么C 程序会比Java快些。然而,考虑到资源的有限性和环境的不断变化,一个充满活力的语言可能会现实应用中超常发挥。
在股票交易这种高频市场,即使延迟10微秒都需要认真对待。 Java甚至标准的OOP C ,用在商业硬件上都不是最佳选择,你需要借助C或者精简版的C 和一些专业的硬件工具,例如FPGAs、GPUs。
然而,在外汇(FX:Foreign Exchange)市场,高频意味着延迟时间不低于100微秒。在这个的环境下,C 或者Java(低GC)都是个不错的选择。个人认为,在不断变化的交易场所,Java拥有更多的灵活性。
当人们讨论高频率时,尤其是在做银行系统的时候,他们想把时间缩短1毫秒或者单单几毫秒。在这样的情况下,我会说,灵活/多态的Java、Scala或者C#等语言在编程时间上将会更加充裕,可维护性或可靠性优势将会超过C/C 或FPGA。
Java所面临的问题
问题不在于这样的语言上,而是缺乏缓存控制和上下文交互。如果你复制一块在本地已经操作过的内存,但是在运行之间使用不同的延迟,副本将会变慢。
原因是部分缓存被交换出去,而复制本身也需要一些时间。这和访问内存的任何操作是一样的。例如,访问计划对象将会更慢。
- private void doTest(Pauser delay) throws InterruptedException {
- int[] times = new int[1000 * 1000];
- byte[] bytes = new byte[32* 1024];
- byte[] bytes2 = new byte[32 * 1024];
- long end = System.nanoTime() (long) 5e9;
- int i;
- for (i = 0; i < times.length; i ) {
- long start = System.nanoTime();
- System.arraycopy(bytes, 0, bytes2, 0, bytes.length);
- long time = System.nanoTime() - start;
- times[i] = (int) time;
- delay.pause();
- if (start > end) break;
- }
- Arrays.sort(times, 0, i);
- System.out.printf(delay ": Copy memory latency 1/50/99%%tile %.1f/%.1f/%.1f us%n",
- times[i / 100] / 1e3,
- times[i / 2] / 1e3,
- times[i - i / 100 - 1] / 1e3
- );
- }
这个测试其实是在多次执行同一件任务,在执行之间使用不同的延时。其中大部分时间都花在本地方法上,在测试期间没有创建或抛弃对象。
- YIELD: Copy memory latency 1/50/99%tile 1.6/1.6/2.3 us
- NO_WAIT: Copy memory latency 1/50/99%tile 1.6/1.6/1.6 us
- BUSY_WAIT_10: Copy memory latency 1/50/99%tile 2.8/3.5/4.4 us
- BUSY_WAIT_3: Copy memory latency 1/50/99%tile 2.7/3.0/4.0 us
- BUSY_WAIT_1: Copy memory latency 1/50/99%tile 1.6/1.6/2.5 us
- SLEEP_10: Copy memory latency 1/50/99%tile 2.2/3.4/5.1 us
- SLEEP_3: Copy memory latency 1/50/99%tile 2.2/3.4/4.4 us
- SLEEP_1: Copy memory latency 1/50/99%tile 1.8/3.4/4.2 us
-XX Java 7的UseLargePages
- YIELD: Copy memory latency 1/50/99%tile 1.6/1.6/2.7 us
- NO_WAIT: Copy memory latency 1/50/99%tile 1.6/1.6/1.8 us
- BUSY_WAIT_10: Copy memory latency 1/50/99%tile 2.7/3.6/6.6 us
- BUSY_WAIT_3: Copy memory latency 1/50/99%tile 2.7/2.8/5.0 us
- BUSY_WAIT_1: Copy memory latency 1/50/99%tile 1.7/1.8/2.6 us
- SLEEP_10: Copy memory latency 1/50/99%tile 2.4/4.0/5.2 us
- SLEEP_3: Copy memory latency 1/50/99%tile 2.3/3.9/4.8 us
- SLEEP_1: Copy memory latency 1/50/99%tile 2.1/3.3/3.7 us
上面是最好的三种运行。
进行内存拷贝的典型时间(中间值)是1.6到4.6微秒,依据是否有线程在繁忙等待或休眠状态上使用了1到10毫秒。这大概是3倍的比率,并且与Java无关,这是因为它没有真正的控制权。即使在最好的情况下时间差大概也是2倍。
代码
总结
在极端高频情况下,核心引擎一般会用C、汇编和定制的硬件实现比使用C 或JAVA面向对象实现的方式多。由于延迟需求不再那么紧张(指当基础平台使用C/C 搭建架构之后,应用平台层面,时间响应已不是很重要,反而开发响应更重要)。因此Java和其他动态语言可能会变得更富有成效,在这种情形下,选择Java或许可以帮你轻松应对不断变化的市场/需求。
来自:DZone
联系客服