2009-09-26 3 views
32

Я поддерживаю приложение обмена сообщениями Java, которое требует низкой задержки (< 300 микросекунд, обрабатывающих каждое сообщение). Тем не менее, наше профилирование показывает, что виртуальная машина Sun Java сначала запускается медленно и ускоряется после первых 5000 сообщений или около того. Первые 5000 сообщений имеют латентность 1-4 миллисекунды. После примерно 5000, последующие сообщения имеют задержку ~ 250 микросекунд, со случайными выбросами.Техника или утилита для минимизации времени «разминки» Java?

Как правило, это типичное поведение для приложения Java. Однако, с точки зрения бизнеса, недопустимо сообщать клиенту, что им приходится ждать, пока JVM «разогреется», прежде чем увидит, какую производительность они требуют. Приложение должно быть «подогретая» перед первым сообщением клиента обрабатывается

JVM является ВС 1.6.0 обновление 4.

Идеи для преодоления этой проблемы:

  1. настройки виртуальной машины Java, такой как -XX: CompileThreshold =
  2. Добавьте компонент для «разминки» приложения при запуске, например, путем отправки «поддельных сообщений» через приложение.
  3. Статически загружать приложение и классы JDK при запуске приложения, чтобы классы не загружались из JAR при обработке сообщений клиента.
  4. Некоторая утилита или агент Java, который выполняет одну или обе из этих двух идей, так что мне не нужно повторно изобретать колесо.

ПРИМЕЧАНИЕ. Очевидно, что для этого решения я рассматриваю все факторы, включая микросхему, тип диска и конфигурацию и настройки ОС. Однако для этого вопроса я хочу сосредоточиться на том, что можно сделать для оптимизации приложения Java и свести к минимуму время прогрева.

+0

Думаю, вам лучше посмотреть на причину этой первоначальной задержки. Инструменты профилирования могут помочь. – Thomas

+1

Отправьте 5000 поддельных сообщений на сервер как часть процедуры установки и запуска. – Zed

+1

5000 поддельных сообщений (даже если это была хорошая идея) звучит так, как будто это добавит 5-20 секунд к времени запуска приложения. –

ответ

24

«Разминка» в Java, как правило, две вещи:

(1): Ленивый класс нагрузки: Это может быть работа вокруг силой его загрузки.

Простой способ сделать это - отправить фальшивое сообщение. Вы должны быть уверены, что поддельное сообщение вызовет весь доступ к классам. Для exmaple, если вы отправляете пустое сообщение, но ваш прогром проверяет, пустое ли сообщение и избегает делать определенные вещи, тогда это не сработает.

Другой способ сделать это - принудительно инициализировать класс путем доступа к этому классу при запуске программы.

(2): Оптимизация в реальном времени: во время выполнения Java VM оптимизирует часть кода. Это основная причина, по которой время разминки.

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

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

Надеюсь, это поможет.

11

Ваша проблема не в загрузке классов, а в сборке «только вовремя».

Попробуйте -XX:CompileThreshold=1

Это заставит Java компилировать все в первый раз, когда он запускает его. Это несколько замедлит запуск вашего кода, но не код VM (поскольку он скомпилируется при установке Java). Существует ошибка, позволяющая Java скомпилировать пользовательские JAR аналогичным образом и сохранить результат для последующих исполнений, что значительно снизит эти накладные расходы, но в ближайшее время не будет необходимости исправлять эту ошибку.

Второй вариант заключается в том, чтобы отправить 5'000 фальшивых сообщений в приложение, чтобы «разогреть их». Продайте это как «убедившись, что все настроено правильно».

[EDIT] Некоторые справочную информацию в Прекомпиляция классах: Class Data Sharing

Вы можете попробовать версию IBM по Java, так как здесь, вы можете добавить несколько классов в разделяемом пуле: Overview of class data sharing

[edit2] Чтобы ответить на вопросы, поднятые kittylyst: Это правда, что это быстро заполнит ваш кеш кода методами, которые используются только один раз. И это может даже сделать все ваше приложение медленнее.

Если вы установите его на низкое значение, время запуска приложения может стать очень медленным. Это связано с тем, что оптимизация JIT + запуск скомпилированного кода дороже, чем запуск кода один раз в интерпретируемом режиме.

Основная проблема заключается в том, что код все еще компилируется «как раз вовремя». Пока вы не можете запускать каждый метод, который вам нужен хотя бы один раз, приложение будет «hickup» в течение нескольких миллисекунд каждый раз, когда оно встречает то, что ранее не было скомпилировано.

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

+1

+1 для снижения порога компиляции горячей точки. –

+0

Рекомендация: Изменить, чтобы добавить ссылку на фактический bugreport. –

+0

Где эта ошибка? У меня было это обсуждение с компилятором Sun, и он убедил меня, что это будет «очень сложно» и намного сложнее, что, по-видимому, указывает первый румянец. – Mainguy

3

Используете ли вы клиент или сервер JVM? Попробуйте начать свою программу с:

java -server com.mycompany.MyProgram 

При запуске JVM Sun в этом режиме JIT компилирует байт-кода в машинный код ранее; из-за этого программе потребуется больше времени для запуска, но после этого она будет работать быстрее.

Ссылка: Frequently Asked Questions About the Java HotSpot VM

Цитата:

Какая разница между -client и -Server систем?

Эти две системы представляют собой разные бинарные файлы. Это, по существу, два разных компилятора (JIT), взаимодействующие с одной и той же системой времени исполнения. Клиентская система оптимальна для приложений, которым требуется быстрое время запуска или небольшие отпечатки, серверная система оптимальна для приложений, где общая производительность является наиболее важной. В целом клиентская система лучше подходит для интерактивных приложений, таких как графические интерфейсы. Некоторые из других различий включают политику компиляции, значения по умолчанию для кучи и политику вложения.

+0

Он работает в режиме сервера по умолчанию, потому что он работает на машине «server-class» (16 ГБ) память, 8 ядер) – noahlz

+0

Хорошо, вы не сказали этого в своем вопросе выше. – Jesper

+0

сервер и клиентский режим оба делают JIT-компиляцию. Разница заключается в количестве вызовов фактического метода (3000 для клиента и 10000 для режима сервера). Кроме того, с 64-битной JVM режим сервера используется по умолчанию. – gyorgyabraham

-4

Похоже, ваш проект выиграет от реальных временных гарантий:

См: Real Time Java

+0

Нет, абсолютно нет. «Реальное время» - это согласованность ответа, а не абсолютная ценность. В реальном времени Java обычно работает значительно медленнее, чем обычная Java, но с уменьшенной дисперсией в профиле производительности. Обычно это не подходит для приложений с малой задержкой. – kittylyst

3

При работе в режиме сервера HotSpot на современных аппаратные средства (с 2-й или более ядрами на процессор) и с последней версией JDK то следующий вариант может быть использован для ускорения прогрева:

 
-server -XX:+TieredCompilation 
+0

По умолчанию включена опция TieredCompilation. Ссылка: http: //docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html – okwap

4

Просто запустите кучу не-оп сообщений через систему, прежде чем он открыл для подлинного покупательского трафика. 10k сообщений - это обычный номер.

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

Если протокол, который вы используете, является доморощенным, то при следующем обновлении библиотек добавьте явную поддержку типов сообщений WARMUP или TEST или SANITYCHECK.

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

+1

Да, это тот подход, который мы приняли. Но мы не спам на рынке. Мы создали фальшивые «петлевые» соединения. – noahlz

2

Старая нить, я знаю, но я нашел в интернете:

Очень интересная вещь, это влияние опционного-XX: CompileThreshold = 1500 для SUN HotSpot JVM. По умолчанию используется 10000 для VM сервера и 1500 для клиентской виртуальной машины. Однако установка его на 1500 для Server VM делает его быстрее, чем клиентская VM. Установка на 100 действительных значений снижает производительность. И использование опции-Xcomp (что означает, что весь код скомпилирован перед использованием) дает еще более низкую производительность, что удивительно.

Теперь вы знаете, что делать.