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