2009-09-04 2 views
13

Я хочу использовать BigDecimal для представления произвольных чисел точности, таких как цены и суммы в торговом приложении с низкой задержкой, с тысячами заказов и отчетов об исполнении в секунду.Как использование BigDecimal повлияет на производительность приложения?

Я не буду делать много математических операций над ними, поэтому речь идет не о производительности BigDecimal как таковой, а о том, как большие объемы объектов BigDecimal повлияют на производительность приложения.

Моя забота заключается в том, что огромное количество недолговечных объектов BigDecimal будет создавать нагрузку на GC и привести к большим остановкам Stop-The-World в сборщике CMS - и это определенно то, чего я бы хотел избежать.

Не могли бы вы подтвердить мои проблемы и предложить альтернативы использованию BigD? Кроме того, если вы считаете, что мои проблемы ошибаются, пожалуйста, объясните, почему.

Update:

Спасибо всем, кто ответил. Теперь я убежден, что использование BigDecimal повредит латентность моего приложения (хотя я все еще планирую его измерить).

На данный момент мы решили придерживаться решения «очень не-ООП» (но без точного попадания) - используйте два int s, один для мантиссы и другой для экспоненты. Обоснование этого заключается в том, что примитивы помещаются в стек, а не в кучу, и, следовательно, не подлежат сборке мусора.

ответ

12

Если вы разрабатываете торговую программу с низкой задержкой, и вы действительно хотите конкурировать в латентности терминах, то BigDecimalне для вас, это так просто. Там, где вопрос микросекунд, создание объекта и любая десятичная математика слишком дороги.

Я считаю, что для почти все остальные, используя BigDecimal не представляет никакой опасности, потому что он будет иметь мало видимое влияние на производительность приложений.

В латентности критичных систем принятия торговых решений, любых непредсказуемых пауз мусора коллекции полностью из-офе-вопроса, так в то время как текущий Algos мусора сбора является фантастическим при нормальном использовании, они не обязательно подходят, когда задержка в 5 миллисекунд может стоить вам больших денег. Я ожидал бы, что большие системы были написаны в стиле, отличном от ООП, с небольшими или отсутствующими объектами, кроме некоторых интернированных строк (для кодов и т. П.).

Вам, конечно, нужно использовать double (или даже float) и возьмите точность попадания.

+0

Если BidD не для меня, что тогда? Я не использую двойники (поскольку он приносит много новых проблем с числами с плавающей запятой, с которыми я работаю, - это, естественно, десятичные числа). – vtrubnikov

+2

+1 для указания ключевого момента о конкуренции по производительности. Как и в шутке об тигре и кроссовках, абсолютные цифры редко имеют значение, лучше/хуже, чем это важно. – soru

+0

@ valery_la99 - Я добавил к своему ответу –

7

JVM довольно хороши в настоящее время с точки зрения обработки создания и уничтожения короткоживущих объектов, так что это не беспокойство, которое когда-то было.

Я бы рекомендовал построить макет того, что вы хотите сделать, и measure it. Это будет стоить намного больше, чем любые «теоретические» ответы, которые вы можете получить :-)

Посмотрите на ваш конкретный проблемный домен, аналогичные системы, над которыми я работал в прошлом, очень хорошо работают с использованием удвоений для данных вы хотите использовать BigDecimal, и, возможно, стоит пересмотреть свое мышление в этой области. Беглый взгляд на BigDecimal показывает, что он имеет 5 или 6 полей, а дополнительное потребление памяти в течение одного двойника может перевесить любые преимущества функциональности, которые у вас есть.

+0

Одним из таких полей является «BigInteger» (а одно из полей «BigInteger» - это 'int []') (Sun реализация). –

+1

Хорошая точка. Я также заметил, что там есть String, но я понимаю, что он заполнен только во время вызова toString(). –

+1

Мне трудно поверить, что торговая система, основанная на удвоениях сумм и цен, может вообще работать вообще, не говоря уже о том, что очень хорошо. Правильность вряд ли является «функциональной выгодой», которую нужно пересмотреть. –

5

BigDecimal имеет производительность намного ниже, чем, скажем, long, double или даже Long. Будет ли это иметь существенное значение для производительности вашего приложения, зависит от вашего приложения.

Я предлагаю найти самую медленную часть вашего приложения и выполнить сравнительный тест. Это все еще достаточно быстро? Если нет, вы можете написать небольшой неизменяемый класс, содержащий один long, возможно, проверяющий переполнение.

1

Я не уверен, каковы ваши требования, но, как правило, при выполнении финансовых расчетов нельзя получить точность попадания, вызванного типами с плавающей запятой. Обычно точность и правильное округление важнее эффективности при работе с деньгами.
Если вам не нужно иметь дело с процентами, и все суммы целые, вы можете использовать целые типы (int, long или даже BigInteger) с одним значением 0.01 вашей валютной единицы.
И даже если вы считаете, что можете получить точный хит с типом double, может быть стоит попробовать сначала с BigDecimal и проверить, действительно ли это замедляется для вас.

2

Большой вопрос: вы на самом деле необходимо произвольные прецизионные десятичные вычисления? Если вычисления выполняются только для анализа данных и принятия решений на основе этого, то артефакты округления и двоичного представления среди наименее значимых битов, вероятно, не имеют к вам отношения; просто используйте и используйте double (и проанализируйте свои алгоритмы для numerical stability).

Если вы на самом деле делаете транзакции, где цифры должны складываться, а точность имеет значение абсолютно, то double не является вариантом. Возможно, вы можете разделить эти две части своего приложения и использовать BigDecimal только в транзакции.

Если это невозможно, вам не повезло. Вам понадобится математическая библиотека BCD, и я не думаю, что у нее есть Java. Вы можете попробовать написать свое собственное, но это будет много работы, и результат может быть еще неконкурентоспособным.

1

Я работаю в команде, которая проводит оценки производительности и оптимизации приложений, недавно было одно приложение, использующее Java Big Decimal. Значительные проблемы с производительностью наблюдались при использовании памяти. Позднее мы переключились на Newton Raphson, который позволил нам поддерживать точность расчетов и показал значительно лучшую производительность до большого десятичного знака.

Просто добавить .. когда мы использовали двойников мы видели массовые потери в точности, как и ожидалось

2

почему бы вам не использовать долго с подразумеваемой числом десятичных случаев? Например, предположим, что вы указали 8 знаков после запятой, тогда 0.01 будет 1000000.