Любой рекомендуемый учебник по профилированию Java?

Есть ли рекомендуемый учебник профилирования приложений Java?

Теперь я использую JProfiler и Eclipse платформа тестирования и производительности инструмента (TPTP) с моим профилированием. Однако, хотя он оснащен прекрасным оружием, как кем-то новым для нового в профилировании Java, мне все еще не хватает общей теории и навыков в определении узкого места.

Ответ 1

Профилирование - предмет, имеющий более чем одну школу мысли.

Более популярным является то, что вы продолжаете получать измерения. То есть вы пытаетесь увидеть, как долго длится каждая функция и/или сколько раз она вызывается. Ясно, что если функция занимает очень мало времени, то ее ускорение мало выиграет. Но если это занимает много времени, то вам нужно выполнить детективную работу, чтобы выяснить, какая часть функции несет ответственность за время. Не ожидайте, что функциональные времена будут суммироваться до общего времени, потому что функции вызовут друг друга, а причина функции A может занять много времени, так это то, что она вызывает функцию B, которая также занимает много времени.

Этот подход может найти множество проблем, но это зависит от того, насколько вы являетесь хорошим детективом и умеете ясно мыслить о разных видах времени, например, о времени настенных часов и времени процессора, а также о времени автономной работы и времени включения. Например, приложение может показаться медленным, но время функции может быть указано как около нуля. Это может быть вызвано тем, что программа связана с I/O. Если I/O - это то, что вы ожидаете, это может быть хорошо, но может быть сделано некоторое количество операций ввода-вывода, о которых вы не знаете, и затем вы вернулись к детективной работе.

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

Другой подход - не измерять, а захватывать. Это основано на идее, что в то время, когда программа занимает больше времени (в режиме настенных часов), чем вы хотели бы, вы хотите знать, что она делает, в основном, и один из способов выяснить это - остановить ее и спросить, или сделать снимок своего состояния и проанализировать его, чтобы полностью понять, что он делает, и почему он делает это в тот конкретный момент времени. Если вы делаете это несколько раз, и вы видите что-то, что оно пытается делать в несколько раз, то эта деятельность - это то, что вы можете плодотворно оптимизировать. Разница в том, что вы не спрашиваете, сколько; вы спрашиваете, что и почему. Вот еще одно объяснение. (Обратите внимание, что скорость принятия такого снимка не имеет значения, потому что вы не спрашиваете о времени, вы спрашиваете, и почему.)

В случае Java вот один низкотехнологичный, но эффективный способ, или вы можете использовать кнопку "пауза" в Eclipse. Другой способ - использовать определенный тип профилировщика, который отображает весь стек вызовов, на время настенных часов (не CPU, если вы не хотите быть слепым к I/O), когда вы хотите, чтобы он пробовал (например, не при ожидании ввода пользователя) и суммирует на уровне строк кода не только уровень функций, а процент времени, а не абсолютное время. Чтобы получить процент времени, он должен сказать вам, что для каждой строки кода, которая появляется в любом образце, процент проб, содержащих эту строку, потому что, если вы можете сделать эту строку, вы сохраните этот процент. (Вы должны игнорировать другие вещи, которые он пытается рассказать вам, например, графики вызовов, рекурсия и самообслуживание.) Очень мало профилографов, которые соответствуют этой спецификации, но одна из них RotateRight/Zoom, но я не уверен, что он работает с Java, и могут быть и другие.

В некоторых случаях бывает сложно получить образцы стека, когда вы захотите, во время фактической медлительности. Затем, поскольку то, что вам нужно, это процентное соотношение, вы можете сделать что-либо для кода, который упростит выборки без изменения процентов. Один из способов - усилить код, обернув вокруг него временной цикл, скажем, 100 итераций. Другой способ - под отладчиком установить точку останова изменения данных. Это приведет к тому, что код будет интерпретироваться в 10-100 раз медленнее, чем обычно. Другой способ - использовать таймер будильника, чтобы уйти в течение периода медлительности, и использовать его для захвата образца.

При использовании метода захвата, если вы используете его многократно, чтобы найти и выполнить несколько оптимизаций, вы можете ожидать достижения почти оптимальной производительности. В случае большого программного обеспечения, где узкие места более многочисленны, это может означать существенные факторы. Люди на Qaru сообщили о факторах от 7x до 60x. Вот подробный пример 43x.

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

Ответ 2

Я использую Yourkit Java Profiler 11.0, и это очень хорошо для оптимизации памяти и мониторинга времени процессора. Кроме того, сайт yourkit имеет хорошую базу знаний и справки.

Ответ 3

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

Я не уверен, как работает интеграция Eclipse с JProfiler, поскольку я в основном использую NetBeans. Однако в NetBeans имеется представление "Снимок", в котором показана иерархия вызовов методов с временем выполнения, которые суммируются до 100%. Я ищу части иерархии, которые занимают (относительно) большие% от общего времени. Оттуда вы должны подумать о том, что делают эти методы, и что может заставить их быть медленными.

Например: я заметил, что метод, который вызывался часто, в целом занимал слишком много времени, чтобы завершить его, и был серьезным узким местом. Короче говоря, оказывается, что код проверял, присутствовал ли элемент в коллекции с использованием метода .contains(), а коллекция была связанным списком. Причина в том, что проблема связана с тем, что Linked Lists имеет временную сложность O (n) для таких функций, как .contains(). Исправление в этом случае было довольно простым, так как я смог заменить Linked List на Hash Set, который выполняет .contains() намного быстрее, в течение O (1).

Ответ 4

В JProfiler входит инструкция по эксплуатации. Я обнаружил, что это очень хорошо.

Ответ 5

Вы можете найти интересную книгу Java Platform Performance. Опубликовано Sun Microsystems.