Повторное выделение байтовых массивов одинакового размера, заменить на пулы? - PullRequest
2 голосов
/ 14 марта 2011

В рамках анализа памяти мы обнаружили следующее:

          percent          live          alloc'ed  stack class
 rank   self  accum     bytes objs     bytes  objs trace name
    3  3.98% 19.85%  24259392  808 3849949016 1129587 359697 byte[]
    4  3.98% 23.83%  24259392  808 3849949016 1129587 359698 byte[]

Вы заметите, что много объектов выделено, но немногие остаются живыми.Это по простой причине - два байтовых массива выделяются для каждого генерируемого экземпляра «клиента».Клиенты не могут быть повторно использованы - каждый может обработать только один запрос и затем выбрасывается.Массивы байтов всегда имеют одинаковый размер (30000).

Мы рассматриваем возможность перемещения в пул (Apache GenericObjectPool) байтовых массивов, так как обычно в любой момент времени существует известное количество активных клиентов (размер пула не должен сильно колебаться).Таким образом, мы можем сэкономить на распределении памяти и сборке мусора.Вопрос в том, вызовет ли пул серьезный удар по процессору?Является ли эта идея хорошей идеей для всех?

Спасибо за вашу помощь!

Ответы [ 4 ]

2 голосов
/ 15 марта 2011

Я думаю, что есть хорошие причины, связанные с gc, чтобы избежать такого рода распределения.В зависимости от размера кучи и свободного места в eden во время выделения, простое выделение байта 30000 элементов [] может стать серьезным ударом по производительности, учитывая, что он может легко быть больше, чем TLAB (следовательно, распределение не является ударомсобытие указателя) & может даже не быть достаточно места в доступном eden, следовательно, выделение непосредственно в пребывания, что само по себе может вызвать еще один удар по линии из-за увеличения активности полного gc (особенно если используется cms из-за фрагментации).

Сказав это, комментарии от fdreger также полностью действительны.Многопоточный пул объектов - это мрачная вещь, которая может вызвать головную боль.Вы упоминаете, что они обрабатывают только один запрос, если этот запрос обслуживается только одним потоком, тогда байтов ThreadLocal [], который стирается в конце запроса, может быть хорошим вариантом.Если запрос недолговечен относительно вашего типичного периода молодого gc, тогда проблема с ссылками young-> old может не быть большой проблемой (так как вероятность обработки любого данного запроса во время gc мала, даже если вы гарантированно получите его).это периодически).

2 голосов
/ 15 марта 2011

Возможно, пул не сильно вам поможет, если вообще сделает, может ухудшить ситуацию, хотя это зависит от ряда факторов (какой GC вы используете, как долго живут объекты, сколько памяти доступно и т. Д.)):

Время GC зависит в основном от количества живых объектов.Collector (я предполагаю, что вы запускаете ванильную Java JRE) не посещает мертвые объекты и не освобождает их один за другим.Это освобождает целые области памяти после копирования живых объектов (это сохраняет память опрятной и сжатой).100 мертвых объектов могут быть собраны так же быстро, как и 100000. С другой стороны, все живые объекты должны быть скопированы - так что, если у вас, скажем, есть пул из 100 объектов и только 50 используются в данный момент времени, сохраняя неиспользуемый объектЭто будет стоить вам.

Если ваши массивы в настоящее время, как правило, живут короче, чем время, необходимое для пребывания (копирование в пространство старого поколения), есть еще одна проблема: ваши объединенные массивы, безусловно, будут жить достаточно долго.Это создаст ситуацию, когда существует множество ссылок от старого поколения к молодому, и GC оптимизируются с учетом обратной ситуации.

На самом деле вполне возможно, что объединение массивов сделает ваш GC МЕНЬШЕ, чем создание новых;это обычно имеет место с дешевыми объектами.

Другая стоимость объединения заключается в синхронизации объектов между потоками и очистке их после использования.И то, и другое хитрее, чем кажется.

Подводя итог, если вы не хорошо знаете внутренности своего GC и не понимаете, как он работает под капотом, И не получили результатов от профилировщика, которые показывают, что управление всеми массивамиявляется узким местом - НЕ БАССЕЙН.В большинстве случаев это плохая идея.

1 голос
/ 14 марта 2011

Если сборка мусора в вашем случае действительно снижает производительность (часто очистка пространства eden не занимает много времени, если не много объектов выживает), и легко подключить пул объектов, попробуйте и измерьте его .

Это, безусловно, зависит от потребностей вашего приложения.

0 голосов
/ 14 марта 2011

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

...