Собственная память Java быстрее, чем куча? - PullRequest
5 голосов
/ 03 мая 2011

Я изучаю варианты, чтобы помочь моему ресурсоемкому приложению, и при этом я наткнулся на терракотовую BigMemory . Исходя из того, что я понял, они используют не-сборочную, «кучную» память «вне кучи», и, очевидно, она примерно в 10 раз медленнее, чем «куча», из-за проблем сериализации / десериализации. До чтения о BigMemory я никогда не слышал о «родной памяти» за пределами обычного JNI. Хотя BigMemory является интересным вариантом, требующим дальнейшего рассмотрения, я заинтригован тем, что может быть достигнуто с помощью встроенной памяти, если можно обойти проблему сериализации.

Быстрее ли собственная память Java (я думаю, это влечет за собой ByteBuffer объекты?), Чем традиционная кучная память, когда нет проблем с сериализацией (например, если я сравниваю ее с огромным byte[])? Или капризы сбора мусора и т. Д. Делают этот вопрос без ответа? Я знаю, что «измерить» - это распространенный ответ, но я боюсь, что я бы не стал создавать репрезентативный тест, так как пока недостаточно знаю, как работает нативная память в Java.

Ответы [ 3 ]

4 голосов
/ 03 мая 2011

Прямая память быстрее при выполнении ввода-вывода, потому что это позволяет избежать одной копии данных. Однако для 95% приложений вы не заметите разницу.

Вы можете хранить данные в прямой памяти, однако это не будет быстрее, чем хранение POJO данных. (или как безопасный или читаемый или поддерживаемый) Если вы беспокоитесь о GC, попробуйте создать свои объекты (должны быть изменяемыми) заранее и повторно использовать их, не отбрасывая. Если вы не выбрасываете свои предметы, нечего собирать.


Является ли собственная память Java быстрее (я думаю, что это влечет за собой объекты ByteBuffer?), Чем традиционная память кучи, когда нет проблем с сериализацией (например, если я сравниваю ее с огромным байтом [])?

Прямая память может быть быстрее, чем использование байта [], если вы используете не байты, такие как int, поскольку она может считывать / записывать целые четыре байта, не превращая данные в байты. Однако это медленнее, чем использование POJO, поскольку оно должно ограничивать проверку каждого доступа.

Или капризы сбора мусора и т. Д. Делают этот вопрос без ответа?

Скорость не имеет ничего общего с ГХ. GC имеет значение только при создании или удалении объектов.

Кстати: если вы минимизируете количество отбрасываемых объектов и увеличиваете размер Eden, вы можете предотвратить даже незначительную коллекцию в течение длительного времени, например, целый день.

2 голосов
/ 03 мая 2011

Смысл BigMemory не в том, что собственная память работает быстрее, а в том, чтобы уменьшить нагрузку на сборщик мусора, который требует усилий для отслеживания ссылок на память и ее очистки.По мере увеличения размера кучи увеличиваются интервалы между сборками GC и загрузка процессора.В зависимости от ситуации это может создать своего рода «стеклянный потолок», когда куча Java становится настолько большой, что GC превращается в боров, потребляя огромное количество процессорной мощности каждый раз, когда GC включается. Кроме того, многие алгоритмы GC требуютнекоторый уровень блокировки, который означает, что никто ничего не может сделать, пока не завершится эта часть алгоритма отслеживания ссылок GC, хотя многие JVM стали намного лучше справляться с этим.Там, где я работаю, с нашим сервером приложений и JVM, мы обнаружили, что «стеклянный потолок» составляет около 1,5 ГБ.Если мы попытаемся сконфигурировать кучу больше этой, процедура GC начнет израсходовать более 50% общего процессорного времени, так что это очень реальные затраты.Мы определили это с помощью различных форм анализа GC, предоставляемых нашим поставщиком JVM.

BigMemory, с другой стороны, использует более ручной подход к управлению памятью.Это уменьшает накладные расходы и отчасти возвращает нас к необходимости выполнять собственную очистку памяти, как мы это делали в C, хотя и в гораздо более простом подходе, похожем на HashMap.Это существенно устраняет необходимость в традиционной процедуре сборки мусора, и в результате мы устраняем эти издержки.Я считаю, что ребята из Terracotta использовали встроенную память через ByteBuffer, так как это простой способ выбраться из-под Java-сборщика мусора.

В следующем техническом документе есть некоторая хорошая информация о том, как они спроектировали BigMemory, и некоторые сведения онакладные расходы ГК: http://www.terracotta.org/resources/whitepapers/bigmemory-whitepaper.

1 голос
/ 03 мая 2011

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

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

Хотя тесты производительности могут дать вам приблизительное представление о накладных расходах, фактические накладные расходы будут зависеть от конкретного приложения. Мой совет будет:

  • Пройдите по этому маршруту, только если знаете, что вам нужно. (Вы будете привязывать ваше приложение к определенной технологии реализации.)

  • Будьте готовы к некоторым навязчивым изменениям в вашем приложении, если соответствующие данные еще не управляются с использованием кеша.

  • Будьте готовы потратить некоторое время на (пере) настройку кода кэширования, чтобы добиться хорошей производительности с BigMemory.

  • Если ваши структуры данных являются сложными, ожидайте пропорционально больших накладных расходов и времени на настройку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...