15

我想使用 BigDecimal 来表示任意精度数字,例如在每秒具有数千个订单和执行报告的低延迟交易应用程序中的价格和金额。

我不会对它们做很多数学运算,所以问题不在于 BigDecimal 本身的性能,而在于 BigDecimal 对象的大容量会影响应用程序的性能。

我担心的是,大量的短期 BigDecimal 对象会给 GC 带来压力,并导致 CMS 收集器中出现更大的 Stop-The-World 停顿——这绝对是我想要避免的。

您能否确认我的担忧并提出使用 BigD 的替代方案?另外,如果您认为我的担忧是错误的 - 请解释原因。

更新

感谢所有回答的人。我现在确信使用 BigDecimal 会损害我的应用程序的延迟(即使我仍打算测量它)。

目前,我们决定坚持使用“非常非 OOP”的解决方案(但不会影响准确性) - 使用两个ints,一个用于尾数,另一个用于指数。这背后的基本原理是原语放置在堆栈上,而不是堆上,因此不受垃圾收集的影响。

4

7 回答 7

15

如果您正在开发一个低延迟交易程序,并且您真的想在延迟方面进行竞争,那么BigDecimal 不适合您,就这么简单。在微秒重要的地方,对象创建和任何十进制数学都太昂贵了。

我会争辩说,对于几乎所有其他人来说,使用BigDecimal是不费吹灰之力的,因为它对应用程序性能几乎没有明显的影响。

在做出交易决策的延迟关键系统中,任何不可预测的垃圾收集暂停都是完全不可能的,因此虽然当前的垃圾收集算法在正常使用中非常出色,但当延迟 5 毫秒时它们不一定合适花了你很多钱。我希望大型系统是以非常非 OOP 的风格编写的,除了一些内部字符串(用于代码等)之外,几乎没有使用任何对象。

您当然需要使用double(或什至float)并获得准确性,或者使用long并以美分、十分之一美分或 satoshis 为单位测量所有金额(无论最小的帐户单位是什么)。

于 2009-09-04T09:26:35.757 回答
8

如今,JVM 在处理短寿命对象的创建和销毁方面已经相当出色,因此不再像以前那样担心。

我建议建立一个你想做的模型,并对其进行测量。这将比您可能得到的任何“理论”答案更有价值:-)

查看您的特定问题域,我过去工作过的类似系统非常好地使用双精度数来处理您想要使用 BigDecimal 的数据,并且可能值得重新检查您在该领域的想法。粗略看一下 BigDecimal 会发现它有 5 或 6 个字段,并且单个 double 的额外内存消耗可能超过您拥有的任何功能优势。

于 2009-09-04T08:55:28.130 回答
5

BigDecimal的性能确实比 ,long甚至double.低很多Long。这是否会对您的应用程序的性能产生重大影响取决于您的应用程序。

我建议找到应用程序中最慢的部分并对其进行比较测试。它仍然足够快吗?如果没有,您可能想要编写一个包含单个 的小型不可变类long,可能会检查溢出。

于 2009-09-04T09:15:07.870 回答
4

最大的问题是:你真的需要任意精度的十进制计算吗?如果计算只是为了分析数据并据此做出决策,那么最低有效位之间的舍入和二进制表示伪影可能与您无关;继续使用double(并分析您的算法以获得数值稳定性)。

如果您实际上是在进行数字必须相加且精度绝对重要的交易,那么double这不是一个选择。也许您可以将应用程序的这两个部分分开并BigDecimal仅在事务部分中使用。

如果那是不可能的,那么你很不走运。您需要一个BCD数学库,而我认为 Java 没有。您可以尝试自己编写,但这将是很多工作,并且结果可能仍然没有竞争力。

于 2009-09-04T10:34:59.050 回答
2

为什么不使用带有隐含小数位数的 long 呢?例如,假设您隐含了 8 个小数位,那么 0.01 就是 1000000。

于 2011-07-15T16:30:44.273 回答
1

我不确定您的要求是什么,但通常在进行财务计算时,无法承受浮点类型造成的准确性损失。通常,在处理金钱时,准确性和适当的舍入比效率更重要。
如果您不必处理百分比并且所有金额都是整数,则可以使用整数类型(int、long 甚至 BigInteger),其中一个表示您的货币单位的 0.01。
即使您认为您可以承受double类型命中的准确性,也可能值得首先尝试使用 BigDecimal 并检查它是否真的会减慢您的速度。

于 2009-09-04T10:25:15.047 回答
1

我在一个对应用程序进行性能评估和优化的团队工作,最近有一个使用 Java Big Decimal 的应用程序。在内存利用率方面观察到了显着的性能问题。后来我们改用 Newton Raphson,这使我们能够保持计算的准确性,并在大小数方面表现出明显更好的性能。

只是补充一下..当我们使用双打时,我们看到预期的准确性大幅下降

于 2011-04-28T14:51:20.257 回答