У меня есть (java) приложение, которое работает в среде с малой задержкой, обычно оно обрабатывает инструкции за ~ 600 микрон (+/- 100). Естественно, по мере того, как мы продвинулись дальше в микросекундное пространство, вы видите, что затраты на задержку меняются, и прямо сейчас мы заметили, что 2/3 этого времени тратится на выделение двух основных объектов домена.
Бенчмаркинг изолировал проблемные участки кода буквально для построения объектов из существующих ссылок, т.е. в основном множество ссылок (~15 в каждом классе) и пара обновленных списков, хотя см. примечание ниже о том, что именно измеряется. здесь.
Каждый из них постоянно занимает ~ 100 микрон, что для меня необъяснимо, и я пытаюсь выяснить, почему. Быстрый тест показывает, что объект аналогичного размера, полный строк, требует около 2-3 микросекунд для обновления, очевидно, что этот вид теста сопряжен с трудностями, но он может быть полезен в качестве базового уровня.
Здесь 2 вопроса
- как расследовать такое поведение?
- какие объяснения существуют для медленного распределения?
Обратите внимание, что в качестве аппаратного обеспечения используется Solaris 10 x86 на Sun X4600 с 8*двухъядерными оптеронами с частотой 3,2 ГГц.
Вещи, которые мы рассмотрели, включают
- проверка статистики PrintTLAB показывает несколько медленных распределений, поэтому там не должно быть конфликтов.
- PrintCompilation предполагает, что один из этих фрагментов кода не является JIT-дружественным, хотя Solaris, похоже, имеет здесь какое-то необычное поведение (а именно, по сравнению с современным Linux, у него нет Linux, аналогичного винтажу Solaris10, для работы на стенде прямо сейчас)
- LogCompilation... немного сложнее разобрать, если не сказать больше, так что это постоянная работа, пока ничего очевидного
- Версии JVM... согласуются между 6u6 и 6u14, еще не пробовали 6u18 или последнюю 7
Любые и все мысли приветствуются
Сводка комментариев к разным постам, чтобы попытаться внести ясность
- стоимость, которую я измеряю, — это общая стоимость создания объекта, построенного с помощью Builder (например, одного из эти), частный конструктор которого несколько раз вызывает новый ArrayList, а также устанавливает ссылки на существующие объекты. Измеренная стоимость включает стоимость настройки построителя и преобразования построителя в объект домена.
- компиляция (по горячей точке) оказывает заметное влияние, но все еще относительно медленная (компиляция в этом случае сокращает время со 100 до ~ 60)
- компиляция (по горячей точке) в моем наивном тесте сокращает время выделения с ~ 2 микросекунд до ~ 300 нс.
- задержка не зависит от алгоритма сбора молодого поколения (ParNew или Parallel Scavenge)