#java #measurement #execution-time #jvmti
#java #измерение #время выполнения #jvmti
Вопрос:
Для профилировщика, который я реализую с использованием JVMTI, я хотел бы начать измерять время выполнения всех методов Java. JVMTI предлагает события:
MethodEntry
MethodExit
Таким образом, это было бы довольно легко реализовать, однако я наткнулся на это примечание в API:
Включение событий входа или выхода метода значительно снизит производительность на многих платформах и, таким образом, не рекомендуется для критически важных применений (таких как профилирование). В этих случаях следует использовать инструментарий байт-кода.
Но мой агент профилирования работает без головы, что означает, что собранные данные сериализуются и отправляются через сокет в серверное приложение, отображающее результаты. Как я должен реализовать это с помощью инструментария байтового кода. Я немного запутался, как действовать дальше. Может ли кто-нибудь объяснить мне, нужно ли мне менять стратегию или как я могу подойти к этой проблеме?
Комментарии:
1. Звучит так, как будто вы хотите создать свой собственный профилировщик. Я бы посоветовал вам посмотреть, как работают существующие профили, такие как VisualVM и YourKit, чтобы увидеть, не делают ли они того, что вам уже нужно.
2. Они делают, я просто хочу сделать это сам. Но VisualVM может быть подсказкой, чтобы увидеть, как они это делают, но я обоснованно предполагаю, что они используют Java agent, а не собственный агент.
3. VisualVM использует Java-агент, для которого вы можете получить исходный код. YourKit использует собственный агент, для которого вы не можете получить исходный код. Записать данные не так сложно, как получить правильную визуализацию данных. Я бы посмотрел, как YourKit выполняет свою визуализацию.
4. Визуализация — это следующий шаг, я имею в виду, что я мог бы использовать именованные события JVMTI MethodEntry и MethodExit, чтобы увидеть, насколько велика разница без инструментария, однако я все равно хотел бы сделать это правильно. Пока я не вижу, как я могу использовать метод класса для сбора данных и отправки этих данных в сокет, так же, как я делаю это в машинном коде прямо сейчас.
5. Я думаю, что у вас будет много проблем с решением, которое, вероятно, будет не таким хорошим, как профессиональное, однако… Когда вы создаете агент, вы можете определить,
premain
которому передаетсяInstrumentation
, который получает весь байт-код каждого загруженного класса. Его также можно использовать для повторной загрузки классов позже. Вы можете использовать библиотеку, подобную ObjectWeb ASM, чтобы изменить байтовый код для вставки в код для таймеров / счетчиков методов, полей и т.д. (все, что вам нравится) И сохранить это в структуре данных POJO, которую вы можете отправить через обычный сокет.
Ответ №1:
Я не знаю о Sun JVM, но IBM JVM переходит в то, что мы называем режимом FullSpeedDebug, когда вы запрашиваете события MethodEntry / Exit…. FSD значительно замедляет выполнение.
Как вы говорите, вы можете использовать BCI, как это делает мой профилировщик, но если вы не будете выбирать, какие методы вы используете, вы также увидите замедление. Например, мой профилировщик вставляет if (профилирующий) вызовprofilerhook() для каждой записи и всех возможных выходов в метод, создаваемый всеми объектами, а также в некоторые другие области…. Эти дополнительные проверки могут замедлить выполнение более чем на 50%…
Что касается того, как использовать BCI … ну, я написал свою собственную библиотеку C, чтобы сделать это … технически это не сложно (подсказка просто удалите StackMapTable), но это может занять у вас некоторое время.. В качестве альтернативы вы можете использовать ASM и др.
Наконец… ваш обратный вызов добавит накладных расходов и при небольших методах сделает сообщаемое время процессора / тактовой частоты бессмысленным, если вы не выполните какое-либо сложное вычисление накладных расходов … даже если вы сделаете это, ваш код обратного вызова повлияет на форму кэша процессора L1, и Java-код станет менее эффективным, потому что в нем меньше места..
Мой профилировщик в основном игнорирует указанное время, поскольку я визуализирую выполнение интересным способом… Я хочу понять поток всего кода, фактически в большинстве случаев какой код выполняется (большинство проектов Java понятия не имеют о миллионах строк стороннего кода, запущенного в их приложении)
Комментарии:
1. Привет, еще раз спасибо за советы, которые вы дали мне в другом вопросе здесь, в stackoverflow, это действительно помогло моему проекту сдвинуться с мертвой точки. Мне действительно нравится ваша аргументация, и я думаю, что это тот момент, который я уловлю. Поскольку я хотел бы измерить, где тратится больше всего времени, а не сколько времени точно требуется методу. Таким образом, вы могли бы сказать, что MethodEntry и MethodExit все еще можно использовать? Кстати, мой проект теперь можно найти на: github.com/platzhirsch/Profiling-Concurrency