SlideShare a Scribd company logo
Как сделать профилировщик
из палок... и других подручных средств
@antonarhipov
JPoint 2016, Москва
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
Batch / ETL
Исходные данные : ~10k записей
Результат: ~20M записей
j.u.Date / j.u.Calendar
Java 1.4 HP-UX
Первый запуск: 25 ч :-(
После оптимизаций: 10 ч
После изменения дизайна: 30 мин :-)
2005
История одного проекта
Тот самый случай
когда выглядишь умным,
но чувствуешь себя
полным ДУРАКОМ
https://twitter.com/shipilev/status/578193813946134529
Как и когда вы
используете профилировщик?
QA Staging Production
Тормозит!
Тесты
показывают падение
производительности
Всё плохо!
JPoint 2016 - Etudes of DIY Java profiler
> Chrome DevTools
> FireBug
> YSlow
> …
> XRebel
“Проактивные” инструменты
> Пользовательский интерфейс
> Профилирование приложения
> Трассировка внешних вызовов
> Трассировка потоков
> Распределённые приложения
Этюды профайлероводства
UI & UX
JPoint 2016 - Etudes of DIY Java profiler
package org.apache.catalina.connector;
public class Response implements HttpServletResponse {
public ServletOutputStream getOutputStream() throws IOException {
if (this.usingWriter) {
throw new IllegalStateException(…));
}
this.usingOutputStream = true;
if (this.outputStream == null) {
this.outputStream = new CoyoteOutputStream(this.outputBuffer);
}
return this.outputStream;
}
Javassist
package org.apache.catalina.connector;
public class Response implements HttpServletResponse {
public ServletOutputStream getOutputStream() throws IOException {
if (this.usingWriter) {
throw new IllegalStateException(…));
}
this.usingOutputStream = true;
if (this.outputStream == null) {
this.outputStream = new CoyoteOutputStream(this.outputBuffer);
}
return this.outputStream;
}
    ctClass.getDeclaredMethod("getOutputStream").insertAfter(

        "if  ("  +  _interceptor  +  "  !=  null)  {"  +

        "    $_  =  (ServletOutputStream)"  +  _interceptor  +  ".getOutputStream($_);"  +

        "}");  
Javassist
package org.apache.catalina.connector;
public class Response implements HttpServletResponse {
public ServletOutputStream getOutputStream() throws IOException {
if (this.usingWriter) {
throw new IllegalStateException(…));
}
this.usingOutputStream = true;
if (this.outputStream == null) {
this.outputStream = new CoyoteOutputStream(this.outputBuffer);
}
if (_interceptor != null) {
this.outputStream = (ServletOutputStream)_interceptor
.getOutputStream(this.outputStream);
}
return this.outputStream;
}
Куда уходит время?
Windows: Ctrl+Break
*nix: kill -3 PID
"http-nio-8080-exec-1"#40 daemon prio=5 os_prio=31 tid=0x00007fd7057ed800 nid=0x7313 runnable
java.lang.Thread.State: RUNNABLE
at o.s.s.p.w.OwnerController.processFindForm(OwnerController.java:89)
at s.r.NativeMethodAccessorImpl.invoke0(Native Method)
at s.r.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at s.r.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at j.l.r.Method.invoke(Method.java:497)
Сэмплирование
Интервал : 20 мс
Кол-во сэмплов: 4
Интервал : 1 мс
Кол-во сэмплов: 100+
main()
foo()
bar()
baz()
Safepoints
main()
foo()
bar()
baz()
Safepoints
main()
foo()
bar()
baz()
Java Mission Control
Java 7u40
Honest Profiler
https://github.com/RichardWarburton/honest-profiler
AsyncGetCallTrace
JVMTI
Как обуздать safepoint bias?
main()
foo()
bar()
baz()
Инструментирующий профилировщик
Высокие накладные расходы для быстрых методов
public  void  businessMethod()  {

    long  start  =  System.currentTimeMillis();

    work();

    Profiler.log(System.currentTimeMillis()-­‐start);  
}
public  void  businessMethod()  {

    long  start  =  System.nanoTime();

    work();

    Profiler.log(System.nanoTime()-­‐start);

}
public  void  businessMethod()  {

    Profiler.start("businessMethod");  
    try  {

        work();

    }  finally  {

        Profiler.log("businessMethod");

    }

}
System.nanoTime
Параллельный поток для замеров времени
sleep-wakup-update
yield-wakup-update
busy-loop-update
class  Profiler  {  


    Loop  loop;



    public  static  void  start(String  method)  {

        long  now  =  loop.getTime();  
        …

    }  
public  class  Loop  implements  Runnable  {

        private  volatile  long  time;

        public  void  run()  {

                while  (running)  {

                        time  =  System.nanoTime();

                        sleep();

                }

        }  
        public  final  long  getTime()  {

                return  time;

        }  
Busy Loop
Наносекунды в приближении
Чтение памяти имеет цену
Занимает циклы процессора = ns
Каждый слой ПО добавляет к цене.
JVM, JNI, OS, HW
http://shipilev.net/blog/2014/nanotrusting-nanotime/
Nanotrusting the NanoTime
Наносекунды в приближении
http://shipilev.net/blog/2014/nanotrusting-nanotime/
Nanotrusting the NanoTime
granularity_nanotime: 26.300 +- 0.205 ns
latency_nanotime: 25.542 +- 0.024 ns
granularity_nanotime: 29.322 +- 1.293 ns
latency_nanotime: 29.910 +- 1.626 ns
granularity_nanotime: 371,419 +- 1,541 ns
latency_nanotime: 14,415 +- 0,389 ns
Linux
Solaris
Windows
Thread.sleep
Win8: 1.7 мс (JNI + socket poll: 1.0 ms )
Linux: 0.1 мс
OS X: 0.05 мс
Всё таки загружает ядро процессора на 25-50%
Thread.yield
Планировшик в Windows может проигнорировать
наш поток в случае высокой загрузки процессора
public  class  Loop  implements  Runnable  {

        private  volatile  long  time;

        public  void  run()  {

                while  (running)  {

                        time  =  System.nanoTime();

                        sleep();

                }

        }  
        private  void  sleep()  {

            if  (!MiscUtil.isWindows())  {

                  Thread.yield();

            }

        }
Busy Loop
Busy Loop
public  class  Loop  implements  Runnable  {

        private  volatile  long  time;

        public  void  run()  {

                while  (running)  {

                        time  =  System.nanoTime();

                        sleep();

                }

        }  
        private  void  sleep()  {

            if  (!MiscUtil.isWindows())  {

                  Thread.yield();

            }

        }
Busy Loop
public  class  Loop  implements  Runnable  {

        private  volatile  long  time;

        public  void  run()  {

                while  (running)  {

                        time  =  System.nanoTime();

                        sleep();

                }

        }  
        private  void  sleep()  {

            if  (!MiscUtil.isWindows())  {

                  Thread.yield();

            }

        }
main()
foo()
bar()
baz()
2
3
4
main()
foo()
bar()
baz()
2
3
5
boo()
Дисбаланс ошибки для веток с разной глубиной
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
Оптимизации
LeafMethodAnalyser(AbstractMethodBodyAnalyser  mv)  {

    super(mv,  not(eq(VISIT_METHOD_INSN)),

                        not(eq(VISIT_INVOKE_DYNAMIC_INSN)),

                        not(eq(VISIT_JUMP_INSN)));

}
Оптимизации
public  int  calculateMargin(Order  order){

    return  order.grossPrice()  /  order.salesPrice()  *  100;

}
public  int  grossPrice()  {

    return  gross;

}
public  int  grossPrice();  
    Code:  
        0:  aload_0  
        1:  getfield  #2      //  Field  gross:I  
        4:  ireturn
Не вызывает других методов
Нет циклов
Можно игнорировать
44
Потоки
val  r  =  new  Runnable(){}  
val  t  =  new  Thread(r)  
t.start()
t.join()
public  void  run()  {  
    doSomething();  
}
Runnable  r  =  new  Runnable(){

    public  void  run()  {  
        doSomething();

    }

};  
Runnable  r  =  new  Runnable(){

    private  WeakReference<Context>  ctx;  
    public  void  run()  {  
        Context  sink  =  ctx.getChildContext();

        sink  =  Sinks.startAsync(sink);



        try  {

            doSomething();

        }  finally  {

            Sinks.stopAsync(sink);

        }

    }

};  
JPoint 2016 - Etudes of DIY Java profiler
Внешние вызовы
JDBC
> Вариант 1. Proxy
> Вариант 2. Список известных нам классов. Что
знаем, то и инструментируем.
> Вариант 3. Есть известные интерфейсы -
сканируем иерархию классов
Привет, ClassCastException
Замедление старта приложения
Привет, DB2
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
Распределённые
приложения
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
Что уже есть?
> Разные $$$ APM-продукты: Dynatrace, AppDynamics
> Dapper
> ZipKin
http://research.google.com/pubs/pub36356.html
http://zipkin.io
NB! Требуется серверная часть
JPoint 2016 - Etudes of DIY Java profiler
Request headers
GET /supplements/ HTTP/1.1
X-XRebel-Event-Id: 6a61eb15-23f1-40ea-a30d-2f62d616a196
X-XRebel-Version: 3.0.2
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.8.0_51
Host: localhost:8080
Response headers
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-XRebel-Event-Id: c5603281-a745-416e-8f27-92ba47c76b26
X-XRebel-Version: 3.0.2
X-xr-bookmark: 3197589b-bc9f-44ab-a2aa-12557a39b090
Content-Type: application/json;charset=ISO-8859-1
JPoint 2016 - Etudes of DIY Java profiler
This slide is intentionally left blank
JPoint 2016 - Etudes of DIY Java profiler
@antonarhipov
anton@zeroturnaround.com
https://speakerdeck.com/antonarhipov
https://www.slideshare.net/arhan

More Related Content

PDF
Joker 2016 - Bytecode 101
Anton Arhipov
 
PDF
JPoint 2016 - Bytecode
Anton Arhipov
 
PDF
JPoint 2015 - Javassist на службе Java-разработчика
Anton Arhipov
 
PDF
Борис Сазонов, RAII потоки и CancellationToken в C++
Sergey Platonov
 
PDF
Something about Golang
Anton Arhipov
 
PDF
Java 8 puzzlers
Evgeny Borisov
 
PDF
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Sergey Platonov
 
PPTX
Александр Фокин, Рефлексия в C++
Sergey Platonov
 
Joker 2016 - Bytecode 101
Anton Arhipov
 
JPoint 2016 - Bytecode
Anton Arhipov
 
JPoint 2015 - Javassist на службе Java-разработчика
Anton Arhipov
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Sergey Platonov
 
Something about Golang
Anton Arhipov
 
Java 8 puzzlers
Evgeny Borisov
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Sergey Platonov
 
Александр Фокин, Рефлексия в C++
Sergey Platonov
 

What's hot (20)

PPT
Mike ponomarenko java17-fork-v1.2
Alex Tumanoff
 
PDF
Component Inspector
Roman Dvornov
 
PDF
Павел Довгалюк, Обратная отладка
Sergey Platonov
 
PDF
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Sergey Platonov
 
PDF
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
Ontico
 
PDF
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
it-people
 
PPTX
Developing highload servers with Java
Andrei Pangin
 
PDF
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
Омские ИТ-субботники
 
PDF
RDSDataSource: Чистые тесты на Swift
RAMBLER&Co
 
PDF
Пользователь точно оценит! Повышение производительности мобильных приложений ...
Ontico
 
PDF
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Yauheni Akhotnikau
 
PDF
Антон Полухин, Немного о Boost
Sergey Platonov
 
PDF
RDSDataSource: Promises
RAMBLER&Co
 
PDF
Сладкое будущее: Phalcon и Zephir
CodeFest
 
PDF
Java 9: what is there beyond modularization
Ivan Krylov
 
PDF
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Sergey Platonov
 
PDF
Parallel STL
Evgeny Krutko
 
PPT
Alexander manuhin selenium_php_v2.0
matroskin1980
 
PDF
Сенцов Сергей "Приемы оптимизаций Desktop приложений"
Yulia Tsisyk
 
PDF
Превышаем скоросные лимиты с Angular 2
Oleksii Okhrymenko
 
Mike ponomarenko java17-fork-v1.2
Alex Tumanoff
 
Component Inspector
Roman Dvornov
 
Павел Довгалюк, Обратная отладка
Sergey Platonov
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Sergey Platonov
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
Ontico
 
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
it-people
 
Developing highload servers with Java
Andrei Pangin
 
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
Омские ИТ-субботники
 
RDSDataSource: Чистые тесты на Swift
RAMBLER&Co
 
Пользователь точно оценит! Повышение производительности мобильных приложений ...
Ontico
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Yauheni Akhotnikau
 
Антон Полухин, Немного о Boost
Sergey Platonov
 
RDSDataSource: Promises
RAMBLER&Co
 
Сладкое будущее: Phalcon и Zephir
CodeFest
 
Java 9: what is there beyond modularization
Ivan Krylov
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Sergey Platonov
 
Parallel STL
Evgeny Krutko
 
Alexander manuhin selenium_php_v2.0
matroskin1980
 
Сенцов Сергей "Приемы оптимизаций Desktop приложений"
Yulia Tsisyk
 
Превышаем скоросные лимиты с Angular 2
Oleksii Okhrymenko
 
Ad

Viewers also liked (20)

PDF
Devclub 01/2017 - (Не)адекватное Java-интервью
Anton Arhipov
 
PDF
Oredev 2015 - Taming Java Agents
Anton Arhipov
 
PDF
Riga Dev Day 2016 - Having fun with Javassist
Anton Arhipov
 
PDF
JavaOne 2015 - Having fun with Javassist
Anton Arhipov
 
PDF
Con-FESS 2015 - Having Fun With Javassist
Anton Arhipov
 
PDF
Introduction to Groovy
Anton Arhipov
 
PDF
Something about Golang
Anton Arhipov
 
PDF
import continuous.delivery.*
Anton Arhipov
 
PDF
Taming Java Agents
Anton Arhipov
 
PDF
Con-FESS 2015 - Is your profiler speaking to you?
Anton Arhipov
 
PDF
Improve your Developer Experiece using the WAS Liberty Profile with JRebel
Anton Arhipov
 
PPTX
NetBeans Plugin Development: JRebel Experience Report
Anton Arhipov
 
PDF
Загрузчики классов в Java - коллекция граблей
Anton Arhipov
 
PDF
Voxxed Days Vilnius 2015 - Having fun with Javassist
Anton Arhipov
 
PPTX
Jenkins Evolutions - JEEConf 2012
Anton Arhipov
 
PPTX
Do it yourself profiler
Vladimir Sitnikov
 
PDF
Scala magic
Alexander Podkhalyuzin
 
PDF
Under the hood of scala implicits (Scala eXchange 2014)
Alexander Podkhalyuzin
 
PPTX
Scala для всех (РИФ 2015)
Арсений Жижелев
 
Devclub 01/2017 - (Не)адекватное Java-интервью
Anton Arhipov
 
Oredev 2015 - Taming Java Agents
Anton Arhipov
 
Riga Dev Day 2016 - Having fun with Javassist
Anton Arhipov
 
JavaOne 2015 - Having fun with Javassist
Anton Arhipov
 
Con-FESS 2015 - Having Fun With Javassist
Anton Arhipov
 
Introduction to Groovy
Anton Arhipov
 
Something about Golang
Anton Arhipov
 
import continuous.delivery.*
Anton Arhipov
 
Taming Java Agents
Anton Arhipov
 
Con-FESS 2015 - Is your profiler speaking to you?
Anton Arhipov
 
Improve your Developer Experiece using the WAS Liberty Profile with JRebel
Anton Arhipov
 
NetBeans Plugin Development: JRebel Experience Report
Anton Arhipov
 
Загрузчики классов в Java - коллекция граблей
Anton Arhipov
 
Voxxed Days Vilnius 2015 - Having fun with Javassist
Anton Arhipov
 
Jenkins Evolutions - JEEConf 2012
Anton Arhipov
 
Do it yourself profiler
Vladimir Sitnikov
 
Under the hood of scala implicits (Scala eXchange 2014)
Alexander Podkhalyuzin
 
Scala для всех (РИФ 2015)
Арсений Жижелев
 
Ad

Similar to JPoint 2016 - Etudes of DIY Java profiler (9)

PDF
CPU Performance in Java.
Dzmitry Hil
 
PDF
Java Platform Performance BoF
Dmitry Buzdin
 
PDF
Распространённые ошибки оценки производительности .NET-приложений
Andrey Akinshin
 
PDF
Распространённые ошибки оценки производительности .NET-приложений
Mikhail Shcherbakov
 
PPTX
Solit 2013, JVM изнутри: оптимизация и профилирование, Слисенко Константин
solit
 
PDF
Thread
Alexander Rusin
 
PDF
In the sun.misc.Unsafe bowels
Alexander Efremenkov
 
PDF
Продолжаем говорить о микрооптимизациях .NET-приложений
Andrey Akinshin
 
PDF
BigMemory - работа с сотнями миллионов бизнес-объектов / Дмитрий Хмаладзе (Ag...
Ontico
 
CPU Performance in Java.
Dzmitry Hil
 
Java Platform Performance BoF
Dmitry Buzdin
 
Распространённые ошибки оценки производительности .NET-приложений
Andrey Akinshin
 
Распространённые ошибки оценки производительности .NET-приложений
Mikhail Shcherbakov
 
Solit 2013, JVM изнутри: оптимизация и профилирование, Слисенко Константин
solit
 
In the sun.misc.Unsafe bowels
Alexander Efremenkov
 
Продолжаем говорить о микрооптимизациях .NET-приложений
Andrey Akinshin
 
BigMemory - работа с сотнями миллионов бизнес-объектов / Дмитрий Хмаладзе (Ag...
Ontico
 

More from Anton Arhipov (20)

PDF
JavaZone 2022 - Building Kotlin DSL.pdf
Anton Arhipov
 
PDF
Idiomatic kotlin
Anton Arhipov
 
PDF
TechTrain 2019 - (Не)адекватное техническое интервью
Anton Arhipov
 
PDF
Build pipelines with TeamCity
Anton Arhipov
 
PDF
Build pipelines with TeamCity
Anton Arhipov
 
PDF
Devoxx Ukraine 2018 - Kotlin DSL in under an hour
Anton Arhipov
 
PDF
GeeCON Prague 2018 - Kotlin DSL in under an hour
Anton Arhipov
 
PDF
Build pipelines with TeamCity and Kotlin DSL
Anton Arhipov
 
PDF
Build pipelines with TeamCity
Anton Arhipov
 
PDF
JavaDay Kiev 2017 - Integration testing with TestContainers
Anton Arhipov
 
PDF
GeeCON Prague 2017 - TestContainers
Anton Arhipov
 
PDF
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
PDF
JavaOne 2017 - TestContainers: integration testing without the hassle
Anton Arhipov
 
PDF
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
PDF
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
Anton Arhipov
 
PDF
JUG.ua 20170225 - Java bytecode instrumentation
Anton Arhipov
 
PDF
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
PDF
GeeCON 2017 - TestContainers. Integration testing without the hassle
Anton Arhipov
 
PDF
JEEConf 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
PDF
JEEConf 2017 - Having fun with Javassist
Anton Arhipov
 
JavaZone 2022 - Building Kotlin DSL.pdf
Anton Arhipov
 
Idiomatic kotlin
Anton Arhipov
 
TechTrain 2019 - (Не)адекватное техническое интервью
Anton Arhipov
 
Build pipelines with TeamCity
Anton Arhipov
 
Build pipelines with TeamCity
Anton Arhipov
 
Devoxx Ukraine 2018 - Kotlin DSL in under an hour
Anton Arhipov
 
GeeCON Prague 2018 - Kotlin DSL in under an hour
Anton Arhipov
 
Build pipelines with TeamCity and Kotlin DSL
Anton Arhipov
 
Build pipelines with TeamCity
Anton Arhipov
 
JavaDay Kiev 2017 - Integration testing with TestContainers
Anton Arhipov
 
GeeCON Prague 2017 - TestContainers
Anton Arhipov
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
JavaOne 2017 - TestContainers: integration testing without the hassle
Anton Arhipov
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
Anton Arhipov
 
JUG.ua 20170225 - Java bytecode instrumentation
Anton Arhipov
 
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
Anton Arhipov
 
JEEConf 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 
JEEConf 2017 - Having fun with Javassist
Anton Arhipov
 

JPoint 2016 - Etudes of DIY Java profiler

  • 1. Как сделать профилировщик из палок... и других подручных средств @antonarhipov JPoint 2016, Москва
  • 4. Batch / ETL Исходные данные : ~10k записей Результат: ~20M записей j.u.Date / j.u.Calendar Java 1.4 HP-UX Первый запуск: 25 ч :-( После оптимизаций: 10 ч После изменения дизайна: 30 мин :-) 2005 История одного проекта
  • 5. Тот самый случай когда выглядишь умным, но чувствуешь себя полным ДУРАКОМ
  • 7. Как и когда вы используете профилировщик?
  • 8. QA Staging Production Тормозит! Тесты показывают падение производительности Всё плохо!
  • 10. > Chrome DevTools > FireBug > YSlow > … > XRebel “Проактивные” инструменты
  • 11. > Пользовательский интерфейс > Профилирование приложения > Трассировка внешних вызовов > Трассировка потоков > Распределённые приложения Этюды профайлероводства
  • 14. package org.apache.catalina.connector; public class Response implements HttpServletResponse { public ServletOutputStream getOutputStream() throws IOException { if (this.usingWriter) { throw new IllegalStateException(…)); } this.usingOutputStream = true; if (this.outputStream == null) { this.outputStream = new CoyoteOutputStream(this.outputBuffer); } return this.outputStream; } Javassist
  • 15. package org.apache.catalina.connector; public class Response implements HttpServletResponse { public ServletOutputStream getOutputStream() throws IOException { if (this.usingWriter) { throw new IllegalStateException(…)); } this.usingOutputStream = true; if (this.outputStream == null) { this.outputStream = new CoyoteOutputStream(this.outputBuffer); } return this.outputStream; }    ctClass.getDeclaredMethod("getOutputStream").insertAfter(
        "if  ("  +  _interceptor  +  "  !=  null)  {"  +
        "    $_  =  (ServletOutputStream)"  +  _interceptor  +  ".getOutputStream($_);"  +
        "}");   Javassist
  • 16. package org.apache.catalina.connector; public class Response implements HttpServletResponse { public ServletOutputStream getOutputStream() throws IOException { if (this.usingWriter) { throw new IllegalStateException(…)); } this.usingOutputStream = true; if (this.outputStream == null) { this.outputStream = new CoyoteOutputStream(this.outputBuffer); } if (_interceptor != null) { this.outputStream = (ServletOutputStream)_interceptor .getOutputStream(this.outputStream); } return this.outputStream; }
  • 18. Windows: Ctrl+Break *nix: kill -3 PID "http-nio-8080-exec-1"#40 daemon prio=5 os_prio=31 tid=0x00007fd7057ed800 nid=0x7313 runnable java.lang.Thread.State: RUNNABLE at o.s.s.p.w.OwnerController.processFindForm(OwnerController.java:89) at s.r.NativeMethodAccessorImpl.invoke0(Native Method) at s.r.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at s.r.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at j.l.r.Method.invoke(Method.java:497) Сэмплирование
  • 19. Интервал : 20 мс Кол-во сэмплов: 4
  • 20. Интервал : 1 мс Кол-во сэмплов: 100+
  • 24. Java Mission Control Java 7u40 Honest Profiler https://github.com/RichardWarburton/honest-profiler AsyncGetCallTrace JVMTI Как обуздать safepoint bias?
  • 26. public  void  businessMethod()  {
    long  start  =  System.currentTimeMillis();
    work();
    Profiler.log(System.currentTimeMillis()-­‐start);   }
  • 27. public  void  businessMethod()  {
    long  start  =  System.nanoTime();
    work();
    Profiler.log(System.nanoTime()-­‐start);
 }
  • 28. public  void  businessMethod()  {
    Profiler.start("businessMethod");      try  {
        work();
    }  finally  {
        Profiler.log("businessMethod");
    }
 }
  • 29. System.nanoTime Параллельный поток для замеров времени sleep-wakup-update yield-wakup-update busy-loop-update
  • 30. class  Profiler  {   
    Loop  loop;
 
    public  static  void  start(String  method)  {
        long  now  =  loop.getTime();          …
    }  
  • 31. public  class  Loop  implements  Runnable  {
        private  volatile  long  time;
        public  void  run()  {
                while  (running)  {
                        time  =  System.nanoTime();
                        sleep();
                }
        }          public  final  long  getTime()  {
                return  time;
        }   Busy Loop
  • 32. Наносекунды в приближении Чтение памяти имеет цену Занимает циклы процессора = ns Каждый слой ПО добавляет к цене. JVM, JNI, OS, HW http://shipilev.net/blog/2014/nanotrusting-nanotime/ Nanotrusting the NanoTime
  • 33. Наносекунды в приближении http://shipilev.net/blog/2014/nanotrusting-nanotime/ Nanotrusting the NanoTime granularity_nanotime: 26.300 +- 0.205 ns latency_nanotime: 25.542 +- 0.024 ns granularity_nanotime: 29.322 +- 1.293 ns latency_nanotime: 29.910 +- 1.626 ns granularity_nanotime: 371,419 +- 1,541 ns latency_nanotime: 14,415 +- 0,389 ns Linux Solaris Windows
  • 34. Thread.sleep Win8: 1.7 мс (JNI + socket poll: 1.0 ms ) Linux: 0.1 мс OS X: 0.05 мс Всё таки загружает ядро процессора на 25-50% Thread.yield Планировшик в Windows может проигнорировать наш поток в случае высокой загрузки процессора
  • 35. public  class  Loop  implements  Runnable  {
        private  volatile  long  time;
        public  void  run()  {
                while  (running)  {
                        time  =  System.nanoTime();
                        sleep();
                }
        }          private  void  sleep()  {
            if  (!MiscUtil.isWindows())  {
                  Thread.yield();
            }
        } Busy Loop
  • 36. Busy Loop public  class  Loop  implements  Runnable  {
        private  volatile  long  time;
        public  void  run()  {
                while  (running)  {
                        time  =  System.nanoTime();
                        sleep();
                }
        }          private  void  sleep()  {
            if  (!MiscUtil.isWindows())  {
                  Thread.yield();
            }
        }
  • 37. Busy Loop public  class  Loop  implements  Runnable  {
        private  volatile  long  time;
        public  void  run()  {
                while  (running)  {
                        time  =  System.nanoTime();
                        sleep();
                }
        }          private  void  sleep()  {
            if  (!MiscUtil.isWindows())  {
                  Thread.yield();
            }
        }
  • 42. Оптимизации LeafMethodAnalyser(AbstractMethodBodyAnalyser  mv)  {
    super(mv,  not(eq(VISIT_METHOD_INSN)),
                        not(eq(VISIT_INVOKE_DYNAMIC_INSN)),
                        not(eq(VISIT_JUMP_INSN)));
 }
  • 43. Оптимизации public  int  calculateMargin(Order  order){
    return  order.grossPrice()  /  order.salesPrice()  *  100;
 } public  int  grossPrice()  {
    return  gross;
 } public  int  grossPrice();      Code:          0:  aload_0          1:  getfield  #2      //  Field  gross:I          4:  ireturn Не вызывает других методов Нет циклов Можно игнорировать
  • 45. val  r  =  new  Runnable(){}   val  t  =  new  Thread(r)   t.start() t.join() public  void  run()  {      doSomething();   }
  • 46. Runnable  r  =  new  Runnable(){
    public  void  run()  {          doSomething();
    }
 };  
  • 47. Runnable  r  =  new  Runnable(){
    private  WeakReference<Context>  ctx;      public  void  run()  {          Context  sink  =  ctx.getChildContext();
        sink  =  Sinks.startAsync(sink);
 
        try  {
            doSomething();
        }  finally  {
            Sinks.stopAsync(sink);
        }
    }
 };  
  • 50. JDBC > Вариант 1. Proxy > Вариант 2. Список известных нам классов. Что знаем, то и инструментируем. > Вариант 3. Есть известные интерфейсы - сканируем иерархию классов Привет, ClassCastException Замедление старта приложения Привет, DB2
  • 56. Что уже есть? > Разные $$$ APM-продукты: Dynatrace, AppDynamics > Dapper > ZipKin http://research.google.com/pubs/pub36356.html http://zipkin.io NB! Требуется серверная часть
  • 58. Request headers GET /supplements/ HTTP/1.1 X-XRebel-Event-Id: 6a61eb15-23f1-40ea-a30d-2f62d616a196 X-XRebel-Version: 3.0.2 Cache-Control: no-cache Pragma: no-cache User-Agent: Java/1.8.0_51 Host: localhost:8080 Response headers HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-XRebel-Event-Id: c5603281-a745-416e-8f27-92ba47c76b26 X-XRebel-Version: 3.0.2 X-xr-bookmark: 3197589b-bc9f-44ab-a2aa-12557a39b090 Content-Type: application/json;charset=ISO-8859-1
  • 60. This slide is intentionally left blank