Насколько большим должен быть буфер в Java, чтобы его можно было повторно использовать?
Или, говоря по-другому: я могу многократно распределять, использовать и отбрасывать объекты byte [] ИЛИ запускать пул для их сохранения и повторного использования. Я мог бы выделить много маленьких буферов, которые часто сбрасываются, или несколько больших, которых нет. В каком размере дешевле их объединить, чем перераспределить, и как небольшие выделения сравниваются с большими?
EDIT:
Хорошо, конкретные параметры. Скажем, процессор Intel Core 2 Duo, последняя версия виртуальной машины для выбранной ОС. Эти вопросы не так расплывчаты, как кажется ... небольшой код и график могут ответить на них.
EDIT2:
Вы опубликовали много хороших общих правил и обсуждений, но вопрос действительно требует цифр. Опубликуйте их (и код тоже)! Теория великолепна, но доказательством являются цифры. Не имеет значения, отличаются ли результаты от системы к системе, я просто ищу приблизительную оценку (на порядок). Никто, кажется, не знает, будет ли разница в производительности в 1,1, 2, 10 или 100+ раз, и это то, что имеет значение. Это важно для любого кода Java, работающего с большими массивами - сети, биоинформатика и т. Д.
Предложения, чтобы получить хороший тест:
- Прогрейте код перед запуском в тесте. Все методы должны вызываться как минимум 1000 10000 раз, чтобы получить полную оптимизацию JIT.
- Убедитесь, что тестируемые методы выполняются не менее 1 10 секунд и, если возможно, используйте System.nanotime, чтобы получить точные значения времени.
- Запуск бенчмарка в системе, в которой работают только минимальные приложения
- Запустите бенчмарк 3-5 раз и все время отчитывайтесь, чтобы мы увидели, насколько он последовательный.
Я знаю, что это неопределенный и несколько требовательный вопрос. Я буду проверять этот вопрос регулярно, и ответы будут получать комментарии и оценивать последовательно. Ленивые ответы не будут (см. Ниже критерии). Если у меня нет исчерпывающих ответов, я назначу награду. В любом случае я мог бы вознаградить действительно хороший ответ небольшим дополнительным.
Что я знаю (и мне не нужно повторяться):
- Выделение памяти Java и сборщик мусора происходят быстро и быстро.
- Объединение объектов раньше было хорошей оптимизацией, но теперь это в большинстве случаев снижает производительность.
- Объединение объектов «обычно не является хорошей идеей, если объекты не дороги в создании». Ядда Ядда.
Что я не знаю:
- Как быстро следует ожидать выделения памяти (МБ / с) на стандартном современном ЦП?
- Как размер распределения влияет на скорость распределения?
- Какова точка безубыточности для количества / размера распределений по сравнению с повторным использованием в пуле?
Маршруты к принятому ответу (чем больше, тем лучше):
- Недавний технический документ, показывающий цифры для распределения и GC на современных процессорах (последние, как в прошлом году или около того, JVM 1.6 или позже)
- Код для краткого и правильного микропробега, который я могу запустить
- Объяснение того, как и почему распределение влияет на производительность
- Реальные примеры / анекдоты от тестирования этого вида оптимизации
Контекст:
Я работаю над библиотекой, добавляющей поддержку сжатия LZF в Java. Эта библиотека расширяет классы H2 СУБД LZF, добавляя дополнительные уровни сжатия (большее сжатие) и совместимость с потоками байтов из библиотеки C LZF. Я думаю о том, стоит ли пытаться повторно использовать буферы фиксированного размера, используемые для сжатия / распаковки потоков. Буферы могут быть ~ 8 кБ или ~ 32 кБ, а в оригинальной версии они ~ 128 кБ. Буферы могут быть выделены один или несколько раз на поток. Я пытаюсь понять, как я хочу обрабатывать буферы для достижения наилучшей производительности, с перспективой на потенциальную многопоточность в будущем.
Да, библиотека будет выпущена с открытым исходным кодом, если кто-то заинтересован в ее использовании.