Я делаю некоторые оптимизации на декодере MPEG. Чтобы убедиться, что мои оптимизации ничего не нарушают, у меня есть набор тестов, который тестирует всю кодовую базу (как оптимизированную, так и оригинальную), а также проверяет, что они оба дают идентичные результаты (в основном, просто пропуская пару разных потоков через декодер и crc32). выходы).
При использовании опции "-server" с Sun 1.6.0_18 набор тестов работает на 12% медленнее на оптимизированной версии после прогрева (по сравнению с настройкой по умолчанию "-client"), в то время как исходная кодовая база увеличивается хороший импульс, работающий примерно в два раза быстрее, чем в режиме клиента.
Хотя поначалу мне это казалось просто проблемой, я добавил цикл, чтобы повторить весь набор тестов несколько раз. Затем время выполнения становится постоянным для каждого прохода, начиная с 3-й итерации теста, но оптимизированная версия остается на 12% медленнее, чем в режиме клиента.
Я также почти уверен, что это не проблема сбора мусора, так как код не требует абсолютно никаких выделений объектов после запуска. Код состоит в основном из нескольких операций с битами (потоковое декодирование) и множества базовых математических вычислений (генерирование звука PCM) Используются только классы JDK - ByteArrayInputStream (передает поток в тест и исключает дисковый ввод-вывод из тестов) и CRC32 (для проверки результата). Я также наблюдал такое же поведение с Sun JDK 1.7.0_b98 (только там 15% вместо 12%).
О, и все тесты проводились на одной машине (одноядерном) без запуска других приложений (WinXP). Хотя есть некоторые неизбежные различия в измеренных временах выполнения (с использованием System.nanoTime, кстати), разница между различными тестовыми прогонами с одинаковыми настройками никогда не превышала 2%, обычно менее 1% (после прогрева), поэтому я заключаю, что эффект реальный, а не чисто индуцированный измерительным механизмом / машиной.
Существуют ли какие-либо известные шаблоны кодирования, которые хуже работают на сервере JIT? В противном случае, какие варианты доступны, чтобы «заглянуть» под капот и посмотреть, что там делает JIT?
Может быть, я неверно описал свое "прогревочное" описание. Там нет явного кода разминки. Весь набор тестов (состоящий из 12 различных потоков MPEG, содержащий ~ 180 тыс. Аудиокадров) выполняется 10 раз, и я считаю, что первые 3 прогона являются «прогревом». Один тестовый цикл занимает около 40 секунд 100% процессора на моей машине.
Я играл с опциями JVM, как было предложено, и использовал "-Xms512m -Xmx512m -Xss128k -server -XX: CompileThreshold = 1 -XX: + PrintCompilation -XX: + AggressiveOpts -XX: + PrintGC" Я мог проверить что вся компиляция происходит в первые 3 раунда. Сборка мусора происходит каждые 3-4 раунда и занимает не более 40 мс (512 м чрезвычайно большой, так как тесты можно запустить с 16 м просто отлично). Из этого я делаю вывод, что сборка мусора не имеет здесь никакого влияния. Тем не менее, при сравнении клиента с сервером (другие параметры не изменились) разница в 12/15% остается.