views:

702

answers:

5

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.

+6  A: 

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.

Brian Agnew
One of those fields is a `BigInteger` (and one of the fields of `BigInteger` is an `int[]`) (Sun implementation).
Tom Hawtin - tackline
Good point. I also noticed a String in there but I understand that's only populated during a toString() invocation
Brian Agnew
I find it hard to believe that a trading system based on doubles for amounts and prices could ever work at all, let alone very well. Correctness is hardly a "functionality benefit" that one should ever re-examine.
Michael Borgwardt
@Michael - most systems I've worked on will store notionals/quantities/cashflows etc. as doubles, without issues
Brian Agnew
I assume those systems analyse the data rather than actually performing the transactions.
Michael Borgwardt
+1 for "build and measure". Way too much gets written as though general tendencies apply to each and every situation.
CPerkins
Good comments. Doubles give you about 50 bits of precision (about 17 decimal places). If you need more than that, big integers probably work better than building it yourself.
Mike Dunlavey
+4  A: 

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.

Tom Hawtin - tackline
+5  A: 

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.

oxbow_lakes
If BidD is not for me, what is, then? I don't to use doubles (as it bring whole lot of new problems with floating point -numbers which I operate with are naturally decimals).
valery_la99
+1 for stating the key point about competing on performance. As in the joke about the tiger and the running shoes, absolute numbers rarely matters much, better than/worse than is what counts.
soru
@valery_la99 - I've added to my answer
oxbow_lakes
+1  A: 

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.

Tadeusz Kopec
A: 

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.

Michael Borgwardt