Как оптимизировать JVM и GC с помощью нагрузочного тестирования - PullRequest
6 голосов
/ 05 января 2012

Редактировать : из нескольких чрезвычайно щедрых и полезных ответов, которые этот вопрос уже получил, для меня очевидно, что я не прояснил важную часть этого вопроса, когда задавал его ранее сегодня утром , Ответы, которые я получил до сих пор, касаются оптимизации приложений и устранения узких мест на уровне code . Я знаю, что это гораздо важнее, чем пытаться получить дополнительные 3–5% от вашей JVM!

В этом вопросе предполагается, что мы уже сделали практически все, что могли, для оптимизации архитектуры нашего приложения на уровне кода. Теперь мы хотим большего, и следующее место, которое нужно посмотреть, это уровень JVM и сборка мусора; Я изменил название вопроса соответственно. Еще раз спасибо!

<Ч />

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

Компоненты находятся внутри файлов WAR, развернутых на серверах Tomcat. Всего в конвейере около 20 компонентов, работающих на 5 разных серверах Tomcat (я не выбирал архитектуру или распределение WAR для каждого сервера). Мы используем Apache Camel для создания всех маршрутов между компонентами, эффективно формируя «соединительную ткань» трубопровода.

Меня попросили оптимизировать сборщик мусора и общую производительность каждого сервера, на котором работает JVM (всего 5). Я провел несколько дней, читая GC и настройку производительности, и довольно хорошо разбираюсь в том, что делает каждый из различных вариантов JVM, как организована куча и как большинство параметров влияют на общую производительность JVM. .

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

Для меня имеет смысл оптимизировать весь конвейер в целом. Итак, мой первый вопрос: согласен ли ТАК, и если нет, то почему?

Чтобы сделать это, я думал о создании LoadTester, который генерировал бы ввод и передавал его в первую конечную точку в конвейере. Это LoadTester может также иметь отдельный « Monitor Thread », который будет проверять пропускную способность последней конечной точки. Затем я мог бы выполнять все виды обработки, где мы проверяем среднее сквозное время прохождения сообщений, максимальную пропускную способность до сбоя и т. Д.

LoadTester будет генерировать один и тот же шаблон входных сообщений снова и снова. Переменная в этом эксперименте будет опциями JVM, передаваемыми опциям запуска каждого сервера Tomcat. У меня есть список из примерно 20 различных вариантов, которые я хотел бы передать JVM, и решил, что смогу просто настроить их значения, пока не найду почти оптимальную производительность.

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

Второй вопрос: Что ТАК думает об этой настройке? Как SO может создать «оптимизирующее решение» иначе?

И последнее, но не менее важное: мне любопытно, какой тип метрик я мог бы использовать в качестве основы для измерения и сравнения. Я действительно могу думать только о:

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

Есть еще кто-нибудь? Какие-либо причины, почему эти 2 плохо?

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

Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 05 января 2012

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

Шаг 1. В каждом процессе я использовал эту технику , чтобы избавиться от расточительных действий. Это заняло несколько дней выборки, пересмотра кода и повторения. Идея в том, что есть цепочка, и первое, что нужно сделать, это устранить неэффективность ссылок.

Шаг 2. Эта часть трудоемка, но эффективна: создание временных меток журналов трафика сообщений. Объедините их вместе в общий график. Посмотрите внимательно на конкретные последовательности сообщений. То, что вы ищете, это

  1. Было ли сообщение необходимым или это была повторная передача в результате тайм-аута или другой причины, которую можно избежать?
  2. Когда сообщение было отправлено, получено и обработано? Если существует значительная задержка между получением и действием, в чем причина этой задержки? Было ли это просто вопросом нахождения в очереди за другим процессом, который, например, выполнял ввод-вывод? Может ли это быть исправлено с другими приоритетами процесса?

Это занятие заняло у меня около дня, чтобы сгенерировать логи, объединить их, найти возможность ускорения и пересмотреть код. При такой скорости примерно через 10 рабочих дней я обнаружил / исправил ряд проблем и значительно улучшил скорость .

Что общего в этих двух шагах, я не измеряю и не пытаюсь получить «статистику». Если что-то тратит слишком много времени, этот факт подвергает его усердному программисту, который внимательно и внимательно смотрит на происходящее.

0 голосов
/ 05 января 2012

Самая большая хитрость, которую я знаю, когда запускаю несколько JVM на одной и той же машине, это ограничение количества ядер, которые будет использовать GC.Иначе, что может случиться, когда одна JVM выполняет полный GC, это попытается захватить каждое ядро, влияя на производительность всех JVM, даже если они не выполняют GC.Одним из предложений является ограничение количества потоков gc до 5/8 или менее.(Я не могу вспомнить, где это написано)


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

Изменение параметров командной строки полезно, если вы не можете изменить код.Однако, если вы профилируете и оптимизируете код, который вы можете значительно изменить, чем настраивать параметры GC (в этом случае вам необходимо изменить их снова)

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

0 голосов
/ 05 января 2012

Я бы начал с нахождения оптимальных рекомендуемых значений jvm, указанных для вашего аппаратного / программного комплекса, ИЛИ просто начал с того, что уже есть.

Далее я бы позаботился о том, чтобы у меня был мониторинг для измерения Бизнеса.пропускные способности и соглашения об уровне обслуживания

Я бы не пытался настраивать только GC, если для этого нет оснований.

Сначала вам нужно найти основные узкие места в вашем приложении.Если это связано с вводом / выводом, связано с SQL и т. Д.

Ключевым моментом здесь является ИЗМЕРЕНИЕ, ИДЕНТИФИКАЦИЯ TOP узких мест, ИСПРАВЛЕНИЕ их и проведение еще одной итерации с повторяющейся загрузкой.1011 *

...