В какой момент стоит повторно использовать массивы в Java? - PullRequest
31 голосов
/ 24 декабря 2009

Насколько большим должен быть буфер в Java, чтобы его можно было повторно использовать?

Или, говоря по-другому: я могу многократно распределять, использовать и отбрасывать объекты byte [] ИЛИ запускать пул для их сохранения и повторного использования. Я мог бы выделить много маленьких буферов, которые часто сбрасываются, или несколько больших, которых нет. В каком размере дешевле их объединить, чем перераспределить, и как небольшие выделения сравниваются с большими?

EDIT:

Хорошо, конкретные параметры. Скажем, процессор Intel Core 2 Duo, последняя версия виртуальной машины для выбранной ОС. Эти вопросы не так расплывчаты, как кажется ... небольшой код и график могут ответить на них.

EDIT2:

Вы опубликовали много хороших общих правил и обсуждений, но вопрос действительно требует цифр. Опубликуйте их (и код тоже)! Теория великолепна, но доказательством являются цифры. Не имеет значения, отличаются ли результаты от системы к системе, я просто ищу приблизительную оценку (на порядок). Никто, кажется, не знает, будет ли разница в производительности в 1,1, 2, 10 или 100+ раз, и это то, что имеет значение. Это важно для любого кода Java, работающего с большими массивами - сети, биоинформатика и т. Д.

Предложения, чтобы получить хороший тест:

  1. Прогрейте код перед запуском в тесте. Все методы должны вызываться как минимум 1000 10000 раз, чтобы получить полную оптимизацию JIT.
  2. Убедитесь, что тестируемые методы выполняются не менее 1 10 секунд и, если возможно, используйте System.nanotime, чтобы получить точные значения времени.
  3. Запуск бенчмарка в системе, в которой работают только минимальные приложения
  4. Запустите бенчмарк 3-5 раз и все время отчитывайтесь, чтобы мы увидели, насколько он последовательный.

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

Что я знаю (и мне не нужно повторяться):

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

Что я не знаю:

  • Как быстро следует ожидать выделения памяти (МБ / с) на стандартном современном ЦП?
  • Как размер распределения влияет на скорость распределения?
  • Какова точка безубыточности для количества / размера распределений по сравнению с повторным использованием в пуле?

Маршруты к принятому ответу (чем больше, тем лучше):

  • Недавний технический документ, показывающий цифры для распределения и GC на современных процессорах (последние, как в прошлом году или около того, JVM 1.6 или позже)
  • Код для краткого и правильного микропробега, который я могу запустить
  • Объяснение того, как и почему распределение влияет на производительность
  • Реальные примеры / анекдоты от тестирования этого вида оптимизации

Контекст:

Я работаю над библиотекой, добавляющей поддержку сжатия LZF в Java. Эта библиотека расширяет классы H2 СУБД LZF, добавляя дополнительные уровни сжатия (большее сжатие) и совместимость с потоками байтов из библиотеки C LZF. Я думаю о том, стоит ли пытаться повторно использовать буферы фиксированного размера, используемые для сжатия / распаковки потоков. Буферы могут быть ~ 8 кБ или ~ 32 кБ, а в оригинальной версии они ~ 128 кБ. Буферы могут быть выделены один или несколько раз на поток. Я пытаюсь понять, как я хочу обрабатывать буферы для достижения наилучшей производительности, с перспективой на потенциальную многопоточность в будущем.

Да, библиотека будет выпущена с открытым исходным кодом, если кто-то заинтересован в ее использовании.

Ответы [ 11 ]

0 голосов
/ 27 декабря 2009

Более важным, чем размер буфера, является количество выделенных объектов и общая выделенная память.

  1. Является ли использование памяти проблемой вообще? Если это маленькое приложение, не стоит беспокоиться.

Реальное преимущество пула состоит в том, чтобы избежать фрагментации памяти. Затраты на выделение / освобождение памяти невелики, но недостатком является то, что при многократном выделении множества объектов разных размеров память становится более фрагментированной. Использование пула предотвращает фрагментацию.

...