Почему VisualVM Sampler не предоставляет полную информацию о загрузке процессора (метод выполнения времени)? - PullRequest
15 голосов
/ 15 ноября 2011

Проблема в том, что сэмплер VisualVM показывает дерево вызовов по времени.Для некоторых методов сэмплер показывает только «Self time», поэтому я не вижу, что делает этот метод медленным. Вот пример .
Как увеличить глубину профилирования?

Ответы [ 2 ]

44 голосов
/ 19 февраля 2012

К сожалению, профилировщики выборки довольно ограничены, когда дело доходит до углубленного профилирования по ряду причин:

  • Выборщики ограничены периодом выборки: Например, VisualVM в настоящее время имеет минимальный период выборки 20 мс. Современные процессоры могут выполнить несколько миллионов инструкций за это время - безусловно, более чем достаточно для вызова нескольких коротких методов и возврата из них.

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

  • Сэмплеры легко путаются с помощью встроенного кода: И JVM, и любой приличный компилятор будут встроять тривиальные и / или часто вызываемые методы, таким образом, включая свой код в код своего вызывающего. Профилировщики выборки не могут определить, какие части каждого метода действительно принадлежат ему, а какие - встроенным вызовам.

    В случае VisualVM Собственное время фактически включает время выполнения как метода , так и любого встроенного кода.

  • Сэмплеры могут быть сбиты с толку продвинутой виртуальной машиной: Например, в современных реализациях JVM методы не имеют стабильного представления. Представьте, например, следующий метод:

    void A() {
        ...
        B();
        ...
    }
    

    Когда JVM запускается, B() интерпретируется прямо из байт-кода, что занимает довольно много времени, что делает его видимым для сэмплера. Затем, через некоторое время JVM решает, что B() является хорошим кандидатом для оптимизации, и компилирует его в собственный код, что делает его намного быстрее. И еще через некоторое время JVM может решить встроить вызов в B(), включив его код в A().

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

    В худшем случае эта стоимость может быть отнесена к вызову одного брата, а не к вызывающему абоненту. Например, в настоящее время я профилирую приложение с использованием VisualVM, где точка доступа кажется методом ArrayList.size(). В моей реализации Java этот метод представляет собой простой метод получения полей, который любая JVM должна быстро встроить. Тем не менее, профилировщик показывает, что он является основным потребителем времени, полностью игнорируя кучу ближайших HashMap вызовов, которые, очевидно, намного дороже.

Единственный способ избежать этих недостатков - использовать инструментальный профилировщик, а не выборочный. Инструментальные средства профилирования, такие как вкладка, предоставляемая вкладкой Profiler в VisualVM, по существу записывают каждую запись и выход каждого метода в выбранном коде. К сожалению, профилировщики инструментов оказывают довольно сильное влияние на профилированный код:

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

  • Они вызывают массовое замедление работы профилированного кода, что делает их совершенно непригодными для мониторинга завершенных приложений.

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

1 голос
/ 15 ноября 2011

В этом примере нет ничего плохого.Похоже, что updateInfoInDirection() звонит new SequenceInfo() и SequenceInfo.next().«Собственное время» означает, что время тратится в коде самих методов (метод updateInfoInDirection() находится в нижней части стека во время взятия пробы потока).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...