使用 BigDecimal 将如何影响应用程序性能?

发布于 2024-08-03 09:20:57 字数 500 浏览 6 评论 0原文

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

我不会对它们进行许多数学运算,因此问题不在于 BigDecimal 本身的性能,而在于大量的 BigDecimal 对象会影响应用程序的性能。

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

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

更新

感谢所有回答的人。我现在确信使用 BigDecimal 会损害我的应用程序的延迟(尽管我仍然计划测量它)。

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

I want to use BigDecimal to represent arbitrary precision numbers like prices and amounts in a low-latency trading application with thousands of orders and execution reports per second.

I won't be doing many math operations on them, so the question is not about performance of the BigDecimal per se, but rather about how large volumes of BigDecimal objects would affect performance of the application.

My concern is that huge amount of short-lived BigDecimal objects will put a strain on a GC and result in larger Stop-The-World pauses in CMS collector - and this is definitely what I would like to avoid.

Can you please confirm my concerns and suggest alternatives to using BigD? Also, if you think my concerns are wrong - please explain why.

Update:

Thanks for all who answered. I am now convinced that using BigDecimal will hurt latency of my application (even though I still plan to measure it).

For the time being we decided to stick with "very non-OOP" solution (but without accuracy hit) - use two ints, one for mantissa and another one for exponent. Rationale behind this is that primitives are placed on stack, not heap, and hence are not subject to garbage collection.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

冰之心 2024-08-10 09:20:57

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

我认为,对于几乎其他人来说,使用BigDecimal是理所当然的,因为它对应用程序性能几乎没有可见影响。

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

您当然需要使用 double (甚至 float)并接受准确性打击,否则使用long 并以美分、十分之一美分或聪(无论最小的记账单位是什么)为单位测量所有金额。

If you are developing a low-latency trading program and you genuinely want to compete in latency terms, then BigDecimal is not for you, it is as simple as that. Where microseconds matter, object creation and any decimal math is just too expensive.

I would argue that for almost everyone else, using BigDecimal is a no-brainer because it will have little visible impact on application performance.

In latency-critical systems making trading decisions, any unpredictable garbage-collection pauses are completely out-of-the-question so whilst the current garbage-collection algos are fantastic in normal use, they are not necessarily appropriate when a delay of 5 milliseconds may cost you a lot of money. I would expect that large systems were written in a very non-OOP style, with little or no objects being used aside from some interned Strings (for codes and the like).

You'll certainly need to use double (or even float) and take the accuracy hit, or else use long and measure all amounts in cents, tenths of a cent or satoshis (whatever the smallest unit of account is).

软糖 2024-08-10 09:20:57

如今,JVM 在处理短期对象的创建和销毁方面非常出色,因此不再像以前那样令人担心。

我建议构建一个您想要做的事情的模型,并测量它。这将比您可能得到的任何“理论”答案更有价值:-)

看看您的特定问题域,我过去研究过的类似系统可以很好地使用双精度来处理您想要使用的数据对于 BigDecimal,可能值得重新审视您在这方面的想法。粗略地看一下 BigDecimal 会发现它有 5 或 6 个字段,并且单个 double 的额外内存消耗可能会超过您所拥有的任何功能优势。

JVMs are pretty good nowadays in terms of handling the creation and destruction of short-lived objects, so that's not the worry it once was.

I would recommend building a mock-up of what you want to do, and measure it. That's going to be worth a lot more than any 'theoretical' answers that you may get :-)

Looking at your particular problem domain, similar systems I've worked on in the past work very well using doubles for the data you want to use BigDecimal for, and it may be worth re-examining your thinking in this area. A cursory glance at BigDecimal shows it has 5 or 6 fields, and the extra memory consumption over a single double may outweigh any functionality benefits you have.

泛滥成性 2024-08-10 09:20:57

BigDecimal 的性能确实比 longdouble 甚至 Long 低很多。这是否会对应用程序的性能产生显着影响取决于您的应用程序。

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

BigDecimal does have performance very much lower than, say, long, double or even Long. Whether that will make a significant difference to your application's performance depends upon your application.

I suggest finding the slowest part of your application and doing a comparative test on that. Is it still fast enough? If not, you might want to write a small immutable class containing a single long, possibly checking for overflows.

坏尐絯 2024-08-10 09:20:57

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

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

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

The big question is: do you actually need arbitrary precision decimal calculations? If the calculations are only done to analyze the data and make decisions based on that, then rounding and binary representation artifacts among the least significant bits are probably irrelevant to you; just go ahead and use double (and analyze your algorithms for numerical stability).

If you're actually doing transactions where the numbers have to add up and precision matters absolutely, then double is not an option. Perhaps you can separate these two parts of your app and use BigDecimal only in the transaction part.

If that is not possible, then you're pretty much out of luck. You'd need a BCD math library, and I don't think Java has one. You can try writing your own, but it will be a lot of work and the result may still not be competitive.

静谧幽蓝 2024-08-10 09:20:57

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

why don't you use a long with an implied number of decimal cases? For example, let's say you have 8 decimal places implied, then 0.01 would be 1000000.

深白境迁sunset 2024-08-10 09:20:57

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

I'm not sure what are your requirements, but generally when doing financial calculation one cannot afford accuracy hit caused by floating point types. Usually accuracy and proper rounding is more important than efficiency when dealing with money.
If you don't have to deal with percentages and all of the amounts are integer, you can use integer types (int, long or even BigInteger) with one meaning 0.01 of your currency unit.
And even if you think you can afford accuracy hit with double type, it may be worth trying first with BigDecimal and checking if it's really to slow for you.

泪意 2024-08-10 09:20:57

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

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

I work for a team that conducts performance assessments and optimizations on applications, had one application recently that was using Java Big Decimal. Significant performance issues were observed with memory utilization. We later switched to Newton Raphson which allowed us to keep up accuracy with calculations and shown significantly better performance to big decimal.

Just to add.. when we used doubles we saw a massive loss in accuracy as expected

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文