elizarov


Блог Романа Елизарова


Previous Entry Share Next Entry
Доклад на ADD CONF 2011 - DIY Java Profiling
elizarov
Сделал доклад на ADD CONF 2011 про самодельное профилирование Java приложений. Поделился нашим десятилетним опытом использования thread dumps и изменения кода через ObjectWeb ASM. К это ни странно, за десять лет инструменты для профилирования Java приложений прошли огромный путь, стали взрослыми и мощными, а наши простенькие поделки, написанные на коленке, до сих используются и приносят пользу, потому что элегантно решают весьма уникальные задачи. Слайды с доклада можно посмотреть здесь.

  • 1
слайды очень интересные. а видео тоже обещают?

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

спасибо

FWIW, на слайды можно речь начитать :) получится слайдкаст. Массы воспримут на ура.

Интересно, а много у вас, так сказать, единомышленников?

Я вот на глазок делю количество людей, которые хотя бы знают, с какой стороны взяться, скажем, за WinDbg и co., который умеет рассказывать все на свете про Win, на общее количество Win и .Net разработчиков, и цифра получается неутешительная. Не все считают, что DIY - особый fun.

Интересно, как в Java-мире...

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

За предложение спасибо, но Java и прочие managed - совершенно не мой профиль. Как и UI.

Роман, интересные слайды, спасибо.
Немало знакомых и дей и выводов, выстраданных годами :)

Совем недавно при "профилировании" при помощи thread dumps натолкнулся на пробелему, решения которой не нашел. Может Вы сталкивались и/или задумывались о таком...

Есть два (или более) дампа одного и того же потока. Текстовое представление этих дампов одинаковое. Как определить пересекаются ли стеки вызовов?

Например есть код
    public static void main(String[] args) throws Exception
    {
        test_m1();
    }

    private static void test_m1()
    {
        test_m2();
    }

    private static void test_m2()
    {
        print(Thread.currentThread().getStackTrace());
        System.out.println();
        print(Thread.currentThread().getStackTrace());
        
    }
    
    private static void print(StackTraceElement[] traces)
    {
        for (StackTraceElement trace: traces)
        {
            System.out.println(trace+"@"+System.identityHashCode(trace));
        }
    }


который выводит
java.lang.Thread.getStackTrace(Thread.java:1479)@9634993
com.inforeach.util.benchmark.test1.test_m2(test1.java:30)@1641745
com.inforeach.util.benchmark.test1.test_m1(test1.java:25)@11077203
com.inforeach.util.benchmark.test1.main(test1.java:20)@14576877

java.lang.Thread.getStackTrace(Thread.java:1479)@12677476
com.inforeach.util.benchmark.test1.test_m2(test1.java:32)@33263331
com.inforeach.util.benchmark.test1.test_m1(test1.java:25)@6413875
com.inforeach.util.benchmark.test1.main(test1.java:20)@21174459


Хочется как-то определить, что часть трейса выделенная болдом -- общая часть, а не просто одинаковое текстовое представление.
Трюк с identityHashCode совершенно не помог, как легко видеть :(

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

Примером может является "разбор" любой очереди. Например в EDT
"AWT-EventQueue-0" Id=14 RUNNABLE (in native)
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
	-  locked java.io.BufferedInputStream@f7dc96
	at java.io.DataInputStream.readByte(DataInputStream.java:248)
	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:195)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
	at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
	at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
	at $Proxy12.getProductInfo(Unknown Source)
	at com.inforeach.eltrader.tms.staticdata.rmi.RMIOutwardStaticDataAdapter$5.run(RMIOutwardStaticDataAdapter.java:270)
...
...
	at com.inforeach.eltrader.tms.view.portfolio.TMSVBasePortfolioFrame$19.processEvent(TMSVBasePortfolioFrame.java:2936)
	at com.inforeach.eltrader.tms.view.TMSVFrame$RPTDelayedActiveRecordAdapter$1$1.run(TMSVFrame.java:871)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

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

Я пытаюсь понять, что именно Вы называете "одним и тем же дампом". Если имеется в ввиду, что надо отличить события происходящие в контексте одного вызова метода java.awt.event.InvocationEvent.dispatch от событий происходящих в контексте другого вызова этого же метода, то такая задача через getStackTrace не решается. На стэке просто не содержится необходимая для этого информация. Стеки разных вызовов одного и того же метода в общем случае идентичны.

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

Если имеется в ввиду, что надо отличить события происходящие в контексте одного вызова метода java.awt.event.InvocationEvent.dispatch от событий происходящих в контексте другого вызова этого же метода, то такая задача через getStackTrace не решается.

Да именно это я и пытался сколько косноязычно спросить :)

В общем случае, это не всегда EDT, но идея с счетчиком понятна. Плохо то, что хочется отличать события происходящие в контексте одного вызова метода java.awt.event.InvocationEvent.dispatch от событий происходящих в контексте другого вызова этого же метода без того, чтобы менять существующий код.

На стэке просто не содержится необходимая для этого информация
Понял, спасибо. Было такое ощущение, но хотелось "второе мнение"

Роман, поделитесь пожалуйста ссылкой на ваш анализатор.

Re: thread dump analyzer

Пока не доступен. Напишу как появится.

  • 1
?

Log in

No account? Create an account