我想使用BigDecimal来表示低延迟交易应用程序中的任意精度数字,如价格和金额,每秒有数千个订单和执行报告。
我不会对它们进行很多数学运算,所以问题不在于BigDecimal本身的性能,而在于大量BigDecimal对象会如何影响应用程序的性能。
我担心的是,大量短命的BigDecimal对象会给GC带来压力并导致CMS收集器中更大的Stop-The-World暂停 - 这绝对是我想要避免的。
您能否确认我的疑虑并建议使用BigD的替代方案?此外,如果您认为我的担忧是错误的 - 请解释原因。
更新:
感谢所有回答的人。我现在确信使用BigDecimal会损害我的应用程序的延迟(即使我仍然计划测量它)。
目前我们决定坚持使用“非常非OOP”解决方案(但没有精确命中) - 使用两个int
s,一个用于尾数,另一个用于指数。这背后的基本原理是原语放在堆栈上,而不是堆,因此不会被垃圾收集。
答案 0 :(得分:13)
如果您正在开发一种低延迟交易程序,并且您确实想要在延迟方面竞争,那么BigDecimal
不适合您,它是就如此容易。微秒很重要,对象创建和任何十进制数学都太贵了。
我认为,对于几乎其他人来说,使用BigDecimal
是明智之举,因为它对应用程序性能几乎没有可见影响。
在制定交易决策的延迟关键系统中,任何不可预测的垃圾收集暂停都是完全不可能的,所以当前的垃圾收集算法在正常使用中非常棒,它们是当延迟5毫秒可能花费你很多钱时,不一定合适。我希望大型系统是以非OOP风格编写的,除了一些实际的字符串(代码等)之外几乎没有使用任何对象。
您肯定需要使用 double
(甚至 float
)并获得精确度。
答案 1 :(得分:7)
现在JVM在处理短期对象的创建和销毁方面非常好,所以这不是曾经的担心。
我建议建立一个你想做的模型,然后测量它。这比你可能获得的任何“理论”答案更值得: - )
查看您的特定问题域,我过去使用过的类似系统使用双打来处理您想要使用BigDecimal的数据,并且可能值得重新审视您在这方面的想法。粗略地看一眼BigDecimal显示它有5个或6个字段,而单个双倍的额外内存消耗可能超过你所拥有的任何功能优势。
答案 2 :(得分:5)
BigDecimal
的效果确实比long
,double
甚至Long
低很多。这是否会对您的应用程序的性能产生重大影响取决于您的应用程序。
我建议找到应用程序中最慢的部分并对其进行比较测试。它还够快吗?如果没有,您可能希望编写一个包含单个long
的小型不可变类,可能会检查溢出。
答案 3 :(得分:3)
最大的问题是:你实际上需要任意精确的十进制计算吗?如果仅进行计算以分析数据并基于此进行决策,则最低有效位中的舍入和二进制表示伪像可能与您无关;然后继续使用double
(并分析您的算法numerical stability)。
如果您实际上正在进行数字必须加起来且精确度非常重要的事务,则double
不是一个选项。也许您可以将应用的这两部分分开,并仅在事务部分中使用BigDecimal
。
如果那是不可能的话,那么你几乎没有运气。你需要一个BCD数学库,我认为Java没有。你可以尝试自己编写,但这将是很多工作,结果可能仍然没有竞争力。
答案 4 :(得分:2)
为什么不使用带有隐含的十进制数的长整数?例如,假设您隐含了8个小数位,那么0.01将是1000000。
答案 5 :(得分:1)
我不确定您的要求是什么,但通常在进行财务计算时,无法承受由浮点类型引起的精度损失。通常,准确和适当的舍入比处理钱时的效率更重要
如果您不必处理百分比且所有金额都是整数,则可以使用整数类型(int,long或甚至BigInteger),其中一个含义为货币单位的0.01。
即使你认为你可以用double
类型获得精确度,也许值得首先尝试使用BigDecimal并检查它是否真的对你来说很慢。
答案 6 :(得分:1)
我为一个对应用程序进行性能评估和优化的团队工作,最近有一个应用程序正在使用Java Big Decimal。内存利用率存在严重的性能问题。我们后来切换到Newton Raphson,它允许我们通过计算保持准确性,并显示出更好的性能到大十进制。
只是添加..当我们使用双打时,我们看到了预期的大量精度损失