C++ 与虚拟机语言在高频金融中的表现

Posted

技术标签:

【中文标题】C++ 与虚拟机语言在高频金融中的表现【英文标题】:Performance of C++ vs Virtual Machine languages in high frequency finance 【发布时间】:2011-03-11 15:27:55 【问题描述】:

我认为 C/C++ 与 C#/Java 性能问题已经很好地解决了,这意味着我已经阅读了足够多的证据表明 VM 语言不一定比“接近硅”的语言慢。主要是因为 JIT 编译器可以做静态编译语言做不到的优化。

但是,我最近收到了一个人的简历,他声称基于 Java 的高频交易总是被 C++ 击败,并且他一直处于这种情况。

快速浏览求职网站确实表明 HFT 申请者需要 C++ 知识,查看Wilmott 论坛显示所有从业者都在谈论 C++。

出现这种情况有什么特别的原因吗?我原以为现代金融业务有点复杂,具有类型安全、托管内存和丰富库的 VM 语言将是首选。这样生产率会更高。另外,JIT 编译器越来越好。他们可以在程序运行时进行优化,因此您会认为他们使用该运行时信息来击败非托管程序的性能。

也许这些人正在用 C++ 编写关键位并从托管环境(P/Invoke 等)调用它们?这可能吗?

最后,有没有人对这个中心问题有经验,这就是为什么在这个领域中,非托管代码无疑比托管代码更受欢迎?

据我所知,高频交易人员需要尽快对传入的市场数据做出反应,但这不一定是hard realtime 的要求。如果你反应慢,你的情况会更糟,这是肯定的,但你不需要保证每次响应都有一定的速度,你只需要一个快速的平均值。

编辑

是的,到目前为止,有几个很好的答案,但很笼统(广为人知)。让我指定 HFT 人员将运行什么样的程序。

主要标准是响应能力。当订单进入市场时,您希望成为第一个能够对其做出反应的人。如果你迟到了,其他人可能会抢在你之前,但每个公司的策略略有不同,所以如果一个迭代有点慢,你可能会没事。

该程序整天运行,几乎没有用户干预。无论处理每条新市场数据的功能如何,每秒都会运行数十次(甚至数百次)。

这些公司通常对硬件的价格没有限制。

【问题讨论】:

并且说“如果一次迭代有点慢可能没关系”似乎是一厢情愿,tbh。听起来像是“我真的很想用 C#,你确定不行吗?”一次迭代缓慢意味着一次迭代中您的利润较低。这可能是“好的”,但如果可能的话,你想避免它。几天前与我交谈的一位 HFT 开发人员非常清楚地强调“如果一个操作需要 1 毫秒,那就太慢了”。他们确实使用了 C# 和 C++ 的混合体,但祝你好运,向那些认为 1ms 延迟不可接受的人出售一种用于时间关键组件的 GC 语言。 你不认为 1 次慢迭代是可以的,因为它会运行数百万次吗?当然,如果你总是比每个人都慢,那是行不通的。但是,如果您每天要获取数百万次股票,那么平均速度更快才是最重要的?我想我想知道对 C++ 的需求是否是历史性的(已建立的代码库),或者它是否真的是一种性能优势。 也许 GC 造成的延迟是您在使用竞争对手的平台编程非 GC 语言时输给其他人的决定因素。我认为这对活跃的交易者会产生巨大的影响。 @Carlos:但你假设这只是一个“有点慢”的迭代。假设您每秒获得 20,000 个价格(这就是我与之交谈的开发人员说他们的系统处理的)。这意味着如果 GC 需要 50 毫秒来运行一个集合,您不会错过一个单一的价格。你错过了很多。而且它不会只发生一次。随着垃圾的堆积,它会定期发生。坦率地说,你不会假设“如果我能保持 80% 的时间就可以了”就进入 HFT。你这样做是因为你认为你可以超越其他人。每次迭代。 我认为要记住的重要一点是,当 JIT 运行的平台在编译时未知时,它非常擅长优化。这(可能)不适用于 HFT。 Java 可以利用特定硬件,但如果您愿意牺牲二进制文件的可移植性,C++ 也可以。 【参考方案1】:

首先,1 ms 在 HFT 中是永恒的。如果您认为不是,那么最好多阅读有关该域的内容。 (这就像距离交易所 100 英里。)吞吐量和延迟是紧密交织在一起的,任何基本排队理论教科书中的公式都会告诉你。相同的公式将显示抖动值(如果网络结构正确并且您没有配置足够多的内核,则通常由 CPU 队列延迟的标准偏差决定)。

高频交易套利的一个问题是,一旦您决定捕捉价差,就有两条(或更多条)腿来实现利润。如果你没有打完所有的腿,你可能会得到一个你真的不想要的头寸(以及随后的损失)——毕竟你是在套利而不是投资。

除非您的策略是预测(非常近期!!!)未来(不管您信不信,这已经非常成功),否则您不想要头寸。如果您距离交易所只有 1 毫秒,那么您的大部分订单将不会被执行,而您想要的将会被取走。最有可能已经执行了一条腿的人最终会失败,或者至少不会盈利。

为了争论,无论您的策略是什么,让我们说它最终的赢/输率是 55%/45%。即使是赢/输比率的微小变化也会对盈利能力产生很大的影响。

re:“运行数十个(甚至数百个)”似乎偏离了 数量级 即使每秒查看 20000 个滴答声似乎也很低,尽管这可能是仪器集一整天的平均值他正在看。

在任何给定秒内看到的速率都存在很大差异。我举个例子。在我的一些测试中,我在一天的中间查看了 7 支场外交易股票(CSCO、GOOG、MSFT、EBAY、AAPL、INTC、DELL),该流的每秒速率可以从 0 mps(非常非常罕见)到每个峰值秒几乎有近 2000 个报价和交易。 (看看为什么我认为上面的20000很低。)

我为这个领域构建了基础设施和测量软件,我们谈论的数字是每秒 100000 和数百万。我有 C++ 生产者/消费者基础设施库,可以在生产者和消费者(32 位,2.4 GHz 内核)之间推送几乎 5000000(500 万)条消息/秒。这些是 64 字节的消息,在生产者端具有 new、construct、enqueue、同步,在消费者端具有 synchronize,dequeue,touch each byte,run virtual destructor,free .现在诚然,这是一个没有 Socket IO 的简单基准测试(并且套接字 IO 可能很难看),就像在端点管道阶段的端点一样。它是所有自定义同步类,仅在空时同步,自定义分配器,自定义无锁队列和列表,偶尔的 STL(带有自定义分配器)但更常见的是自定义侵入式集合(其中我有一个重要的库)。我不止一次地为这个领域的供应商提供了四倍(甚至更多)的吞吐量,而没有增加套接字端点的批处理。

我有 OrderBook 和 OrderBook::Universe 类,当平均超过 22000 个仪器时,新、插入、查找、部分填充、查找、第二次填充、擦除、删除序列所需的时间不到 2us。该基准在插入第一次填充和最后一次填充之间连续迭代所有 22000 个仪器,因此不涉及廉价的缓存技巧。对同一本书的操作被 22000 本书的访问分开。这些都不是真实数据的缓存特性。真实数据在时间上更加本地化,​​连续交易经常出现在同一本书中。

所有这些工作都涉及仔细考虑所用集合的任何算法成本中的常量和缓存特性。 (有时似乎 KO(n) KO(n*log n) 等中的 K 被忽略了有点过于圆滑)

我从事 Marketdata 基础架构方面的工作。甚至想到使用 java 或托管环境来完成这项工作都是不可思议的。当您可以使用 C++ 获得这种性能时,我认为在托管环境中很难获得百万以上/mps 的性能)我无法想象有任何重要的投资银行或对冲基金(他们的薪水为 250,000 美元)一流的 C++ 程序员什么都不是)不会使用 C++。

真的有人从托管环境中获得 2000000+/mps 的性能吗?我在这个领域认识一些人,但从来没有人向我吹嘘过。而且我认为托管环境中的 2 毫米会有一些吹牛的权利。

我知道一个主要参与者的 FIX 顺序解码器每秒进行 12000000 场解码。 (3Ghz CPU)它是 C++,编写它的人几乎挑战任何人想出一些东西 在甚至只有一半速度的托管环境中。

从技术上讲,这是一个有趣的领域,有很多有趣的性能挑战。考虑当基础证券发生变化时的期权市场——可能会出现 6 个具有 3 或 4 个不同到期日的未偿价格点。现在每笔交易可能有 10-20 个报价。这些报价可以触发期权的价格变化。 因此,对于每笔交易,期权报价可能会有 100 或 200 次变化。这只是大量的数据——不是大型强子对撞机碰撞检测器般的数据量,但仍然有点挑战。这与处理击键有点不同。

甚至关于 FPGA 的争论仍在继续。许多人认为运行在 3GHZ 商品硬件上的编码良好的解析器可以击败 500MHz FPGA。但即使稍微慢一点(不是说它们慢),基于 FPGA 的系统也往往具有更紧密的延迟分布。 (阅读“倾向于”——这不是一个笼统的说法)当然,如果你有一个很棒的 C++ 解析器,你可以通过 Cfront 推送,然后通过 FPGA 图像生成器推送它……但那是另一场辩论……

【讨论】:

哇,这太迷人了!也很详细。几个问题:如果您在几分之一毫秒内做出响应,这是否会严重限制您可以实施的策略类型?我无法想象任何非常简单的策略都有足够的时间来计算。这是否意味着所有这些高频交易策略都只是套利? 不,这意味着策略周围的一切都尽可能好。战略就是战略。 FPGA 的优势在于您可以拥有 wide 管道(想要一个 2Kbit 宽的管道?你明白了!)和用于超紧时间限制的自定义并发逻辑(当然,FPGA 的最大时钟速度低于 CPU 的最大速度)。查看最新的 Xilinx FPGA,他们估计其机器的 IO 吞吐量高达 TB。 @pgast:您是否发现托管语言在此应用​​程序上下文中的正确性方面提供的好处微不足道? 我不是这个领域的专家,但听起来 LMAX 可能与讨论有关【参考方案2】:

其中很多都归结为事实与理论之间的简单区别。人们已经使用theories 来解释为什么 Java 应该(或至少可能)比 C++ 更快。大多数论点与 Java 或 C++本身几乎没有关系,而是与动态编译与静态编译有关,Java 和 C++ 实际上只是两者的示例(当然,有可能静态编译Java,或动态编译C++)。这些人中的大多数都有基准来“证明”他们的主张。当这些基准在任何细节上都是examined 时,很快就会发现,在相当多的情况下,他们采取了相当极端的措施来获得他们想要的结果(例如,在编译时有相当多的启用优化Java,但特别是在编译 C++ 时禁用优化)。

将此与Computer Language Benchmarks Game 进行比较,几乎任何人都可以提交条目,因此所有代码都倾向于优化到合理的程度(在少数情况下,甚至是不合理的程度)。很明显,相当多的人将其视为本质上的竞争,每种语言的拥护者都尽最大努力“证明”他们首选的语言是最好的。由于任何人都可以提交任何问题的实现,因此特别糟糕的提交对整体结果几乎没有影响。在这种情况下,C 和 C++ 成为明显的领导者。

更糟糕的是,这些结果可能比完全准确的结果更好地显示 Java。特别是,使用 C 或 C++ 并且真正关心性能的人可以(并且经常会)使用英特尔的编译器而不是 g++。与 g++ 相比,这通常会在速度上至少提高 20%。

编辑(回应 jalf 提出的几点,但确实太长而无法合理地放入 cmets):

    指针是优化器编写者的噩梦。这确实有点夸大其词(相当)。指针会导致混叠的可能性,这会在某些情况下阻止某些优化。也就是说,内联在很多时候可以防止不良影响(即,编译器可以检测是否存在别名,而不是总是在假设可能存在的情况下生成代码)。即使代码确实必须假设别名,缓存也可以最大限度地减少这样做对性能的影响(即,L1 缓存中的数据仅比寄存器中的数据慢分钟)。防止混叠有助于提高 C++ 的性能,但并没有你想象的那么好。

    垃圾收集器的分配速度要快得多。确实,许多 C++ 实现中的 default 分配器比大多数(当前)垃圾回收分配器提供的要慢。 C++ 中的分配往往在堆栈上,这也很快,而在 GC 语言中,几乎所有的分配通常都在堆上,这可以平衡(至少在一定程度上)。更糟糕的是,在托管语言中,您通常为每个对象单独分配空间,而在 C++ 中,您通常为范围内的所有对象一起分配空间。

确实,C++ 直接支持全局和逐个类地替换分配器,因此当/如果分配速度确实是一个问题时,通常很容易解决。

最终,jalf 是对的:这两点无疑确实支持“托管”实现。不过,应该保持这种改进的程度:它们不足以让动态编译的实现在许多代码上运行得更快——甚至从一开始就设计的基准测试都尽可能地支持它们。

Edit2:我看到 Jon Harrop 试图插入他的两(十亿分之一)美分的价值。对于那些不认识他的人,乔恩一直是notorioustrollandspammerforyears,并且似乎正在寻找新的土地来播种杂草。我会尝试详细回复他的评论,但是(对他来说是典型的)它完全由不合格、不受支持的概括组成,其中包含的实际内容太少,以至于不可能做出有意义的回复。所能做的就是向旁观者发出公平的警告,让他们知道他以不诚实、自私自利和最好被忽视而闻名。

【讨论】:

+1 用于 Language Shootout 参考,我过去也曾指出过一个很棒的资源,另外还有一个 +1(如果可以的话)用于“理论对战”事实的背景——太真实了!也就是说,这里并不完全合适,因为 C# 人员希望仅在 Windows 上运行,我们没有对其进行基准比较。在相关的说明中,我还听说 gcc/g++ 4.5 正在接近 icc,因此“20% 的改进”可能不再成立。值得另一组基准测试。 @Dirk:MSVC++?您可以免费获得 Express。他们还在 Ultimate 版本中提供了可爱的 Profile Guided Optimization 功能和强大的分析器。 @DeadMG:太好了,所以请建立基准站点。我是一个快乐的 Linux 用户,因此可以使用现有的 Language Shootout。原始海报不是。 @Dirk Eddelbuettel:我的工作不是建立一个基准站点来弥补原始基准站点的缺陷。 @DeadMG:你知道 Shootout 站点似乎是基于 Ubuntu Linux 服务器的时间吗?因此,您的 MSVC++ 建议没有用处。【参考方案3】:

理论上,JIT 编译器可以执行很多优化,是的,但是您愿意等待多长时间?一个 C++ 应用程序可能需要几个小时来编译,因为它发生在离线状态,并且用户不会坐在那里敲击手指等待。

JIT 编译器必须在几毫秒内完成。 那么您认为哪些可以摆脱最复杂的优化?

垃圾收集器也是一个因素。不是因为它本身比手动内存管理慢(我相信它的摊销成本相当不错,绝对可以与手动内存处理相媲美),而是它的可预测性较差。它可以在几乎任何时候引入停顿,这在需要极快响应的系统中可能是不可接受的。

当然,这些语言本身也适用于不同的优化。 C++ 允许您编写非常紧凑的代码,几乎没有内存开销,并且许多高级操作基本上是免费的(例如,类构造)。

另一方面,在 C# 中,您会浪费大量内存。并且简单地实例化一个类会带来很大的开销,因为基类 Object 必须被初始化,即使你的实际类是空的。

C++ 允许编译器积极地剥离未使用的代码。在 C# 中,大部分都必须存在,以便可以通过反射找到。

另一方面,C# 没有指针,这是优化编译器的噩梦。托管语言中的内存分配比 C++ 便宜得多。

无论哪种方式都有优势,因此期望您能得到一个简单的“一个或另一个”答案是幼稚的。根据确切的源代码、编译器、操作系统、运行它的硬件,其中一个可能更快。根据您的需求,原始性能可能不是第一目标。也许您更感兴趣的是响应能力,避免不可预知的停顿。

一般而言,您的典型 C++ 代码将执行类似等效的 C# 代码。有时更快,有时更慢,但无论哪种方式都可能没有显着差异。

但同样,这取决于具体情况。这取决于您愿意花多少时间进行优化。如果你愿意花尽可能多的时间,C++ 代码通常可以实现比 C# 更好的性能。只是需要做很多工作。

当然,另一个原因是大多数使用 C++ 的公司已经拥有庞大的 C++ 代码库,他们并不特别想放弃这些代码库。他们需要这样才能继续工作,即使他们逐渐将(一些)新组件迁移到托管语言。

【讨论】:

jaif - JIT 编译器可以缓存他们的结果(即 .Net),这样你就只会在第一次执行时受到打击。同样在 .Net 的情况下,它们可以基于单个源代码库在每台机器上进行优化——这是静态编译器无法做到的。如果 Java 没有做类似的事情,我会感到惊讶 @Peter:您可能不会认为这是一个问题,但编写 JIT 编译器的人却认为。因此,当您第一次运行程序时,JIT 编译器不会花费 2 个小时进行优化,这使您的观点有点学术。是的,当然,理论上 JIT 编译器可以在阳光下执行所有优化。但实际上他们不会,因为 99.999% 的客户希望在首次启动程序时等待 2 小时。 @Peter:我没有看到相关性。你的最后两个 cmets 与这个讨论有什么关系?是的,JIT 编译器可以在安装时运行,也可以在启动时运行,或者在运行时运行。这并没有改变人们没有耐心等待 6 个小时才能完成的事实。即使有这种耐心,JIT 设计者也假设人们没有这种耐心,所以他们的编译器没有 执行静态编译器可能执行的相同优化。没有理论上的理由说明它不能完成。但事实并非如此。 @Peter:不,JIT 版本不会需要 23 小时才能启动,它只会跳过优化以更快地启动应用程序。这就是 JIT 编译器所做的,它们不会在启动上花费数小时,它们启动程序的速度相当快,即使这意味着它们没有时间进行所有可能的优化。 现在,我想我已经浪费了我的时间了。您可能想阅读我回答的 question 以及我的实际回答。然后坐下来问问自己是否有任何与这些实际相关的问题。我看不出 OCaml 或 C++ 可怕的编译时间的相关性,我不明白为什么通过为您提供静态和 JIT 编译器执行的每个该死的优化的完整列表来改进我的答案。【参考方案4】:

这些公司通常对硬件的价格没有限制。

如果他们也不关心软件有多贵,那么我认为 C++ 当然可以更快:例如,程序员可能使用自定义分配或预分配的内存;和/或它们可以在内核中运行代码(避免环形转换),或在实时操作系统上运行,和/或使其与网络协议栈紧密耦合。

【讨论】:

啊哈,这些听起来像是一些真正的优势。 实际上,我想说帮助内核/用户空间转换的趋势是更多地进入用户空间而不是内核。 @pgast 我不明白这是为什么?当然在用户空间中你必须先访问内核,所以你有一个额外的“层”可以通过?将更多内容推入内核,转换次数肯定会更少吗?【参考方案5】:

除了性能之外,还有其他原因使用 C++。有一个巨大的现有 C 和 C++ 代码库。用其他语言重写所有这些是不切实际的。为了使 P/Invoke 之类的东西正常工作,必须将目标代码设计为从其他地方调用。如果不出意外,您将不得不为暴露完全 C API 的事物编写某种包装器,因为您无法 P/Invoke 到 C++ 类。

最后,P/Invoke 是一项非常昂贵的操作。

JIT 编译器越来越好。他们可以在程序运行时进行优化

是的,他们可以做到这一点。但是您忘记了任何 C++ 编译器都能够进行相同的优化。当然,编译时间会更糟,但这种优化必须在运行时完成的事实本身就是开销。在某些情况下,托管语言可以在某些任务上击败 C++,但这通常是因为它们的内存模型,而不是运行时优化的结果。严格来说,你当然可以在 C++ 中拥有这样的内存模型,EDIT:例如 C# 对字符串的处理,/EDIT,但很少有 C++ 程序员像 JIT 人员那样花费大量时间优化他们的代码。

托管语言存在一些性能问题,即磁盘 I/O。这是一次性成本,但取决于应用程序,它可能很重要。即使使用最好的优化器,程序启动时仍需要从磁盘加载 30MB 以上的 JIT 编译器;而 C++ 二进制文件很少会接近这个大小。

【讨论】:

“但是您忘记了任何 C++ 编译器都能够进行相同的优化”。 C++ 编译器不执行在线配置文件引导优化之类的操作。 @Jon:大多数 JIT 也不行。您可以离线进行配置文件引导优化。【参考方案6】:

简单的事实是 C++ 是为速度而设计的。 C#/Java 不是。

与 std::sort 或 std::for_each 的零开销相比,这些语言特有的无数继承层次结构(例如 IEnumerable)是通用的。 C++ 的原始执行速度不一定更快,但程序员可以设计快速或零开销的系统。即使是缓冲区溢出之类的事情-您也无法关闭它们的检测。在 C++ 中,您拥有控制权。从根本上说,C++ 是一种快速的语言——你不需要为你不使用的东西付费。相比之下,在 C# 中,如果使用 stackalloc,则不能不进行缓冲区溢出检查。您不能在堆栈上或连续分配类。

还有整个编译时问题,C++ 应用程序可能需要更长的时间来编译和开发。

【讨论】:

C# 被设计为不像 Java 那样慢。 C# 中结构的全部意义在于您可以在堆栈上分配它们或拥有它们的连续数组。您还可以获取指向对象的指针,并在不进行边界检查的情况下随意使用它们。 @Gabe:指针没有边界检查。数组可以。此外,我当然希望我不想要一种既可以连续排列又可以引用而不干扰我的语言的正常操作的类型。而且,仍然有整个荒谬的继承量,事情。当您编写 C++ 时,您的类只执行您想要的操作,并且以通用方式与其他类或语言库进行交互可以在没有运行时开销的情况下完成。 C# 不能做这两件事。此外,我无法将库类制作成结构来展示这一点。 DeadMG:你似乎非常努力地不同意我的观点,除非我不理解你,否则没有太大的成功。 jalf 是对的:C++ 是为低开销而设计的,而不是为速度而设计的。 Fortran 是为速度而设计的,这就是为什么很难在 C++ 中编写比在 Fortran 中更快的数值算法。 @Gabe:请原谅我假设您正在回答这个问题。【参考方案7】:

这可能有点离题,但我在几周前看了一个视频,你可能会感兴趣:http://ocaml.janestreet.com/?q=node/61

它来自一家决定使用 ocaml 作为其主要交易语言的贸易公司,我认为他们的动机应该对你有所启发(基本上,他们当然重视速度,但也重视强类型和功能风格以加快增量以及更容易理解)。

【讨论】:

事实上,F#(微软对 OCaml 的看法)由于其速度(比 OCaml 更好:flyingfrogblog.blogspot.com/2009/07/…)而经常用于此应用程序 我对 F# 了解不多,但如果我记得我之前链接的视频很好,他们会选择 ocaml 而不是 F#,并且不打算在任何可预见的将来切换。一个原因是 F# 在 .net 上运行,它不是专门为函数式语言设计的(因此并不总是尽可能优化)... 我在开发 HLVM 时问过他们这个问题,他们说符号性能对他们来说和数字一样重要。 F# 通常具有更好的数值性能,但它的符号性能要差得多(通常比 OCaml 慢约 5×),因为 .NET 的 GC 没有为此进行优化。 感谢更新,但是“5×”是多少应该是 ? ;) 哈哈。 ×是 × 的 html【参考方案8】:

我们的大部分代码最终都必须在由 1000 台机器组成的网格上运行。

我认为这种环境改变了论点。例如,如果 c++ 和 c# 执行速度之间的差异为 25%,那么其他因素就会发挥作用。当它在网格上运行时,它的编码方式可能没有区别,因为一旦分布在机器上的整个过程可能不是问题或通过分配或购买更多机器来解决。最重要的问题和成本可能成为“上市时间”,c# 可能证明是赢家和更快的选择。

c++ 和 c# 哪个更快?

C# 六个月......

【讨论】:

你不能真的说 C# 比某个时间段更快。使用 C++ 的优秀开发人员可以像使用 C# 的开发人员一样快速编写代码,当然,除非您雇用蹩脚的 C++ 开发人员和优秀的 C# 开发人员。 我认为这就是他们所谓的笑话来说明一个观点。 20 年来我一直在编写 C++ 和 C# 5 年中最好的部分...... C# 的某些功能使其开发起来更加容易和快捷。可以使用反射从编辑器中检查编译的 c#,因此可以帮助您更多地为您提供编辑时语法检查和更广泛的智能感知。标准类库 (.NET) 比 C++ 的 STL 更广泛和更具凝聚力。如果您花一些时间使用最新的 Visual Studio 和 Resharper 进行开发,您就会明白我的意思。 另外,我认为使用 C# 的更多开发人员会被归类为优秀的,因为它更容易掌握。我认为一直很难找到优秀的 C++ 开发人员,因为它更难掌握。【参考方案9】:

这不仅仅是编程语言的问题,硬件和操作系统都将相关。 使用实时操作系统、实时编程语言和高效 (!) 编程,您将获得最佳的整体性能。

因此,您在选择操作系统时有很多可能性,在选择语言时也有一些可能性。 有 C、Realtime Java、Realtime Fortran 等等。

或者,您可能会在对 FPGA/处理器进行编程以消除操作系统成本方面获得最佳结果。

您必须做的最大选择是,您将忽略多少可能的性能优化,而选择一种易于开发且运行更稳定的语言,因为您可以减少错误,这将导致更高的可用性系统。这不应该被忽视。开发一个运行速度比任何其他应用程序快 5% 的应用程序(由于一些难以发现的小错误而导致每隔几个点崩溃)的应用程序,你就没有成功。

【讨论】:

【参考方案10】:

在 HFT 中,延迟是比吞吐量更大的问题。鉴于数据源中固有的并行性,您总是可以在问题上投入更多的内核,但您无法用更多的硬件来弥补响应时间。无论语言是预先编译的,还是即时编译的,垃圾收集都会破坏您的延迟。存在具有保证垃圾收集延迟的实时 JVM。这是一项相当新的技术,调整起来很痛苦,而且价格昂贵得离谱,但如果你有资源,就可以做到。随着早期采用者为目前正在进行的研发提供资金,它可能会在未来几年变得更加主流。

【讨论】:

“总会有下一个版本非常快。” Java 人已经说了 15 年了 ;-) AFAIK,实时 GC 在吞吐量方面花费了 很多(例如 50%)。【参考方案11】:

C++ 中最有趣的事情之一是它的性能数字不是更好,而是更可靠

它不一定比 Java/C#/... 快,但 它在整个运行过程中都是一致的

与网络一样,有时吞吐量并不像稳定的延迟那么重要

【讨论】:

【参考方案12】:

在这种情况下,除了已经说过的之外,更喜欢 c++(或更低级别)的一个重要原因是,低级有一些适应性优势

如果硬件技术发生变化,您可以随时放入__asm 块并在语言/编译器赶上之前实际使用它

例如,仍然在 Java 中不支持 SIMD。

【讨论】:

“Java 或 .NET 中仍然不支持 SIMD”。【参考方案13】:

虚拟执行引擎(JVM 或 .Net 的 CLR)不允许以省时的方式组织工作,因为流程实例无法在所需的尽可能多的线程上运行。

相比之下,纯 C++ 可以在时间关键的执行路径之外执行并行算法和构建对象。这几乎就是一切——简单而优雅。此外,使用 C++,您只需为使用的内容付费。

【讨论】:

我用 C++ 和 .NET 编写过线程,但我不明白你的意思。你能解释一下你可以用 C++ 线程做什么,而不是用例如.NET 线程?【参考方案14】:

这里的问题是 C++ 比 Java 快

我们都知道。但我们也知道,如果我们像我刚才所做的那样明确地陈述,我们就不能假装就这个无可争议的话题进行有意义的辩论。对于您的应用程序,C++ 比Java 快多少?这有一个值得商榷的话题,但是,唉,除非你用两种语言实现你的应用程序,否则它总是假设的,在这一点上它没有争论的余地。

让我们回到您的第一次设计会议:您的项目的硬性要求是高性能。房间里的每个人都会想到“C++”和一些其他编译语言。房间里建议 Java 或 C# 的人将不得不用证据(即原型)来证明它的合理性,而不是假设,不是供应商的声明,不是程序员八卦网站上的陈述,当然也不是“你好世界”的基准。

就目前而言,您必须根据自己的了解继续前进,而不是假设可能的情况。

【讨论】:

【参考方案15】:

Nikie 写道:“你能解释一下你可以用 C++ 线程做什么,而不是用 e.g. .NET 线程?”

.Net 线程几乎可以执行 C++ 线程可以执行的所有操作,除了:

    高效执行 COM 封装的二进制代码。例如,可能必须对应用程序开发人员保密的敏感算法。 (可能与高频交易相关) 使用大块构建块创建不会耗尽系统资源的精简线程 - 封装的操作系统 API 以及同步和信令操作系统原语。 (与 HFT 性能时间优化的并行算法极为相关) 在相同的硬件和相同的延迟下将业务流程应用程序的吞吐量提高 10 倍或更多倍。 (与高频交易无关) 将每单位硬件同时处理的用户交互数量扩大 100 倍甚至更多倍。 (与高频交易无关)

使用更多的 CPU 内核并不能完全弥补 .Net 构建块对系统资源的消耗,因为更多的 CPU 内核是内存争用出现的保证。

【讨论】:

以上是关于C++ 与虚拟机语言在高频金融中的表现的主要内容,如果未能解决你的问题,请参考以下文章

经典Java面试100例,轻松搞定BAT——高频面试题

2019秋招:460道Java后端面试高频题答案版模块四:Java虚拟机

java虚拟机工作原理图解

深入理解JVM读书笔记三: 虚拟机类加载机制

重读《深入理解Java虚拟机》虚拟机如何加载Class文件

虚拟机的表现