Я написал этот небольшой (и крайне неэффективный) класс и хотел профилировать его с помощью Java VisualVM.
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
int n = Integer.parseInt(args[0]);
int fib = fib(n);
System.out.println(fib);
}
private static int fib(int n) {
if (n < 2) {
return n;
}
return fib(n-1)+fib(n-2);
}
}
Результаты странные.В результатах преобладают вызовы ConnectionHandler.run ().
(98,2%) sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run ()
(1,7%) java.lang.Thread.join (long)
(0%) java.lang.String.equals (Object)
etc ...
Вероятно, профилировано около ста методов, и ни один из них не являетсяfib (int)!
Невероятно, что моя программа фактически тратит все свое время на эти методы.Похоже, они подключаются к моему jvm и делают свое дело.
Что я делаю не так?
Отредактировано для ясности: Если передать 45 дляЭто приложение работает в течение 20 секунд.Изначально программа, которую я профилировал (не калькулятор Фибоначчи), привязывает все четыре ядра к моему процессору на 100%, и я выполнял профилирование продолжительностью до 5 минут.У них были те же результаты, и методы из моего приложения не появлялись высоко в списке методов горячих точек.
Это варьируется от запуска к запуску, но ConnectionHandler.run () всегда вверху и обычно составляет ~99% времени профиля.
Второе редактирование: Я попытался использовать сэмплер, и теперь я получаю результаты, которые согласуются с тем, что производит JProfiler.Недостатком этого является то, что я не получаю информацию трассировки стека, которая поставляется с профилированием.Но для моих насущных потребностей это отлично.
Что-то, что я обнаружил во время игры, - это то, что VisualVM подсчитывает время для вызовов методов во время их профилирования.
В моем конкретном случае в моем приложении есть основной поток, который запускает рабочие потоки и немедленно блокирует ожидание сообщения в очереди.
Это означает, что метод блокировки, по-видимому, займет почти всевремени на профилировщике, несмотря на тот факт, что не этот метод поглощает мой процессор.
Я ожидаю, что то же самое верно и для sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.Метод run (), который хорошо выполняет свою работу - но когда он завершается, он становится одним из самых продолжительных методов в моем приложении - несколько раз .