Зависит ли скорость выделения от используемого сборщика мусора? - PullRequest
2 голосов
/ 01 июня 2010

Мое приложение выделяет тонну объектов (> 1 млн. В секунду; большинство объектов - это байтовые массивы размером ~ 80-100 и строки одинакового размера), и я думаю, что это может быть причиной его низкой производительности.

Рабочий набор приложения составляет всего десятки мегабайт. Профилирование приложения показывает, что время GC ничтожно мало.

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

Это так? Или производительность распределения не зависит от настроек GC при условии, что сборка мусора сама по себе занимает мало времени?

Ответы [ 3 ]

2 голосов
/ 01 июня 2010

Конечно, ваша производительность зависит от используемого распределителя. Но вы профилировали GC и видели, что это не большая проблема. Кроме того, одной из сильных сторон GC является быстрое распределение за счет более медленного сбора.

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

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

Тем не менее, я не думаю, что производительность сильно зависит от того, как вы управляете памятью, но как вы на самом деле используете ее, обращаетесь к ней. Скорее всего, ваш профилировщик имеет определенный ответ.

1 голос
/ 01 июня 2010

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

Вторая - инициализация объектов, которые вы выделяете. Поскольку все, что вы выделяете в Java, инициализируется, затраты на инициализацию могут легко перевесить стоимость размещения (за исключением самых простых, самых маленьких объектов). Есть больше. Поскольку для инициализации требуется запись всей области памяти, которую занимает новый объект (например, если вы выделяете «новый байт [1 << 20]», весь мегабайт должен быть установлен в нули), это также обычно вытягивает эту память в процессор. кэшировать, исключая другие, более старые строки кэша (которые могут принадлежать или не принадлежать вашему текущему «горячему» рабочему набору). </p>

Если вы сравнительно мало обрабатываете каждый из ваших массивов, эти эффекты могут серьезно повлиять на производительность вашего кода. Этого можно частично избежать, многократно используя одни и те же массивы, но обычно это усложняет логику программы. Также часто нелегко определить, действительно ли виновником является очистка кеша. Невозможно сказать из того, что мало информации приведено в вашем вопросе.

0 голосов
/ 02 июня 2010

Ваша виртуальная машина пытается объединить строки? Однажды я слышал, что виртуальная машина IBM выполняла что-то вроде интернирования строк, но динамически (не знаю, верна ли она), возможно, ваша виртуальная машина пытается выполнить дополнительную работу для построения внутренней структуры данных внутренних элементов String.

Вы случайно не делаете что-то вроде byte b[] = new byte[100]; String s = new String(b);? Вы можете попытаться не размещать объекты String, а вместо этого выделить некоторый случайный объект, который имеет ссылку на byte [] (для сравнения).

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