Подтвердить что ты не робот

Как использование BigDecimal повлияет на производительность приложения?

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

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

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

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

Обновление

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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