Разное

Java профайлер: Do It Yourself Java Profiling / Хабр

Содержание

Do It Yourself Java Profiling / Хабр

На прошедшей конференции Appication Developer Days, Роман Елизаров (elizarov) рассказал, как профилировать, т.е. исследовать производительность любых Java-приложений, без использования специализированных инструментов, будь они хоть вендорские, хоть open-source.Оказывается, можно использовать малоизвестные, встроенные в JVM возможности (threaddumps, java agents, bytecode manipulation), и быстро и эффективно реализовать профилирование, которое можно запускать постоянно даже на боевой системе.Вот видео доклада (тут оно косолапо эмбедится, но оно 1280×720, все отлично читаемо):

Но я предлагаю также, взглянуть на 70K текста иллюстрированной статьи-стенограммы под катом, составленной мной по видео и слайдам.
У меня сегодня будет доклад про «Сделай себе сам профилирование на Яве». Слайды будут на английском, доклад я буду делать на русском. Слайдов очень-очень много, а времени не так много, поэтому я буду какие-то очень быстро проскакивать, и постараюсь оставить больше времени в конце на вопросы, и может быть даже где-то в середине. В принципе, не стесняйтесь, если захочется вдруг что-то спросить или уточнить, и даже меня прервать. Я лучше подробнее освещу то, что вам интересно, чем буду просто рассказывать то, что я хотел рассказать.

Доклад основан на реальном опыте, мы в компании больше десяти лет занимаемся созданием сложных, очень высоконагруженных финансовых приложений, работающих с большими массивами данных, с миллионами котировок в секунду, c десятками тысяч пользователей онлайн, и там, при такой работе, всегда речь идет о профилировании приложения. Профилирование приложения — неизбежный компонент любой оптимизации, оптимизация без профилирования невозможна. Вы профилируете, находите узкие места, оптимизируете-профилируете, это постоянный цикл. Почему доклад называется «Do It Yourself Java Profiler», зачем что-то делать самому? Есть же огромное количество готовых инструментов, которые помогают профилировать — собственно профилировщики, и подобные инструменты.

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

Мы, когда пишем финансовые приложения, у нас есть еще задача обеспечить надежность системы. И мы делаем не «банки», где главное — не потерять ваши деньги, но которые могут быть часами недоступны. Мы делаем брокерские системы онлайн-торговли, где постоянно 24×7 доступность систем, это одна из ключевых их качеств, они никогда не должны падать.

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

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

Причем даже если инструмент с открытым кодом, это ничего не меняет, потому что этого кода много, вы убъете кучу времени в нем разбираясь. Инструменты надо учиться, а делать что-то самому, конечно, намного приятней. В чем проблема с изучением? Естественно, если вы используете какой-то инструмент часто, то стоит его учить. Если вы программируете каждый день в какой-то любимой вами среде разработки, вы ее знаете вдоль и поперек, и это знание, естественно, окупается вам сторицей.

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

Делая что-то своими руками, вы можете переиспользовать ваши знания. Например, у вас есть знания языков программирования, своих инструментов, вы можете их углубить, расширить, уточнить, глубже изучив те инструменты, которые у вас уже есть, вместо изучения нового. Почему доклад о Java? Ну мало того, что наша компания программирует на Java, это ведущий язык 2001 года по индексу TIOBE, отлично подходит для enterprise приложений. А для данной конкретной лекции вообще замечательно — потому что Java — это managed язык, работает в виртуальной машине, и именно профилирование в Java делается очень легко. Я буду рассказывать во-первых, просто о том, как решить многие проблемы профилирования, написав некий код на Java. Скажу о возможностях Java-машин, которые можно использовать, и расскажу о такой технике, как манипулирование байт-кодом. Мы посмотрим сегодня на профилирование как CPU, так и памяти. Я расскажду про разные техники. Профилирование CPU. Самый простой способ, это просто взять и запрограммировать. Если вам нужно разобраться, куда, сколько, чего, в вашей программе занимает времени, и сколько раз вызывается, то самый-самый простой способ: не надо никаких инструментов, ничего — написать просто несколько строчек кода.

В Java есть замечательная функция «currentTimeMillis», которая возвращает текущее время. Можно ее замерять в одном месте, замерять в другом, а дальше можно посчитать, сколько раз это сделано, суммарное время, минимальное и максимальное время, все что угодно. Самый такой простой способ. DIY в своей максимальной простоте и примитивизме.

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

В этом смысле, запрограммировать приложение, чтобы оно само себя профилировало, является логичным шагом. Вы увеличиваете функционал приложения, профилирование приложения становится частью его функционала. Особенно, если таким образом вы расставляете определения в ваших бизнес-методах, которых конечный пользователь вызывает, то конечному пользователю эта информация тоже будет осмысленна. Сколько раз и какие методы вызывались, сколько по времени отрабатывали и так далее. Информация, которую вы собираете, в данном случае, при данном подходе, полностью под вашим контролем. Можете замерять количество вызовов, минимальное время, максимальное время, среднее считать, можете строить гистограммы распределения времени выполнения, считать медианы и персентили. Можете разные пути исполнения в коде отслеживать по разному, как в этом примере, кто успел разглядеть, пока я говорил, обратил внимание, что в зависимости от пути исполнения, мы записываем разную статистику: как часто результат запроса попал в кеш, и сколько времени это заняло, и как часто запросу пришлось лезть в базу данных, и сколько времени это заняло. Это возможно, если вы этот код пишете сами, собираете статистику, встраиваете сами в свое приложение. Более того, вам, как человеку, который занимается циклом профилирования-оптимизации, вы потом эту информацию используете — что же в вашем приложении происходит? Эта информация всегда находится внутри вашего приложения, код работает в живой системе. У вас произошел какой-то неудачный день, что-то система не так работала, вы можете посмотреть в логах эту статистику, разобраться, и так далее.

Замечательная методика, нет никаких сторонних инструментов, только немножко кода на яве.


Что же делать, если методы короче, и вызываются чаще?

Дело в том, что такой прямой метод уже не подойдет, потому что метод «currentTimeMillis» не быстрый, и меряет только в миллисекундах. Если вам нужно замерить только количество вызовов, то достаточно быстро можно это сделать используя Java-класс «AtomicLong». С его помощью, вы можете, внося минимальный вклад в производительность, посчитать количество вызовов какого-нибудь интересующего вас метода. Это будет работать до десятков тысяч вызов в секунду, не сильно искажая работу самого приложения. Что же делать, если вам нужно еще замерить время выполнения? Замер времени исполнения коротких методов — это очень сложная тема. Стандартными никакими методами она не решается, несмотря на то, что в Java есть метод «systemNanoTime», он эти проблемы не решает, он сам по себе медленный, и с помощью него что-то быстрое сложно замерить.

Единственный реальный выход — это использовать нативный код, для x86 процессора есть такая замечательная инструкция rdtsc, которая возращает счетчик количества тактов процессора. Напрямую к ней доступа нет, можно написать на C однострочный метод, который вызывает «rdtsc», а дальше слинковать его с Java-кодом, и вызывать из Java. Этот вызов вам займет сто тактов, и если вам нужно замерить кусок кода, который занимают тысячу-другую тактов, то это осмысленно, если у вас идет оптимизация каждого машинного такта, и вы хотите понять, «плюс-минус», «быстрее-медленнее», как вы работаете. Это действительно редкий случай, когда вам нужно оптимизировать каждый такт.

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

Такое место в программе называется «горячей точкой». Это всегда замечательный кандидат для оптимизации. Что классно — есть встроенная фукнция под названием «thread dump», чтобы получить дамп всех потоков. В Windows она делается путем нажатия CTRL-Break на консоли, а на Linux и других юниксах это делается посылкой третьего сигнала, командой «kill -3». В этом случае, Java-машина на консоль выводит подробное описание состояния всех потоков. И если у вас действительно есть горячее место в коде, то скорее всего программу там и застанете. Поэтому опять же, когда у вас проблема производительности с кодом, не надо бежать к профилировщику, не надо ничего делать. Видите, что тормозит, сделайте хоть один thread dump, и посмотрите. Если у вас одно горячее место, в котором программа тратит все время, вы в thread dump и увидите эту строчку, в своей любимой среде разработки, без использования каких-нибудь сторонних, дополнительных инструментов. Посмотрите этот код, изучите, оптимизируйте — либо он слишком часто вызывается, либо он медленно работает, дальше уже разбор полетов, оптимизация, либо дальнейшее профилирование. Также в современных Java-машинах есть замечательная утилита «jstack», ей можно передать идентификатор процесса, и получить на выходе thread dump.

Сделайте не один thread dump, сделайте несколько thread dumpов. Если первый ничего не выловит, посмотрите еще на пару-тройку. Может у вас в горячей точке не сто процентов времени программа проводит, а 50%. Сделав несколько thread dumpов, вы явно в хоть какой-то из этих моментов, достанете ваш код из горячей точки, и глазками посмотрите те места, где вы застали ваш код. Эту идею можно развить дальше. Можно, запустив ява-машину, перенаправить ее выход в файл, и запустить скрипт, который делает thread dump каждые три секунды. Это можно делать совершенно спокойно на живой системе, без какого либо риска что-то с ней сделать. Потому что сам сбор thread dump досточно быстрая процедура, занимает от силы 100 миллисекунд, даже при очень большом количестве тредов.

А если вы пишите на яве, то скорее всего ваша система не hard real time, и вам там наносекунды не важны, потому что у вас уже периодически встречается сборка мусора и так далее. Т.е. вам лишнее засыпание системы на сто миллисекунд катастрофы не создает.

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

Поэтому можно не переживать о лишних ста миллисекундах, и раз в три секунды делать thread dump, можно совершенно безопасно, даже на живой системе. При этом thread dump, это часть java-машины, хорошо оттестированная — я за весь свой опыт работы ни разу не видел, чтобы попытка сделать на Java-машине thread dump сделала с ней что-то плохое.

Т.е. это совершенно безопасный инструмент профилирования живых и работающих систем. После этого, получив файл thread dump, его можно посмотреть глазками, а можно написать несложный кусок кода, который анализирует, считает какие-нибудь статистики → хотя бы тупо, посмотреть, какие методы проявились и сколько раз, посмотреть, в каком состоянии находились потоки. При этом если стандартные инструменты профилирования, действительно смотрят на состояние потока, которое выводит Java-машина («RUNNABLE»), то в реальности, ваше состояние ни о чем не говорит, потому что если ваша программа много работает с базой данных, и много работает с какими-то внешними… сетью, то ваш код может ожидать получение данных по сети, при этом java-машина его считает «RUNNABLE», и вы ничего не сможете понять — какие у вас реально методы, и какие ждут данных от сети. С другой стороны, если вы сами анализируете стеки, — вы можете написать, вы-то знаете, что ваша программа делает, что вот это — вызов в базу данных, что этот метод в стеке означает, что вы вошли в базу данных, можете посчитать, сколько процентов времени вы проводите в базе данных, и так далее, тому подобное. Вы можете знать, что вот этот метод на самом деле CPU не жрет, хотя java-машина думает, что он «RUNNABLE». Более того, thread dump можно интегрировать в приложения, в Java есть замечательный метод

Thread.getAllStackTraces 

который позволяет получить информацию о stacktrace программно.

Таким образом, вы можете интегрировать профилирование, как функциональную часть этого приложения, и распространять приложение вашим клиентам, с уже встроенным профилированием. Тем самым, у вас будет постоянный поток информации, который вы сможете анализировать для улучшения вашего приложения. Но есть проблема. Дело в том, что когда вы Java-машину просите сделать thread-dump, она не просто процесс останавливает, и делает стек, она включает флажок, что ява-машине надо бы остановится в следующем безопасном месте. «Безопасное место» — это специальные места, которые расставляет компилятор по коду, где у программы есть определенное состояние, где понятно, что у нее в регистрах, понятна точка исполнения, и так далее. Если брать кусок последовательного кода, где нет никаких обратных переходов, никаких циклов, то там «safe point» может не оказаться вообще. Причем неважно, что вызовы методов могут заинлайнится hotspot-ом, и savepoint-ов тоже не будет.

Поэтому если вы видите в thread dumpe какую-то строчку — это совершенно не значит, что это горячая строчка вашего кода, это просто ближайший savepoint к горячей точке. Потому что когда вы нажимаете «CTRL-BREAK», Java всем потокам выставляет флажок «остановиться на ближайшем savepointе», и только когда они останавливаются, Java-машина анализирует, в каком состоянии они это делают. Теперь перейдем к профилированию памяти, как это делается.

Во-первых, есть замечательные, готовые фичи Java-машина. Есть отличный инструмент jmap, который выводит гистограмму того, чем у вас забита память, какие объекты и сколько памяти занимают. Это замечательный инструмент для общего обзора, что же у вас происходит, и чем забита память.

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

Поэтому у jmap есть специальная опция «live», которая перед тем, как сделать гистограмму делает сборку мусора, оставляет только используемые объекты, и только после этого строит гистограмму.

Проблема, что уже с этой опцией, большую, живую систему работающую с многими гигабайтами памяти, запрофилировать нельзя, потому что сборка мусора системы, работающей с десятком гигабайт памяти занимает десяток-другой секунд, и это может быть неприемлимо… в любой системе, если ваша система работает с конечными людьми, человек, которому система дольше трех секунд не отвечает, считает, что она зависла. Нельзя живую, работающую с человеком систему останавливать дольше чем на секунду, на самом деле. Даже секунда уже будет человеку заметна, но еще не катастрофа, но если вы подключите какой-то инструмент, который остановит на 10 секунд — то это будет катастрофа. Поэтому часто приходится довольствоваться на живых системах jmap-ов тех объектов, которые есть, и в целом, неважно, мусор это или нет.
Также дополнительно полезно знать дополнительные опции Java-машин. Например, у Java-машин можно попросить отпечатать гистограмму классов, когда вы делаете thread dump → «PrintClassHistogram».

Ява-машину можно попросить при исчерпании памяти записывать свое состояние на диск. Это очень полезно, потому что обычно, люди начинают оптимизировать потребление памяти только тогда, когда она заканчивается почему-то. Никто не занимается профилированием, когда все хорошо, а вот когда программе начинает памяти не хватать, она вылетает, начинают думать, как бы так соптимизировать. Поэтому это опцию полезно всегда иметь включенной. Тогда в плохом случае Java-машина вам запишет бинарный дамп, который вы можете потом, не на живой системе, любыми инструментами проанализировать. При этом, этот дамп можно в любой момент взять с Java-машины, тем же jmap-ом, с опцией «-dump», но это, опять же, останавливает Java-машину на долгое время, на живой системе вы это вряд ли заходите делать.

Реплика из зала: Там есть свойство, что этот «HeapDumpOutOfMemory» оптимизирован для тех случаев, когда память уже кончилась.

Да, конечно. «HeapDumpOutOfMemory» очень полезная опция, причем хотя она «-XX», не надо этих опций бояться, хотя этот «XX» подчеркивает их мегаспециальность, но это не экспериментальные опции, это нормальные production-опции ява-машины, они стабильные, надежные, их можно использовать на живой, реальной системе.

Это не экспериментальные опции! В java-машине есть четкое деление, но деление на экспериментальные и неэкспериментальные опции не зависит от числа X-ов.

Реплика из зала: Эта опция иногда не откладывают дампы…

Ну, в java-машине тоже бывают баги, все зависит от того, … бывают разные причины исчерпания памяти, я не буду на этом останавливаться, у нас времени мало. Я хочу остановится на очень важном моменте, в оставшееся время, а именно, на профилировании выделения памяти.

Одно дело — чем память занята, как вы ее вообще используете. Если у вас где-то в коде есть излишнее выделение временной памяти, т.е. вы выделяете, … что-то с ним делаете, этом методе и потом забываете, он уходит в мусор, и garbage collector потом его забирает. И так вы делаете снова и снова, ваша программа будет работать медленнее, чем бы она работала с этим … но вы никаким профилировщиком по CPU это место кода не найдете, потому что сама операция выделения в Java-машине памяти, работает фантастически быстро, быстрее, чем в любом не-managed языке, C/C++, потому что в Java выделение памяти это банально увеличение одного указателя. Все. Это несколько ассемблерных инструкций, все очень быстро происходит. Она уже предварительно обнулена, все уже выделено и подготовлено. Вы этого времени при анализе горячих точек вашего кода не найдете — оно не высветится у вас никогда, ни в каком thread dumpe, ни в каком профилировщике, что это у вас горячая точка. Хотя у вас это все будет жрать ваше время, работы вашего приложения — почему? Потому что потом, сборщик мусора будет тратить время, чтобы этот мусор собрать. Поэтому смотрите, на то, сколько процентов времени ваше приложение тратит на сборку мусора.

Это полезная опция «-verbose:gc», «+PrintGC», «+PrintGCDetails», которые позволят вам разобраться, сколько времени вашего приложения уходит на сборку мусора. Если вы видите, что на сборку мусора уходит существенный процент времени, значит вы где-то в программе много выделяете памяти, вы это место не найдете, нужно искать, кто выделяет память. Как искать? Есть встроенный в Java-машину способ, ключик «-Xaprof». Он вам, к сожалению, только при завершении процесса, выводит так называемый allocation profile, который говорит не о содержимом памяти, а о статистике выделяемых объектов → какие объекты и как часто выделялись.

Если у вас это действительно часто происходит, вы скорее всего увидите, что где-то заведен какой-то временный класс, который действительно очень часто выделяется. Попробуйте сразу сделать «aprof» — может вы сразу найдете вашу проблему. Но не факт. Может получится ситуация, что вы увидите выделения большого количества массивов character-ов, каких-то string-ов, или чего-нибудь, и непонятно где.

Понятно, что у вас могут быть подозрения — где. Может какое-нибудь недавнее изменение, это могло внести. В конце-концов, вы можете добавить в том месте, где выделяется память слишком часто, используя ту же технику изменерения кода в atomiс longах, посчитайте, сколько раз в этом месте происходит выделение — посмотрите статистику, подозрительные места вы сами сможете проинициировать и найти.

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

Я сейчас за оставшееся время попробую остановится как раз на технике манипуляции байт-кодом, которая как раз подходит, для решения задач типа «вот я хочу во всех местах, где выделяется массив, посчитать, сколько раз в этом месте это происходит, по всему своему коду, чтобы найти то самое место, в котором я почему-то очень много массивов int-ов выделяю». Т.е. я вижу, что их много выделяется, но я просто хочу найти где. Манипулирование байткодом позволяет не только эти задачи решить, она позволяет любые изменения, нефункциональные, в код вносить, уже после его компиляции. Тем самым, этот способ декомпозировать профилирование от бизнес-логики. Если в начале я говорил, что часто профилирование может быть логичной частью вашего функционала, то бывают случаи, когда это не нужно, когда вам нужно найти проблему, решить, и чтобы никаких строк не осталось. В этом случае подходит такая замечательная техника, как манипулирование байт-кодом.

Причем это можно делать как с посткомпиляцией выкладки кода, так и на лету, с кодом. Самый лучший способ, который я знаю, это использовать библиотечку ASM, ObjectWebовскую. Это open-source библиотека, которая позволяет очень легко заниматься манипуляцией байткодом, и она фантастически быстрая — можно манипулировать кодом на лету, не сильно замедляя время загрузки приложения.

ASM устроен очень просто. У него есть класс под названием class-reader, который читает .class-файлы, и преобразовывает байтики, используя шаблон Visitor, в набор вызовов вида «я вижу метод», «я вижу поле с такими-то полями в этом классе» и так далее. Когда он видит метод, он начинает с помощью «MethodVisitor» сообщать, какой он там видит байт-код.

А потом есть, с другой стороны, такая штука, как «ClassWriter», который наоборот, превращает класс в массив байтиков, который нужен ява-машине. Чтобы например, с помощью ASM-а, отследить все выделения массивов… в-общем, это делается примитивно. Вам нужно всего парочку классов сделать. Вам нужно определить свой класс-адаптер, который, когда ему говорят, что виден метод, перекрывает, и возвращает свой собственный метод-visitor, чтобы оузнать, что в этом методе происходит.

А когда внутри метода ему говорят, что вот, есть целочисленная инструкция с байт-кодом выделения массива («NEWARRAY»), то в этот момент, он имеет возможность … вставить свои какие-нибудь байткоды в восходящий поток и все. И вы отследили все места, где у вас выделяются массивы, и поменяли соответствующий байт-код. Дальше — что делать, если вы хотите эти изменения делать на лету.

Если у вас есть набор скомпилированных классов — то это легко → вы как бы обработали этим инструментом, и все.

Если вам это нужно делать на лету, то в java-машине есть замечательная опция — javaagent. Вы делаете специальный jar-файл, у которого в манифесте указываете опцию «Premain-Class», и указываете там имя своего класса. Потом … метод «premain» по определенному шаблону, и тем самым, вы еще до запуска основного кода, c main-методом, получаете управление, и получаете указатель на interface instrumentation. Этот интерфейс замечательный, он позволяет вам, на лету, менять классы в java-машине. Он позволяет вам поставить свой собственный class-file трансформер, который Java-машина будет вызывать для каждой попытки загрузки класса.

И вы сможете классы подменять. Т.е. загружать не только те классы, которые на самом деле лежат, а с помощью того же ObjectWebASM, анализировать что-то, менять, и подменять их на лету… можете узнать размер выделенного объекта.

Замечательный инструмент такого профилирования на коленке, когда у вас есть конкретная задача, которую нужно решить. В завершении скажу, что совершенно не обязательно, для решения каких-то задач профилирования владеть каким-нибудь инструментом, достаточно знать байт-код, знать опции ява-машины, и знать стандатные ява-библиотеки, тот же javalang-инструмент. Это позволяет решить огромное число специфичных проблем, с которыми вы сталкиваетесь. Мы за десять лет у себя в компании разработали несколько доморощенных инструментов, которые решают проблемы не специфичные нам, которые не решают специфичные профилировщики. Начиная с того, что у нас в процессе работы появился развесистый, но тем не менее простой инструмент который анализирует thread dump, и выдает по ним статистику, это тем не менее простая утилитка, которую нельзя назвать инструментом. Классик на несколько страничек, который собирает статистику и выдает ее в красивом виде. Дико полезен, потому что нам не надо в production систему подключать какие-то профилировщики, просто thread dump, и все…

И кончая тем, что у нас есть свой собственный инструмент профилирования памяти, который опять же, маленький, его сложно назвать инструментом, который отслеживает, где и что выделяется, причем делает он это, практически не замедляя программы. Причем как коммерческие, так и открытые профилировщики, они тоже умеют отслеживать выделение памяти, но они пытаются решить проблему более сложную, и универсальную. Они пытаются узнать, в каком месте выделение памяти происходит, с полным stack-trace’ом. Это долго, это сильно замедляет. Не используют то же семплирование. Не всегда собирают, тем самым получая не всю статистику, и так далее.

Идут на какие-то свои компромиссы, которые в вашей предметной области, они вам не нужны, у вас есть какие-то свои задачи, которых вы хотите решить при анализе производительности ваших систем.

Теперь я будут отвечать на вопросы (ответы на вопросы с 30:06).


Также можно посмотреть другие статьи-стенограммы с application developer days, скачать все видео с прошедших конференций торрентами ([2011], [2010]) или всю папку по http.


Disclaimer еще раз: Я не автор доклада. Я председатель ПК этой конференции, видео-монтажер, и составитель стенограммы. У автора нет хабрааккаунта, возможно со временем мне удастся его пригласить, например, для комментариев к вашим вопросам.Автор доклада elizarov призван в комментарии и отвечает на вопросы.См. также обсуждение в журнале автора.

BTW, elizarov выступает на конференции ADD-2012 с докладом «Пишем самый быстрый хэш для кэширования данных».

Пять секретов… контроля производительности Java, часть 1

Профилирование производительности Java с помощью JConsole и VisualVM

Тед Ньюворд
Опубликовано 19.10.2012

Об этом цикле статей

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

Ссылка на оригинал (in English)

Когда приложение работает медленно, большинство разработчиков впадает в панику, и тому есть веская причина. Поиск причин узких мест в Java-приложениях всегда было головной болью ― как потому, что виртуальная машина Java имеет свойства «черного ящика», так и потому, что на платформе Java традиционно недоставало инструментов профилирования.

Однако с появлением JConsole в Java 5 все изменилось. JConsole – это встроенный профайлер производительности Java, который работает из командной строки и в GUI-оболочке. Он не идеален, но служит более чем достаточной первой линией обороны, когда босс указывает вам на проблему производительности — и это гораздо лучше, чем консультироваться у Google.

В этой статье из цикла 5 секретов… я продемонстрирую пять простых способов использования инструмента JConsole (или его визуально продвинутого собрата VisualVM) для мониторинга производительности Java-приложений и отслеживания узких мест в коде Java.

1. JDK поставляется с профайлером

Многие Java-программисты не знают, что, начиная с Java 5, в JDK включен инструмент профилирования. JConsole (или, в более поздних версиях платформы Java, VisualVM) — это встроенный профайлер, запустить который так же легко, как компилятор Java. Достаточно вызвать jconsole из командной строки при наличии JDK в переменной PATH. В GUI-оболочке перейдите в каталог установки JDK, откройте папку bin и дважды щелкните на jconsole.

Когда профайлер появится (время зависит от версии Java и количества других Java-программ, работающих в данный момент), откроется диалоговое окно с запросом URL-адреса процесса, к которому следует подключиться, или списком локальных процессов Java — иногда содержащим сам процесс JConsole.

JConsole или VisualVM?

JConsole входит в каждый выпуск платформы Java, начиная с Java 5. VisualVM — это усовершенствованный профайлер, основанный на платформе NetBeans, который впервые появился где-то в Java 6 update 12. Большинство организаций еще не перешли на Java 6 еще, поэтому данная статья посвящена JConsole. Однако большинство советов актуально для обоих профайлеров. Примечание. VisualVM не только включен в Java 6, но и предоставляется отдельно. См. раздел Ресурсы.)

Работа с JConsole

В Java 5 Java-процессы по умолчанию не настроены на профилирование. При запуске аргумент командной строки -Dcom.sun.management.jmxremote указывает ВМ Java 5, что нужно открыть соединения, чтобы профайлер мог их найти. Когда JConsole следит за процессом, достаточно дважды щелкнуть на нем, чтобы начать профилирование.

Профайлеры вносят свои собственные издержки, так что полезно потратить несколько минут на то, чтобы оценить их. Простейший способ обнаружить издержки JConsole — сначала запустить приложение отдельно, а затем под профайлером, и измерить разницу в производительности. (Приложение не должно быть слишком большим или слишком маленьким, мой любимый пример — SwingSet2, который поставляется с JDK). Я сначала попробовал запустить SwingSet2 с параметром -verbose:gc, чтобы увидеть циклы сбора мусора, а затем запустил то же приложение с подключенным к нему профайлером JConsole. С JConsole наблюдалась регулярная последовательность циклов GC, которой в противном случае не было. Это издержки производительности профайлера.

2. Дистанционное подключение к процессам

Профайлеры Web-приложений предполагают связь через сокет, поэтому достаточно небольшой настройки, чтобы JConsole (или любой профайлер на основе JVMTI) контролировал/профилировал удаленные приложения.

Например, если Tomcat работает на компьютере с именем webserver, и JMX на этой JVM включен и прослушивает порт 9004, то чтобы подключить к нему JConsole (или любой другой JMX-клиент), нужно указать URL-адрес JMX service:jmx:rmi:///jndi/rmi://webserver:9004/jmxrmi.

По сути, все, что требуется для профилирования сервера приложений, работающего в удаленном центре обработки данных, — это URL-адрес JMX. (Подробнее об удаленном мониторинге и управлении с помощью JMX и JConsole см. в разделе Ресурсы.)

3. Отслеживание статистики

Нестандартный подход

На проблемы производительности в коде приложения реагируют по-разному, но все эти реакции предсказуемы. Те разработчики, которые программируют с первых дней Java, скорее всего, запустят старую IDE и начнут просматривать основные части базы исходного кода в поисках знакомых «красных флажков», таких как синхронизированные блоки, размещение объектов и т.п. Разработчик с меньшим стажем, вероятно, будет корпеть над флагами -X, которые поддерживает JVM, в поисках способов оптимизации сборщика мусора. А новички, конечно же, пойдут прямо в Google в надежде на то, что кто-нибудь уже нашел магический «ускоритель» JVM, и им не придется переписывать весь код.

Ни в одном из этих подходов нет ничего принципиально порочного, но все это действия наугад. Наиболее эффективное средство решение проблемы производительности — использование профайлера, а теперь, когда он встроен в платформу Java, отказу от этого нет никакого оправдания!

В JConsole есть несколько вкладок, полезных для сбора статистических данных, в том числе:

  • Memory: для наблюдения за работой различных куч в сборщике мусора JVM;
  • Threads: для изучения текущей работы потоков в целевой JVM;
  • Classes: для наблюдения за общим количеством загруженных классов ВМ.

Эти вкладки (и соответствующие графики) основаны на объектах JMX, которые каждая ВМ Java 5 и выше регистрирует в JMX-сервере, встроенном в JVM. Полный список модулей в составе данной JVM приведен на вкладке MBeans вместе с некоторыми метаданными и ограниченным пользовательским интерфейсом для просмотра этих данных и выполнения операций. (Однако регистрация для получения уведомлений выходит за рамки пользовательского интерфейса JConsole.)

Использование статистики

Допустим, что процесс Tomcat «тормозит» из-за ошибок типа OutOfMemoryError. Чтобы узнать, что происходит, откройте JConsole, щелкните на вкладке Classes и следите за количеством классов. Если их число неуклонно возрастает, можно предположить, что где-то в сервере приложений или вашем коде есть утечка ClassLoader, и в скором времени пространство PermGen будет исчерпано. Если требуется дальнейшее подтверждение проблемы, проверьте вкладку Memory.

4. Создание дампа кучи для автономного анализа

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

Начните с перехода на вкладку MBeans, где нужно раскрыть узел com.sun.management, а затем HotSpotDiagnostic. Выберите Operations, и вы увидите кнопку dumpHeap на правой панели. Если в первом поле ввода (String) указать dumpHeap имя файла для дампа, он сделает снимок текущего состояния всей кучи JVM и сохранит его в этом файле.

Позднее можно использовать различные коммерческие профайлеры для анализа файла или VisualVM ― для анализа снимка. (Помните, что VisualVM присутствует в Java 6, а также доступен для отдельной загрузки).

5. JConsole ― не предел мечтаний

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

В JConsole хорошо то, что вся программа написана на «старом добром языке Java»: такую утилиту мог бы написать любой Java-программист. В JDK даже входит пример того, как настроить JConsole, создав новый плагин для него (см. раздел Ресурсы). В VisualVM, построенном поверх NetBeans, концепция плагинов идет гораздо дальше.

Если JConsole (а также VisualVM или любой другой инструмент) ― совсем не то, что вам нужно, или отслеживает не то, что вы ищете, или не так, как вам хочется, то можно попробовать написать свой собственный. И если Java-код кажется слишком громоздким, всегда под рукой Groovy, JRuby или любой из десятка других языков JVM, которые помогут вам сделать это быстрее.

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

Заключение

Мониторинг производительности Java не заканчивается на JConsole или VisualVM — в JDK скрывается целый ряд инструментов, о которых большинство разработчиков и не подозревает. В следующей статье этого цикла мы рассмотрим некоторые экспериментальные средства на основе командной строки, которые помогают «нарыть» больше данных о производительности. Поскольку эти инструменты обычно ориентированы на конкретные данные, они компактнее и легче полного профайлера и поэтому сами меньше влияют на производительность.

Ресурсы для скачивания
Похожие темы

Профилирование Java под Linux / Блог компании JUG Ru Group / Хабр

Бытует мнение, что бесконечно можно смотреть на огонь, воду и то, как другие работают, но есть и ещё кое-что! Мы уверены, что можно бесконечно говорить с Сашей goldshtn Гольдштейном о перформансе. Мы уже брали у Саши интервью перед JPoint 2017, но тогда разговор касался конкретно BPF, которому был посвящен доклад Саши.

На этот раз мы решили копнуть глубже и узнать фундаментальные проблемы мониторинга производительности и варианты их решения.

С чего стоит начинать

— В прошлый раз мы довольно подробно поговорили про BPF и вскользь обсудили проблемы мониторинга производительности Java под Linux. В этот раз хотелось бы сконцентрироваться не на конкретном инструменте, а на проблемах и поиске решений. Первый вопрос, довольно банальный, — как понять, что с производительностью есть проблемы? Следует ли думать об этом, если пользователь не жалуется?

Саша Гольдштейн: Если начинать думать о производительности только в момент, когда ваши пользователи жалуются, с вами они будут недолго. Для многих инженерия производительности — это траблшутинг и crisis mode. Телефоны звонят, свет мигает, система упала, клавиатура горит — обычные трудовый будни перформанс-инженера. В реальности же они проводят большую часть своего времени, планируя, проектируя, мониторя и предотвращая кризисы.

Для начала, capacity planning — оценка ожидаемой нагрузки системы и использования ресурсов; проектирование масштабируемости поможет избежать узких мест и получить значительные увеличения в нагрузке; инструментирование и мониторинг жизненно необходимы для понимания того, что происходит внутри системы, чтобы не копаться вслепую; благодаря установке автоматического оповещения вы точно будете знать о любых возникающих проблемах, как правило ещё до того, как пользователи начнут жаловаться; ну и конечно же будут единичные кризисы, решать которые придётся в стрессовых условиях.

Стоит отметить, что тулы постоянно меняются, но сам процесс остаётся неизменным. Приведу пару конкретных примеров: capacity planning вы можете сделать и на бумажке на коленке; можно использовать APM-решения (как New Relic или Plumbr) для end-to-end инструментирования и мониторинга, AB и JMeter для быстрого нагрузочного тестирования и так далее. Чтобы узнать больше, можно почитать книгу Брендана Грегга «Systems Performance» — это отличный источник по теме жизненного цикла и методологии перформанса, а «Site Reliability Engineering» от Google освещает тему установки характеристик производительности (Service Level Objectives) и их мониторинга.

— Допустим, мы поняли, что проблема есть: с чего начинать? Мне часто кажется, что многие (особенно не профессиональные перформанс-инженеры) сразу готовы расчехлять JMH, переписывать всё на unsafe и «хакать компиляторы». Потом смотреть, что получилось. Но ведь в реальности лучше не с этого начинать?

Саша Гольдштейн: Это довольно распространённая практика, когда при написании кода и проведении базовых тестов профайлера возникают проблемы с перформансом, которые можно легко исправить, поменяв код или «хакнув компиляторы». Однако на проде, исходя из моего опыта, это делается не так часто. Многие проблемы присущи только какой-то одной среде, вызваны меняющимися паттернами рабочей нагрузки или связаны с узкими местами вне кода вашего приложения, и лишь малую часть можно замикробенчмаркать и улучшить на уровне исходного кода «умными» хаками.

Вот пара примеров для иллюстрации:

  • Пару лет назад Datadog столкнулись с проблемой, когда вставки и обновления базы данных в PostgreSQL скакали от 50 мс до 800 мс. Они использовали AWS EBS с SSD. Что это дало? Вместо тюнинга базы данных или изменения кода приложения они обнаружили, что виноват во всём троттлинг EBS: у него есть квота по IOPS, в случае превышения которой вы попадёте под ограничение производительности.
  • Недавно у меня был пользователь с проблемой огромных скачков времени отклика на сервере, которые были связаны с задержками сбора мусора. Некоторые запросы занимали более 5 секунд (и появлялись они абсолютно бессистемно), так как сборка мусора выходила из-под контроля. Внимательно изучив систему, мы обнаружили, что с распределением памяти приложения или же с тюнингом сборки мусора всё было в порядке; из-за скачка в размере рабочей нагрузки фактическое использование памяти повысилось и вызвало свопинг, что абсолютно губительно для реализации любой сборки мусора (если сборщику нужно подкачивать и откачивать память, чтобы отмечать активные объекты, — это конец).
  • Пару месяцев назад Sysdig столкнулся с проблемой изоляции контейнера: находясь рядом с контейнером Х, операции с файловой системой, выполняемые контейнером Y, были гораздо медленнее, в то время как использование памяти и загрузка процессора для обоих контейнеров были очень низкими. После небольшого исследования они обнаружили, что кэш каталогов ядра перегружался контейнером Х, что в дальнейшем вызывало коллизию хэш-таблицы и, как следствие, значительное замедление. Опять-таки, изменение кода приложения или распределения ресурсов контейнера эту проблему бы не решили.

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

— Наверняка следует сначала посмотреть, как приложение/сервис работает в продакшне. Какие инструменты ты для этого рекомендуешь, а какие — не очень?

Саша Гольдштейн: Мониторинг и профайлинг на проде — это набор инструментов и техник.

Начинаем с метрик высокоуровневого перформанса, фокусируясь на использовании ресурсов (процессор, память, диск, сеть) и характеристике нагрузки (# запросов, ошибок, типов запросов, # запросы к базе данных). Есть стандартные тулы для получения этих данных для каждой операции и времени выполнения. К примеру, на Linux обычно используют инструменты вроде vmstat, iostat, sar, ifconfig, pidstat; для JVM используют JMX-based тулы или jstat. Это метрики, которые можно непрерывно собирать в базу данных, возможно с 5-ти или 30-ти секундным интервалом, чтобы можно было проанализировать скачки и при необходимости вернуться в прошлое, чтобы скоррелировать предыдущие операции по развёртыванию, релизы, мировые события или изменения рабочей нагрузки. Важно, что многие фокусируются на собирании только средних показателей; они хоть и хороши, но, по определению, не представляют полное распределение того, что вы измеряете. Гораздо лучше собирать процентили, а по возможности даже и гистограммы.

Следующий уровень — это операционные метрики, которые обычно нельзя непрерывно собирать или хранить долгое время. Они включают в себя: лог сбора мусора, запросы сети, запросы к базе данных, классовые нагрузки и так далее. Разобраться в этих данных после того, как их где-то хранили, иногда гораздо труднее, чем, собственно, их собирать. Это позволяет, однако, задавать вопросы, вроде «какие запросы работали, пока нагрузка ЦП базы данных повышалась до 100%» или «какими были IOPS дисков и время отклика во время выполнения этого запроса». Одни лишь числа, особенно в виде средних показателей, не позволят вам провести подобного рода исследование.

И наконец, «хардкорный» уровень: SSH в сервере (или удаленный запуск тулов) для сбора большего количества внутренних метрик, которые нельзя хранить во время штатной работы сервиса. Это инструменты, которые обычно называют «профайлерами».

Для профайлинга Java-продакшна существует множество жутких тулов, которые не только дают большой оверхэд и задержки, но могут ещё и лгать вам. Несмотря на то, что экосистеме уже около 20 лет, есть лишь несколько надёжных профайлинговых техник с низким оверхэдом для JVM-приложений. Я могу порекомендовать Honest Profiler Ричарда Ворбертона, async-profiler Андрея Паньгина и, конечно, моего любимчика — perf.

Кстати, много тулов фокусируются на профайлинге процессора, разбираясь в том, какой путь выполнения кода вызывает высокую загрузку ЦП. Это здорово, но часто проблема не в этом; нужны инструменты, которые могут показывать пути выполнения кода, ответственные за распределение памяти (async-profiler теперь может делать и это), ошибки отсутствия страницы, непопадание в кэш, доступы к диску, запросы сети, запросы к базе данных и другие события. Меня в этой области привлекла именно проблема поиска правильных перформанс-тулов для исследования работающей среды.

Профилирование Java под Linux

— Я слышал, что под Java/Linux стек есть куча проблем с достоверностью замеров. Наверняка с этим можно как-то бороться. Как ты это делаешь?

Саша Гольдштейн: Да, это печально. Вот как выглядит текущая ситуация: у вас есть быстрая конвейерная линия с огромным количеством разных частей, которые нужно протестировать, чтобы найти дефекты и понять скорость приложения/сервиса. Вы не можете проверить абсолютно каждую часть, поэтому ваша основная стратегия — это проверять 1 часть в секунду и смотреть, всё ли в порядке, и вам нужно это делать через «крохотное окно» над этой «лентой», потому что подходить ближе уже опасно. Вроде неплохо, не так ли? Но потом оказывается, что когда вы пытаетесь в него посмотреть, оно показывает вам не то, что происходит на конвейере прямо сейчас; оно ждёт, пока конвейер перейдёт в волшебный «безопасный» режим, и только после этого даёт вам всё увидеть. Также оказывается, что многих частей вы не увидите никогда, потому что конвейер не может войти в свой «безопасный» режим, пока они рядом; и ещё оказывается, что процесс поиска дефекта в окошке занимает целых 5 секунд, так что делать это каждую секунду невозможно.

Примерно в таком состоянии сейчас находится множество профайлеров в мире JVM. YourKit, jstack, JProfiler, VisualVM — у всех у них одинаковый подход к профайлингу ЦП: они используют семплинг потоков в безопасном состоянии. Это значит, что они используют документированный API, чтобы приостановить все JVM-треды и взять их стек-трейсы, которые затем собирают для отчёта с самыми горячими методами и стеками.

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

Есть исследование, показывающее, насколько это плохо, когда у каждого профайлера своя точка зрения по поводу самого горячего метода в одной и той же рабочей нагрузке (Миткович и соавт., «Evaluating the Accuracy of Java Profilers»). Более того, если у вас есть 1000 тредов в сложном стеке вызовов Spring, часто собирать стек-трейсы не получится. Возможно, не чаще 10 раз в секунду. В результате ваши данные по стекам будут отличаться от фактической рабочей нагрузки ещё больше!

Решать такие проблемы непросто, но вкладываться стоит: некоторые рабочие нагрузки на проде невозможно профилировать, используя «традиционные» тулы вроде перечисленных выше.

Существует два раздельных подхода и один гибридный:

  • Honest Profiler Ричарда Ворбертона использует внутренний недокументированный API, AsyncGetCallTrace, который возвращает стек-трейс одного треда, не требует перехода в безопасное состояние и вызывается с помощью обработчика сигнала. Изначально он был спроектирован Oracle Developer Studio. Основной подход заключается в установке обработчика сигнала и его регистрации на сигнал с установленным временем (например, 100 Гц). Затем необходимо взять стек-трейс любого треда, который в данный момент работает внутри обработчика сигнала. Очевидно, что есть непростые задачи, когда дело доходит до эффективного объединения стек-трейсов, особенно в контексте обработчика сигнала, но этот подход отлично работает. (Этот подход использует JFR, требующий коммерческую лицензию)
  • Linux perf может предоставлять богатый сэмплинг стеков (не только для инструкций ЦП, но и для других событий, таких как доступ диска и запросы сети). Проблема заключается в преобразовании адреса Java-метода в имя метода, что требует наличие JVMTI-агента, достающего текстовый файл (perf map), который perf может читать и использовать. Есть также проблемы с реконструкцией стека, если JIT использует подавление указателей фрейма. Этот подход вполне может работать, но требует небольшой подготовки. В результате, однако, вы получите стек-трейсы не только для JVM-тредов и Java-методов, но и для всех имеющихся у вас тредов, включая стек ядра и стеки C++.
  • async-profiler Андрея Паньгина сочетает в себе два подхода. Он устанавливает набор образцов perf, но также использует обработчик сигнала для вызова AsyncGetStackTrace и получения Java-стека. Объединение двух стеков даёт полную картину того, что происходит в потоке, позволяя избегать проблем с преобразованием имен Java-методов и подавлением указателей фрейма.

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

Профилирование в контейнерах

— К слову об окружениях, сейчас модно всё паковать в контейнеры, здесь есть какие-то особенности? О чём следует помнить, работая с контейнеризованными приложениями?

Саша Гольдштейн: С контейнерами возникают интересные проблемы, которые многие тулы полностью игнорируют и в результате вообще перестают работать.

Вкратце напомню, что контейнеры Linux построены вокруг двух ключевых технологий: группы контроля и пространства имён. Группы контроля позволяют увеличить квоту ресурсов для процесса или для группы процессов: CPU time caps, лимит памяти, IOPS хранилища и так далее. Пространства имён делают возможной изоляцию контейнера: mount namespace предоставляет каждому контейнеру свою собственную точку монтирования (фактически, отдельную файловую систему), PID namespace — собственные идентификаторы процессов, network namespace даёт каждому контейнеру собственный сетевой интерфейс и так далее. Из-за пространства имён множеству тулов сложно правильно обмениваться данными с контейнезированными JVM-приложениями (хотя некоторые из этих проблем свойственны не только JVM).

Прежде чем обсудить конкретные вопросы, будет лучше, если мы вкратце расскажем о разных видах observability тулов для JVM. Если вы не слышали о некоторых из них, самое время освежить ваши знания:

  • базовые тулы вроде jps и jinfo предоставляют информацию о действующих JVM-процессах и их конфигурации;
  • jstack можно использовать, чтобы достать thread dump (стек-трейс) из действующих JVM-процессов;
  • jmap — для получения head dump действующих JVM-процессов или более простых гистограмм классов;
  • jcmd используется, чтобы заменить все предыдущие тулы и отправить команды действующим JVM-процессам через JVM attach interface; он основан на сокете домена UNIX, который используется JVM-процессами и jcmd для обмена данными;
  • jstat — для мониторинга базовой информации JVM-перформанса, как загрузка класса, JIT-компиляция и статистика сборки мусора; основан на JVM, генерирующей файлы /tmp/hsperfdata_$UID/$PID с этими данными в бинарном формате;
  • Serviceability Agent предоставляет интерфейс для проверки памяти JVM процессов, тредов, стеков и так далее и может быть использован с дампом памяти и не только живых процессов; он работает, читая память процесса и структуры внутренних данных;
  • JMX (управляемые бины) может использоваться для получения информации о перформансе от действующего процесса, а также для отправления команд, чтобы контролировать его поведение;
  • JVMTI-агенты могут присоединяться к разным интересным JVM-событиям, таким как загрузка классов, компиляция методов, запуск/остановка треда, monitor contention и так далее.

Вот некоторые проблемы, возникающие при профайлинге и мониторинге контейнеров из хоста, и способы их решения (в будущем постараюсь рассказать об этом подробнее):

  • большинство инструментов требуют доступ к бинарникам процесса для поиска объектов и значений. Всё это находится в mount namespace контейнера и недоступно из хоста. Частично этот доступ можно обеспечить при помощи bind-mounting из контейнера или к вводу mount namespace контейнера в профайлере во время выполнения symbol resolving (это то, что сейчас делают perf и BCC тулы, о которых я рассказывал в предыдущем интервью).
  • если у вас есть JVMTI-агент, который генерирует perf map (например, perf-map-agent), она будет написана в хранилище контейнера /tmp, используя ID процесса контейнера (например, /tmp/perf-1.map). Map-файл должен быть доступен хосту, а хост должен ждать верный ID процесса в имени файла. (Опять же, perf и BCC теперь могут делать это автоматически).
  • JVM attach interface (на который полагаются jcmd, jinfo, jstack и некоторые другие тулы) требует верных PID и mount namespace attach файла, а также сокет UNIX домена, использовавшегося для обмена данными с JVM. Эту информацию можно прокинуть при помощи jattach utility и создания attach файла, входя в пространство имён контейнера или при помощи bind-mounting соответствующих директорий на хосте.
  • использование файлов данных о производительности JVM (в /tmp/hsperfdata_$UID/$PID), которыми пользуется jstat, требует доступ к монтированию пространства имён контейнера. Это легко адресуется bind-монтированием /tmp контейнера на хосте;
  • самый простой подход к использованию JMX-based инструментов — это, пожалуй, доступ к JVM, как если бы она была удалённой — конфигурируя RMI endpoint, как вы бы делали для удалённой диагностики;
  • тулы Serviceability Agent требуют точного соответствия версий между JVM-процессом и хостом. Думаю, вы понимаете, что не стоит запускать их на хосте, особенно если он использует разное распределение и на нём установлены разные версии JVM.

Тут можно подумать: а если мне просто положить перформанс-тулы в контейнер, чтобы все эти проблемы с изоляцией возникали не из-за меня? Хоть идея неплохая, множество тулов не будут работать и с такой конфигурацией из-за seccomp. Docker, к примеру, отклоняет системный вызов perf_event_open, необходимый для профайлинга с perf и async-profiler; он также отклоняет системный вызов ptrace, который используется большим количеством тулов для чтения объёма памяти JVM-процесса. Изменение политики seccomp для принятия этих системных вызовов ставит хост под угрозу. Также, помещая тулы профайлинга в контейнер, вы увеличиваете его поверхность атаки.


Мы хотели продолжить разговор и обсудить влияние железа на профилирование…

Совсем скоро Саша приедет в Санкт-Петербург, чтобы провести тренинг по профилированию JVM-приложений в продакшне и выступить на конференции Joker 2017 с докладом про BPF, поэтому, если вы хотите погрузиться в тему глубже – у вас есть все шансы встретиться с Сашей лично.

Андрей Паньгин и Нитсан Вакарт о Java-профилировании / Блог компании JUG Ru Group / Хабр

Легко подумать, что от профилирования не стоит ожидать больших новостей: поскольку разработчики профилируют уже десятилетиями, до чего там можно было ещё не додуматься? Но в Java-профилировании кроются серьёзные подводные камни вроде safepoint bias, и появляются новые инструменты для решения подобных проблем.

Андрей apangin Паньгин (Одноклассники) недавно создал один из таких инструментов: на конференции JPoint в апреле он представил опенсорсный проект async-profiler, которому safepoint bias не страшен. Другой эксперт в этой теме — Нитсан Вакарт: о той же проблеме с safepoints многие узнали благодаря его блог-посту «Why (Most) Sampling Java Profilers Are Fucking Terrible».

Мы решили поговорить с ними обоими сразу, начав разговор с последних новостей об async-profiler, а позже перейдя к состоянию Java-профилирования в целом.

JUG.ru: Недавно async-profiler был перемещён на GitHub из личного репозитория Андрея в “jvm-profiling-tools” — что представляет собой jvm-profiling-tools, и чем вызвано перемещение?

Нитсан: Это объединение нескольких репозиториев, преследующих схожие цели. Идея в том, чтобы собрать их в одном месте и стимулировать сообщество активнее их развивать.

Андрей: Именно. Когда стало понятно, что async-profiler интересен Java-сообществу, я решил его перенести в нейтральное место, потому как сторонним разработчикам порой некомфортно контрибьютить в чужой личный репозиторий.

Нитсан: В jvm-profiling-tools есть Honest Profiler, async-profiler и perf-map-agent, и они подходят к одной теме с разных сторон: perf-map-agent открывает возможности для профилирования с использованием линуксового perf, Honest Profiler использует AsyncGetCallTrace, что позволяет избежать safepoint bias, а async-profiler совмещает то и другое очень приятным образом.

Андрей: Да. На самом деле, в идее сочетания обоих подходов ничего космического нет, но почему-то никому в голову это раньше не приходило.

Нитсан: Вообще это было в Solaris Studio, но проблема Solaris Studio в том, что им пользуются человек 20 в мире.

Андрей: Но, насколько я знаю, он не показывает вызовы ядра, так ведь?

Нитсан: Показывает нативный код, но не ядро.

JUG.ru: Поскольку у Honest Profiler и async-profiler есть общее преимущество «отсутствие safepoint bias», теперь при взгляде на jvm-profiling-tools у новичков в профилировании может появиться вопрос: «Ну и какой из двух похожих инструментов мне использовать?» Что вы можете им сказать?

Андрей: Я считаю, что в отношении точности профилирования и полноты информации async-profiler далеко впереди. Ведь даже сам AsyncGetCallTrace в HotSpot работает не всегда: в некоторых пограничных случаях JVM не может восстановить стек-трейс, хотя async-profiler справляется и с такими ситуациями. Кроме того, Honest Profiler вообще не показывает нативные стек-трейсы. Но его большое преимущество в инфраструктуре вокруг представления данных. Он умеет отображать результаты красиво, у него есть UI, а async-profiler — это просто Java-агент, запускаемый из консоли.

Нитсан: Я думаю, что будущее за async-profiler. И мне бы хотелось, чтобы некоторые возможности Honest Profiler попали в async-profiler. Есть ещё разница в том, что Honest Profiler работает на macOS, а async-profiler пока нет: поддерживать большое сообщество хипстеров в нашей отрасли — это важно.

JUG.ru: Вроде бы Вадим Цесько из Одноклассников уже делал возможной работу async-profiler на macOS?

Андрей: Это было до того, как я добавил поддержку perf events. Linux-специфичный вызов сломал поддержку macOS. Но есть и хорошие новости: буквально на днях я разговаривал с Норманом Маурером из Apple (автором Netty), ему также интересен async-profiler, и он любезно согласился сделать Mac-порт.

JUG.ru: В июле в async-profiler появился профайлер хипа — можете рассказать об этом?

Андрей: Существует два основных подхода к профилированию памяти в Java. Первый — это инструментация байткода. Но для продакшен-систем он ужасен, потому что плачевно сказывается на производительности. Ряд оптимизаций компилятора перестаёт работать: прежде всего, Escape Analysis больше не помогает избегать аллокаций в хипе.

Другой подход — использование DTrace probes, что тоже крайне накладно, и может включаться только на старте JVM.

Но это не всё. Есть ещё гораздо более эффективный подход, основанный на сэмплировании TLAB (Thread Local Allocation Buffer). Он реализован в Java Mission Control / Java Flight Recorder, но требует включения коммерческих функций Oracle JDK, а с OpenJDK вообще не работает. Похожий метод используют внутри Google, но там требуется сборка модифицированной версии JVM.

Я нашёл способ использовать этот подход без подключения платных функций, в том числе, с OpenJDK. Сейчас не буду погружаться в подробности, но в отдельном докладе обязательно расскажу.

Нитсан: Я думаю, это важно. Поскольку Java Mission Control сейчас, пожалуй, единственный инструмент для профилированием аллокаций, и работа с подобными процессами в JMC реализована очень своеобразно, многие люди просто не занимаются таким профилированием. Надеюсь, что это поможет профилированию аллокаций стать мейнстримом.

JUG.ru: Может показаться странным, что заметные подвижки в профилировании происходят в 2017-м, когда они были бы полезны годы назад. В чём причина такой задержки?

Андрей: Java — корень всех зол 🙂 Она делает жизнь одновременно и лучше, и хуже. С одной стороны, из-за особенностей JVM стандартные подходы становятся неприменимы, но с другой — JVM предоставляет свои собственные API для профилирования.

Нитсан: Я думаю, что мир Java похож на Windows. Windows была ужасной ОС (вероятно, сейчас куда лучше), но, страдая от многих недостатков, она одновременно имела большой успех. Та же история и с Java. В случае с инструментами профилирования у Java получилось плохо. Я не совсем уверен в том, почему это так.

Я думаю, что разработчики JVM традиционно использовали Solaris Studio, так что всё более-менее нормально работало, но только для них. Специалисты использовали специализированные инструменты. А большинство Java-разработчиков были довольны тем, что имели.

Но теперь Java пришлось столкнуться с реальностью. Нативное профилирование, которое работало в Solaris Studio, но тогда было нишевым решением, становится все более популярным.

Андрей: Считаю нужным добавить, что Java не равно HotSpot, и другие JVM могут быть более дружелюбны к профайлерам.

Нитсан: Может быть, я что-то упустил, но о какой JVM мы говорим? Я знаю много о Zing, и у меня есть немного опыта работы с IBM J9…

Андрей: Сейчас на мне футболка Excelsior JET, и поэтому я вспомнил об этом проекте. Он умеет прекомпилировать Java в нативный код, и, насколько я знаю, от safepoint bias не страдает.

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

JUG.ru: AsyncGetCallTrace, который используют async-profiler и Honest Profiler, не является официальным API. Не ощущается ли его использование «хаком»? Не беспокоитесь ли, что в будущем он может перестать функционировать? Помогла бы более официальная поддержка Oracle в вопросах профилирования?

Нитсан: AsyncGetCallTrace работает ещё с запуска OpenJDK 6, так что похоже, что он всегда был и будет работать. Это «незаконнорожденный ребенок», но я не думаю, что его могут взять и выкинуть. Когда что-либо становится опцией JVM, это в некотором роде получает официальную поддержку. Так что думаю, нам не стоит слишком беспокоиться об этом. Хотя мне интересно, насколько хорошо AsyncGetCallTrace уживается с новым компилятором Graal.

Конечно, более официальная поддержка помогла бы. На данный момент Oracle предоставляет JMC в качестве платного варианта, а всему остальному Java-миру остаётся что-то вроде VisualVM. Сейчас в этом деньги. Я думаю, что Oracle испытывает конфликт интересов: интересы Java, с одной стороны, и их собственные — с другой. Можно сказать, что для них поспособствовать улучшению других JVM-профайлеров означало бы ухудшить собственное положение.

Я не утверждаю, что они активно переживают из-за этого. Я понятия не имею, чего они сейчас хотят. Возможно, они сделают доступными для всех вещи вроде JMC. Теперь, когда работа над Jigsaw закончена, у них есть много времени для другого.

Андрей: Соглашусь, что AsyncGetCallTrace — отчасти «хакерский» API. К тому же далеко не идеальный: я и сам сообщал о багах. Но пока что это лучшее, что есть в HotSpot JVM.

JUG.ru: А может ли, помимо уже имеющихся вещей вроде AsyncGetCallTrace, появиться что-то ещё, что облегчит жизнь создателям профайлеров?

Андрей: Да. Недавно в списках рассылки HotSpot обсуждалось профилирование аллокаций. В итоге даже появился проект JEP, который предлагает новый стандартизованный API для сэмплирования хипа. Думаю, что поднимать такие темы в рассылках и предлагать JEP — правильный путь. Так что, возможно, когда-нибудь в Java 11…

JUG.ru: Что вы думаете о будущем Java-профилирования независимо от действий Oracle? Профайлеры станут намного лучше, чем сейчас?

Андрей: Очень на это надеюсь. В своих докладах я стараюсь доносить до разработчиков мысль, что у профайлеров, которые они используют сейчас, есть большие подводные камни. Нужно либо прекратить использовать их, либо как следует разобраться в их недостатках и ловушках. И думаю, когда больше людей осознают масштабы проблемы, разработчики этих инструментов примутся их улучшать.

Нитcан: В ряде вопросов есть куда расти. С perf-map-agent мы обрели возможность отслеживать инлайнинг при профилировании, но перейдя к async-profiler, снова её теряем. Мне бы очень хотелось увидеть её снова воплощённой.

Другая область — визуализация. Если использовать async-profiler при работе с многопоточными приложениями, где один поток задействует 100% CPU, а все остальные просто висят в ожидании, при профилировании можно получить сбивающую с толку картину. Меня интересуют проблемы представления данных, и я уверен, что существует множество подобных проблем.

Андрей: Да. Сегодня FlameGraph очень популярен в качестве визуализации, но я бы сказал, что он далеко не совершенен.

JUG.ru: Вы оба уже говорили (в докладах и блог-постах), что профайлеры могут создавать искажённую картину. Считаете ли вы, что отрасли сильно вредит использование людьми этой искажённой картины? Может ли быть так, что индустрии от профайлеров тогда вообще больше вреда, чем пользы?

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

Некоторые люди говорили мне, что проблема никогда не оказывается в HashMap. И причина, по которой они никогда не думали, что HashMap может быть проблемой, состоит в том, что обычный профайлер им этого никогда не покажет. Я не утверждаю, что конкретно в их случае проблема в нём, но как бы то ни было, они об этом никогда не узнают. А когда они смотрят на график расхода времени CPU, они не могут увидеть время, затраченное на GC. То есть в том случае, если «бутылочным горлышком» у них оказался GC, они никак не смогут этого отследить.

Андрей: Я согласен с Нитсаном, но добавлю, что лучше иметь хотя бы плохой инструмент, чем не иметь никакого. Главная проблема — не когда профайлер привирает, а когда он не используется совсем. Многие разработчики вообще не профилируют, хотя зачастую проблема производительности кроется в неэффективных алгоритмах, и любой сэмплирующий профайлер её легко выявит.

Нитсан: Я согласен, что многие люди не профилируют, и это проблема. Но если единственным вашим инструментом оказывается плохой профайлер… Вы смотрите на него, видите, что он выдаёт какую-то бессмыслицу, и говорите остальным: «Лучше мы будем просто ставить временные метки», таким у вас получается вывод, и несложно понять, как подобное отбивает у людей желание использовать профайлеры.

JUG.ru: Значит, чтобы улучшить ситуацию с Java-профилированием, нам всем надо работать не только над улучшением инструментов, но и над знаниями сообщества о них?

Нитсан: Да. Я думаю, масштабная история успеха в Java-мире — это JMH, Java Microbenchmarking Harness. И причина в том, что это решение было очень успешным не только с технологической точки зрения, но и в аспекте обучения пользователей, предоставления им возможности лучше познакомиться с этой областью.

Думаю, то, что Андрей и создаёт инструменты, и рассказывает людям, очень важно.

Андрей: Даже самые мощные инструменты будут бесполезны, если не уметь ими пользоваться. С тем же JMH: я много раз видел, как люди писали ерунду в JMH, а потом делали совершенно неправильные выводы. Обучение является неотъемлемой частью успеха.

JUG.ru: Вы оба собираетесь помочь этому обучению своими докладами на ближайшем Joker, и вы оба собираетесь представить там новые версии докладов, ранее представленных на других конференциях. В чём будет состоять новизна?

Нитсан: После того, как я представил на QCon доклад “Profilers are lying hobbitses”, я подумал, что самое лучшее в нём — это название. Поэтому я решил сохранить название, но сам доклад будет очень сильно отличаться. Мы снова будем говорить о профайлерах и о том, как они могут ввести нас в заблуждение, но, думаю, я начну с самого мрачного, а затем буду показывать, как выкарабкаться. В прошлом доклад был серией сюрпризов, приводивших к выводу «ничего не работает». В этот раз будет так: «ничего не работает, но посмотрим, как нам с этим справиться».

Андрей: Изначально я планировал показать продолжение истории async-profiler, начатой на JPoint 2017. Однако потом мы с Программным Комитетом обнаружили большое сходство моего доклада с докладом Нитсана, так что я решил взять новую тему. Пока что я не готов сказать, что именно это будет, но в ближайшее время в программе Joker 2017 можно будет увидеть мой новый доклад! Так что следите за обновлениями.


Java-конференция Joker, где выступят Нитсан и Андрей, состоится в Петербурге 3-4 ноября. Как обычно, после докладов спикеры Joker оказываются в дискуссионных зонах, так что там можно будет расспросить их о профилировании лично. А помимо Андрея и Нитсана, там будут десятки других спикеров — на сайте конференции можно увидеть программу (и приобрести билет).

Введение в профилирование приложений Java в IDE NetBeans

IDE NetBeans включает многофункциональный инструмент профилирования, который позволят получить важные сведения о режиме работы приложения во время выполнения. Средство профилирования NetBeans позволяет просто отслеживать состояния потоков, производительность ЦП и использование памяти приложением в среде IDE; оно потребляет сравнительно немного ресурсов.

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

В этом документе будет демонстрироваться использование средства профилирования для получения данных профилирования о примере приложения Anagram Game, простого приложения Java, входящего в состав среды IDE. Хотя Anagram Game — это очень простой проект приложения Java, при профилировании больших и более сложных приложений Java, а также проектов корпоративных и веб-приложений желательно выполнять те же действия.

В этом документе показано использование среды IDE для профилирования приложения и получения следующих результатов профилирования:

  • Поведение приложения при выполнении
  • Время ЦП, используемое методами приложения
  • Создание объекта

Кроме того, в этом документе показано получение и сравнение снимков результатов профилирования.

Содержание

Начало работы

Предпосылки

Предполагается, что читатель обладает базовыми знаниями по следующим технологиям или опытом программирования с их использованием:

  • Программирование на Java
  • IDE NetBeans

Программное обеспечение, требуемое для работы с данным учебным курсом.

Для работы с этим учебным курсом на компьютере должно быть установлено следующее программное обеспечение.

Примечания.

Первое профилирование

При первом использовании средства профилирования среде IDE необходимо выполнить некоторые начальные операции для обеспечения получения точных результатов профилирования и интеграции средства с проектом. Чтобы продемонстрировать это, создадим проект AnagramGame, а затем выполним калибровку. Среда IDE автоматически выполнит интеграцию при первом профилировании проекта AnagramGame.

Создание примера проекта

В этом документе будет выполнено профилирование примера проекта Anagram Game. Для этого вам сначала необходимо использовать мастер создания проектов для создания примера приложения и настроить проект, как главный проект.

Для создания приложения Anagram Game выполните следующие действия.

  1. Выберите «Файл > Новый проект» (CTRL+SHIFT+N; &#8984+SHIFT+N в Mac ОС) в главном меню.
  2. В мастере создания проекта выберите категорию «Примеры > Java».
  3. Выберите проект «Anagram Game». Нажмите кнопку «Далее».
  4. Укажите местоположение проекта. Нажмите кнопку «Завершить».

    При нажатии кнопки «Готово» среда IDE создает пример проекта Anagram Game.

  5. Выберите ‘Выполнить’ > ‘Настроить основной проект’ > AnagramGame в главном меню.

После настройки проекта как основного имя проекта Anagram Game будет выделено полужирным в окне ‘Проекты’. По умолчанию при использовании среды IDE для профилирования проекта среда IDE профилирует главный проект. Если ни один проект не выбран в качестве главного, среда IDE выполнит профилирование проекта, который выбран в окне ‘Проекты’.

Первое использование средства профилирования

Для получения точных результатов профилирования требуются данные калибровки для каждой платформы Java, которая будет использоваться для профилирования. При первом запуске средства профилирования, или если допустимые данные калибровки недоступны для данной платформы Java, среда IDE запросит выполнить процесс калибровки для вашей платформы.

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

  1. Выберите Дополнительные команды > Управление данными калибровки в меню ‘Профиль’.
  2. Выберите платформу Java. Нажмите ‘Калибровать’.

По завершении операции калибровки появится диалоговое окно. Можно нажать кнопку «Показать подробные сведения», чтобы просмотреть диалоговое окно с информацией о результатах калибровки. Данные калибровки для каждой платформы Java сохраняются в каталоге .nbprofile в домашнем каталоге.

Примечание. При использовании NetBeans IDE 7.4 или более ранней версии нажмите Дополнительные команды > Выполнить калибровку средства профилирования в меню ‘Профиль’ и выберите платформу Java в диалоговом окне ‘Выбор платформы Java для калибровки’.

Выбор задачи профилирования

Среда IDE предоставляет ряд внутренних параметров, позволяющих настраивать профилирования в соответствии с вашими требованиями. Например, можно уменьшить дополнительный расход ресурсов на профилирование за счет уменьшения объема созданной информации. Однако ознакомление со множеством доступных параметров может занять некоторое время. Для большинства приложений параметров по умолчанию, ука

Руководство по Java Profilers


1. Обзор

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

Java Profiler — это инструмент,

отслеживающий конструкции и операции байт-кода Java на уровне JVM

. Эти конструкции и операции кода включают в себя создание объектов, итеративные выполнения (включая рекурсивные вызовы), выполнение методов, выполнение потоков и сборку мусора.

В этой статье мы обсудим основные профилировщики Java:


2. JProfiler

JProfiler — лучший выбор для многих разработчиков. Благодаря интуитивно понятному пользовательскому интерфейсу JProfiler предоставляет интерфейсы для просмотра производительности системы, использования памяти, потенциальных утечек памяти и профилирования потоков.

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

Вот как выглядит интерфейс JProfiler:

ссылка:/uploads/1-jprofiler-overview-probing.png[Обзорный обзор JProfiler с функциями]

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

профилировать приложения Java, работающие на удаленных машинах, без необходимости устанавливать на них что-либо

.

JProfiler также предоставляет

расширенное профилирование для баз данных SQL и NoSQL

. Он обеспечивает особую поддержку для профилирования баз данных JDBC, JPA/Hibernate, MongoDB, Casandra и HBase.

На снимке экрана ниже показан интерфейс проверки JDBC со списком текущих соединений:

ссылка:/uploads/2-jprofiler-database-probing-1.png[Просмотр базы данных JProfiler]

Если мы заинтересованы в том, чтобы узнать о

дереве вызовов взаимодействий с нашей базой данных

и увидеть

соединения, которые могут быть пропущены

, JProfiler прекрасно с этим справится.

Live Memory — это одна из функций JProfiler, которая позволяет

видеть текущее использование памяти нашим приложением

. Мы можем просматривать использование памяти для объявлений и экземпляров объектов или для полного дерева вызовов.

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

На приведенном ниже экране показано использование оперативной памяти всеми объектами с количеством экземпляров:

ссылка:/uploads/3-jprofiler-live-memory.png[JProfiler просмотр оперативной памяти]

JProfiler поддерживает

интеграцию с популярными средами разработки

, такими как Eclipse, NetBeans и IntelliJ. Можно даже

переходить от снимка к исходному коду

!


3. YourKit

YourKit Java Profiler работает на многих различных платформах и предоставляет отдельные установки для каждой поддерживаемой операционной системы (Windows, MacOS, Linux, Solaris, FreeBSD и т. Д.).

Как и JProfiler, YourKit имеет основные функции для визуализации потоков, сборок мусора, использования памяти и утечек памяти, с

поддержкой локального и удаленного профилирования через туннелирование ssh

.

Вот краткий обзор результатов профилирования памяти серверного приложения Tomcat:

ссылка:/uploads/4-yourkit-tomcat-profiling-memory.png[профилирование памяти YourKit Java Profiler серверного приложения Tomcat]

YourKit также пригодится в тех случаях, когда мы хотим

профилировать выданные исключения

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

YourKit имеет интересную

функцию профилирования процессора, которая позволяет сфокусировать профилирование на определенных областях нашего кода

, таких как методы или поддеревья в потоках. Это очень мощный инструмент, так как он позволяет выполнять условное профилирование с помощью функции «что, если».

На рисунке 5 показан пример интерфейса профилирования потока:

ссылка:/uploads/5-yourkit-threads-profiling.png[Рисунок 5. Интерфейс профилирования потоков YourKit Java Profiler]

Мы также можем

профилировать вызовы SQL и базы данных NoSQL

с помощью YourKit. Он даже предоставляет представление для реальных запросов, которые были выполнены.

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


4. Java VisualVM

Java VisualVM — это упрощенный, но надежный инструмент профилирования для приложений Java. По умолчанию этот инструмент

связан с Java Development Kit

(JDK). Его работа основана на других автономных инструментах, предоставляемых в JDK, таких как

JConsole

,

jstat

,

jstack

,

jinfo

и

jmap

.

Ниже мы видим простой обзорный интерфейс текущего сеанса профилирования с использованием Java VisualVM:

ссылка:/uploads/6-visualvm-overview.png[Профилирование локального tomcat-сервера Java VisualVM]

Одним из интересных преимуществ Java VisualVM является то, что мы можем

расширить его для разработки новых функциональных возможностей в виде плагинов

. Затем мы можем добавить эти плагины во встроенный центр обновлений Java VisualVM.

Java VisualVM поддерживает

локальное и удаленное профилирование

, а также профилирование памяти и процессора.

Подключение к удаленным приложениям требует предоставления учетных данных

(имя хоста/IP и пароль при необходимости)

, но не обеспечивает поддержку туннелирования ssh

. Мы также можем выбрать либо

профилирование в реальном времени с мгновенными обновлениями

(обычно каждые 2 секунды).

Ниже мы можем увидеть внешний вид памяти Java-приложения, профилированного с помощью Java VisualVM:

ссылка:/uploads/7-visualvm-sample-memory.png[Гистограмма кучи памяти Java VisualVM]

С помощью функции моментальных снимков Java VisualVM мы можем

сделать снимки сеансов профилирования для последующего анализа

.


5. Профилировщик NetBeans

NetBeans Profiler

поставляется в комплекте с Oracle IDE NetBeans с открытым исходным кодом

.

Хотя этот профилировщик

имеет много общего с Java VisualVM

, это хороший выбор, когда мы хотим, чтобы все было упаковано в одну программу (IDE Profiler).

Все другие профилировщики, рассмотренные выше, предоставляют плагины для улучшения интеграции IDE.

На приведенном ниже снимке экрана показан пример интерфейса NetBeans Profiler:

ссылка:/uploads/8-netbeans-telemetry-view.png[Интерфейс телеметрии Netbeans Profiler]

Netbeans Profiler также является

хорошим выбором для облегченной разработки и профилирования

. NetBeans Profiler предоставляет единое окно для настройки и управления сеансом профилирования и отображения результатов. Это дает уникальную возможность узнать

Лучший и безопасный Java Profiler для использования в производстве? [закрытый]

Я ищу профилировщик Java для использования в производственной среде с очень высоким спросом, коммерческой или бесплатной, которая отвечает всем следующим требованиям:

  • легкая интеграция с кодом (без перекомпиляции со специальными опциями, без кодовых крючков и т. д.). Отбрасываем некоторые профилировщики .банки рядом с кодом приложения в порядке.
  • должна быть возможность подключения/отключения к JVM без перезапуска приложения.
  • для профилирования не активен, не влияет на производительность
  • когда профилирование активно, незначительное влияние на производительность. Очень небольшое ухудшение приемлемо.
  • должен делать все «ожидаемые» вещи, которые делает профилировщик-время, затраченное в каждом методе, чтобы найти горячие точки,выделение объекта / профилирование памяти и т. д.

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

10 ответов


вы пробовали YourKit? Он имеет почти все функции, которые вы ищете.


Java VisualVM-это инструмент, который предоставляет визуальный интерфейс для просмотра подробной информации о приложениях на основе технологии Java (Java applications) во время их работы на виртуальной машине Java (JVM). Java VisualVM организует данные JVM, которые извлекаются средствами Java Development Kit (JDK), и представляет информацию таким образом, что позволяет быстро просматривать данные в нескольких приложениях Java. Можно просматривать данные о локальных приложениях и приложениях, запущенных на удаленном компьютере принимать гостей. Вы также можете захватить данные о программном обеспечении JVM и сохранить данные в локальной системе, а затем просмотреть данные позже или поделиться данными с другими. Это поставляется с Oracle JDK IT self…

$ jvisualvm 

14

автор: Prabath Siriwardena



предпочитаю Java Flight Recorder. Это не вызывает почти никаких накладных расходов производительности и имеет хороший графический интерфейс. Добавить параметры JVM

-XX:+UnlockCommercialFeatures -XX:+FlightRecorder

-XX:StartFlightRecording=name=test,filename=test.jfr,dumponexit=true

и откройте запись с помощью JMC.



Я использую проект Платформы Eclipse TPTP — Eclipse Test & Performance Tools. Подходит ли он для производственного использования или нет, зависит от пользователя. Для меня это нормально, и это соответствует вашим потребностям.

http://www.eclipse.org/tptp/


другой вариант -http://www.newrelic.com/. Мы используем его в производстве в течение некоторого времени, и он кажется довольно надежным и эффективным. Простой в настройке (один .опция командной строки jar и A-agent).



Fusionreactor Java Application Performance Monitor, также включает в себя очень низкие накладные расходы Java Profiler как часть своего портфолио функций.
http://www.fusion-reactor.com/production-java-profiler/
FusionReactor может быть установлен в течение нескольких минут, и у них есть бесплатная 14-дневная пробная версия, чтобы проверить его.

1

автор: David Tattersall


посмотри Java Mission Control в сочетании с Самописцам. Начиная с выпуска Oracle JDK 7 Update 40 (7u40), Java Mission Control поставляется в комплекте с HotSpot JVM, поэтому он высоко интегрирован и претендует на небольшое влияние на производительность во время выполнения. Он имеет функциональность дерева вызовов, такую как Callgrind.

1

автор: Muxiang Yang


Особенности

Java Profiler — YourKit

Отмеченный наградами Java Profiler

Профилирование ЦП и памяти Java никогда не было таким простым и интеллектуальным одновременно.
YourKit разработал революционный способ профилирования Java-приложений на
стадии разработки и производства, принося беспрецедентные преимущества
Разработчики Java.

Готовы к вашим задачам

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

Тесная интеграция с вашей IDE

Плагины для Eclipse, IntelliJ IDEA и IDE NetBeans предлагают
профилирование всех видов Java-приложений в один клик, а также
умная навигация от результатов профилирования до исходного кода.

Профиль удаленных приложений

Профилировать удаленное приложение так же просто, как и локальное.Когда вам нужно профилировать удаленный сервер, профилировщик будет
все настроить.

Чтобы начать удаленное профилирование, вам нужен только SSH-доступ.

Профилирование процессора

YourKit Java Profiler использует множество функций JVM и ОС для
получить информацию о методах и времени
с минимальными накладными расходами. Профили ЦП можно визуализировать как
называйте деревья или списки горячих точек.

Smart что если функция позволяет оценить
повышение производительности предполагаемых оптимизаций без перепрофилирования
приложение.

Графики пламени

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

Запросы к базе данных и веб-запросы

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

Поддерживаются популярные базы данных, такие как MongoDB, Cassandra и HBase.

Профилирование памяти

Профилировщик визуализирует кучу объектов и позволяет обходить
граф объекта в любом направлении. Свойства объектов визуализируются в удобном
форма. Профилировщик выбирает лучший способ показать вам содержимое HashMap или
Строка значение.

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

Сравнение снимков процессора и памяти

Отслеживайте, как изменения в коде влияют на производительность
вашего приложения.

YourKit Java Profiler может сравнивать производительность и снимки памяти
и экспортировать сравнительные отчеты в различных форматах.

Проверка эффективности

40+ комплексных проверок ждут, чтобы
код быстрее и эффективнее.

Profiler много знает о типичных проблемах в Java-приложениях.
и автоматически находит их.
Вы можете легко найти утечки веб-приложений, повторяющиеся объекты,
незамкнутые операторы SQL и потоки.
Профилировщик показывает неэффективные коллекции и операции ввода-вывода.

Найти проблемы синхронизации потоков

YourKit Java Profiler визуализирует активность потоков.
Вы можете легко найти заблокированные темы и понять
причины.

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

Можно комбинировать состояния потоков с HTTP-запросами и SQL-запросами, чтобы получить
полная картина того, как запросы обрабатываются вашими приложениями.

Телеметрия и графики производительности

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

Профилирование исключений

Массивное генерирование исключений — распространенная, но часто скрытая проблема производительности.
YourKit Java Profiler немедленно находит все места, где возникло исключение.

Деобфускация кода на лету

YourKit Java Profiler может восстанавливать исходные имена классов, методов и полей.
приложений, запутанных с помощью ProGuard, yGuard, Zelix KlassMaster, Allatori,
и другие популярные Java-обфускаторы.Если вы разрабатываете мод для Minecraft, просто
дайте профилировщику свой файл сопоставления MCP, и он покажет исходные имена.

Вы контролируете накладные расходы

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

Экспорт во внешние форматы и открытый API

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

Расширяемый API позволяет создавать собственные зонды и
собирать данные для конкретного приложения. Вы можете управлять профилированием
режимах, делайте снимки и анализируйте их прямо с вашего
Код Java.

Интерфейс командной строки

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

Доступное разрешающее лицензирование

Гибкие варианты лицензирования позволяют выбрать лучшее
лицензия для команд разработчиков любого размера.

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

.

Java VisualVM — приложения для профилирования

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

Профилирование приложений

Вкладка Profiler приложения позволяет запускать и останавливать
сеанс профилирования локального приложения.Результаты профилирования
отображается на вкладке Профилировщик. Вы можете использовать панель инструментов для обновления
результаты профилирования, вызовите сборку мусора и сохраните
данные профилирования.

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

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

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

Использование панели инструментов

Вы можете использовать следующие кнопки в результатах профилирования
панель инструментов для работы с результатами профилирования:

  • Обновить результат автоматически. Когда активен, отображается
    результаты профилирования автоматически обновляются через короткие промежутки времени
    (около 2 секунд).
  • Обновить результат сейчас. Нажмите, чтобы обновить результаты
    немедленно.
  • Запустить сборку мусора. Нажмите, чтобы запустить мусор
    коллекция.
  • Сбросить собранные результаты. Нажмите, чтобы отказаться от уже
    накопленные результаты профилирования.
  • Сделать снимок. Щелкните, чтобы сделать снимок текущего
    данные профиля. Когда вы делаете снимок, снимок открывается в
    новая подвкладка.
  • Сохранить текущий вид. Нажмите, чтобы сохранить текущий вид
    результаты профилирования в виде файла изображения .png. Когда вы щелкаете
    кнопка вам будет предложено выбрать место, где вы хотите
    сохраните изображение.

Фильтрация результатов профилирования

Поле фильтра под результатами профилирования позволяет фильтровать
отображаемые результаты в соответствии с названием метода. Чтобы
отфильтруйте результаты, введите термин в поле фильтра имени метода,
выберите, какой метод фильтрации использовать, и нажмите Return.Ты можешь видеть
и выберите предыдущие условия фильтра, щелкнув стрелку справа
поля фильтра имени метода.

Изменение настроек профилирования

Инструмент профилирования Java VisualVM предоставляет настройки по умолчанию для
профилирование приложений. Вы можете просмотреть настройки по умолчанию, выбрав
установив флажок Настройки на вкладке Профилировщик. Вы можете изменить
настройки профилирования при отсутствии сеанса профилирования
прогресс.

Профилирование ЦП

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

Снимок экрана вкладки Profiler, показывающий результаты профилирования CPU

Снимок экрана вкладки Profiler, показывающий настройки профилирования CPU

Профилирование памяти

Когда вы анализируете использование памяти, запускается Java VisualVM.
инструментирует загруженные классы и отображает общее количество
объекты, выделенные каждым классом (включая классы массивов) в
Таблица.Для каждого загруженного в настоящее время класса в Java Virtual
Machine (JVM), результаты профилирования отображают размер и количество
объекты, выделенные с момента начала сеанса профилирования. Результаты, достижения
автоматически обновляются по мере размещения новых объектов и по мере появления новых
классы загружены.

Java VisualVM отображает количество объектов как абсолютное
число и в процентах. Также отображаются выделенные байты
в виде графика, представляющего процент байтов, а также
общее количество байтов, выделенных каждым классом.

Снимок экрана вкладки Profiler, показывающий результаты профилирования памяти

Снимок экрана вкладки Profiler, показывающий настройки профилирования памяти

Создание снимков профилировщика

Java VisualVM позволяет делать снимки профилировщика для захвата
результаты сеанса профилирования. Снимок профилировщика захватывает
результаты на момент создания снимка. Взять
снимка, нажмите кнопку Сделать снимок собранных результатов в
панель инструментов во время сеанса профилирования.Когда вы берете
снимок, снимок откроется в виде вкладки на вкладке приложения. А
узел для моментального снимка также отображается под узлом приложения в
Окно приложений.

Скриншот снимка профилирования памяти

Снимок экрана с моментальным снимком профилирования процессора

Дополнительные сведения о снимках профилировщика см. В следующих
документ:

.Производительность

— Какой профилировщик Java лучше: JProfiler или YourKit?

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

Загрузка…

.

YourKit Java Profiler Help — Запуск приложений с помощью профилировщика

Локальное и удаленное профилирование

Профилированное приложение и профилировщик могут работать на одной или на разных машинах.

Эти режимы называются локальным профилированием и удаленным профилированием.
соответственно.

Агент профилировщика

Чтобы профилировать приложение Java, будь то локальное или удаленное, агент профилировщика должен быть загружен в JVM.

Подход 1. Запустите JVM с агентом профилировщика

Этот подход рекомендуется , так как он обеспечивает полный набор возможностей профилирования.
Чтобы узнать, как его применять, см. Соответствующий подтем:

Подход 2. Присоедините профилировщик к работающему экземпляру JVM, запущенному без агента

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

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

Подробнее о прикреплении.

Поддерживаемые JVM

Поддерживаемые версии Java: Java 7, Java 8, Java 9, Java 10, Java 11, Java 12, Java 13, Java 14.

Поддерживаемые JDK:

  • Oracle JDK
  • OpenJDK, включая сборки из:
    • AdoptOpenJDK
    • Amazon Corretto
    • Azul Zulu
    • BellSoft Liberica JDK
    • JetBrains
    • Оракул
    • Красная шляпа
    • SapMachine
  • IBM JDK и OpenJ9

Поддерживаемые платформы

AIX

  • AIX, 32-битная Java (ppc) и 64-битная Java (ppc64)

FreeBSD

  • FreeBSD 9 и новее, i386 и amd64 (также известные как x86-64).Ограничение:
    Профилирование процессора всегда будет измерять время стены
    и телеметрия потоков покажет одно и то же время ЦП — время ЦП процесса — для всех потоков,
    потому что FreeBSD не может измерять процессорное время по потоку.

HP-UX

  • HP-UX IA64, 32-разрядная и 64-разрядная Java

Linux

Linux, 32-битная Java и 64-битная Java:

  • x86 / x86-64
  • ARM, жесткий поплавок
  • ppc / ppc64 / ppc64le

macOS

  • macOS 10.9 и новее, Intel, 64-битная Java

Solaris

  • Solaris 10 и новее, x86, 32-битная и 64-битная Java
  • Solaris 9 и новее, SPARC, 32-битная и 64-битная Java

Окна

32-битная Java (x86) и 64-битная Java (x86-64):

  • Windows 10, Windows Server 2016, Windows Server 2019
  • Windows 8.1, Windows Server 2012 R2
  • Windows 8, Windows Server 2012
  • Windows 7, Windows Server 2008 R2

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *