JPoint 2016 - Etudes of DIY Java profiler
-
Upload
anton-arhipov -
Category
Technology
-
view
749 -
download
1
Transcript of JPoint 2016 - Etudes of DIY Java profiler
![Page 1: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/1.jpg)
Как сделать профилировщикиз палок... и других подручных средств
@antonarhipov
JPoint 2016, Москва
![Page 2: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/2.jpg)
![Page 3: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/3.jpg)
![Page 4: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/4.jpg)
Batch / ETL
Исходные данные : ~10k записейРезультат: ~20M записейj.u.Date / j.u.Calendar
Java 1.4 HP-UX
Первый запуск: 25 ч :-(После оптимизаций: 10 ч После изменения дизайна: 30 мин :-)
2005
История одного проекта
![Page 5: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/5.jpg)
Тот самый случай когда выглядишь умным, но чувствуешь себя полным ДУРАКОМ
![Page 6: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/6.jpg)
https://twitter.com/shipilev/status/578193813946134529
![Page 7: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/7.jpg)
Как и когда вы используете профилировщик?
![Page 8: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/8.jpg)
QA Staging Production
Тормозит!
Тесты показывают падение производительности
Всё плохо!
![Page 9: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/9.jpg)
![Page 10: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/10.jpg)
> Chrome DevTools
> FireBug
> YSlow
> …
> XRebel
“Проактивные” инструменты
![Page 11: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/11.jpg)
> Пользовательский интерфейс
> Профилирование приложения
> Трассировка внешних вызовов
> Трассировка потоков
> Распределённые приложения
Этюды профайлероводства
![Page 12: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/12.jpg)
UI & UX
![Page 13: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/13.jpg)
![Page 14: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/14.jpg)
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
![Page 15: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/15.jpg)
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
![Page 16: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/16.jpg)
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; }
![Page 17: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/17.jpg)
Куда уходит время?
![Page 18: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/18.jpg)
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)
Сэмплирование
![Page 19: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/19.jpg)
Интервал : 20 мс
Кол-во сэмплов: 4
![Page 20: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/20.jpg)
Интервал : 1 мс
Кол-во сэмплов: 100+
![Page 21: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/21.jpg)
main()foo()bar()baz()
![Page 22: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/22.jpg)
Safepoints
main()foo()bar()baz()
![Page 23: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/23.jpg)
Safepoints
main()foo()bar()baz()
![Page 24: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/24.jpg)
Java Mission ControlJava 7u40
Honest Profiler
https://github.com/RichardWarburton/honest-profiler
AsyncGetCallTraceJVMTI
Как обуздать safepoint bias?
![Page 25: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/25.jpg)
main()foo()bar()baz()
Инструментирующий профилировщик
Высокие накладные расходы для быстрых методов
![Page 26: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/26.jpg)
public void businessMethod() { long start = System.currentTimeMillis(); work(); Profiler.log(System.currentTimeMillis()-‐start); }
![Page 27: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/27.jpg)
public void businessMethod() { long start = System.nanoTime(); work(); Profiler.log(System.nanoTime()-‐start);}
![Page 28: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/28.jpg)
public void businessMethod() { Profiler.start("businessMethod"); try { work(); } finally { Profiler.log("businessMethod"); }}
![Page 29: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/29.jpg)
System.nanoTime
Параллельный поток для замеров времениsleep-wakup-updateyield-wakup-updatebusy-loop-update
![Page 30: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/30.jpg)
class Profiler { Loop loop; public static void start(String method) { long now = loop.getTime(); … }
![Page 31: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/31.jpg)
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
![Page 32: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/32.jpg)
Наносекунды в приближении
Чтение памяти имеет цену Занимает циклы процессора = ns
Каждый слой ПО добавляет к цене. JVM, JNI, OS, HW
http://shipilev.net/blog/2014/nanotrusting-nanotime/
Nanotrusting the NanoTime
![Page 33: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/33.jpg)
Наносекунды в приближении
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
![Page 34: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/34.jpg)
Thread.sleepWin8: 1.7 мс (JNI + socket poll: 1.0 ms )Linux: 0.1 мсOS X: 0.05 мсВсё таки загружает ядро процессора на 25-50%
Thread.yieldПланировшик в Windows может проигнорировать наш поток в случае высокой загрузки процессора
![Page 35: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/35.jpg)
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
![Page 36: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/36.jpg)
Busy Looppublic 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(); } }
![Page 37: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/37.jpg)
Busy Looppublic 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(); } }
![Page 38: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/38.jpg)
main()foo()
bar()baz()
234
![Page 39: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/39.jpg)
main()foo()
bar()baz()
235
boo()
Дисбаланс ошибки для веток с разной глубиной
![Page 40: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/40.jpg)
![Page 41: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/41.jpg)
![Page 42: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/42.jpg)
Оптимизации
LeafMethodAnalyser(AbstractMethodBodyAnalyser mv) { super(mv, not(eq(VISIT_METHOD_INSN)), not(eq(VISIT_INVOKE_DYNAMIC_INSN)), not(eq(VISIT_JUMP_INSN)));}
![Page 43: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/43.jpg)
Оптимизации 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
Не вызывает других методов
Нет циклов
Можно игнорировать
![Page 44: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/44.jpg)
44
Потоки
![Page 45: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/45.jpg)
val r = new Runnable(){} val t = new Thread(r) t.start()
t.join()
public void run() { doSomething(); }
![Page 46: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/46.jpg)
Runnable r = new Runnable(){ public void run() { doSomething(); }};
![Page 47: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/47.jpg)
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); } }};
![Page 48: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/48.jpg)
![Page 49: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/49.jpg)
Внешние вызовы
![Page 50: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/50.jpg)
JDBC> Вариант 1. Proxy
> Вариант 2. Список известных нам классов. Что знаем, то и инструментируем.
> Вариант 3. Есть известные интерфейсы - сканируем иерархию классов
Привет, ClassCastException
Замедление старта приложения
Привет, DB2
![Page 51: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/51.jpg)
![Page 52: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/52.jpg)
![Page 53: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/53.jpg)
Распределённые приложения
![Page 54: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/54.jpg)
![Page 55: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/55.jpg)
![Page 56: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/56.jpg)
Что уже есть?
> Разные $$$ APM-продукты: Dynatrace, AppDynamics
> Dapper
> ZipKin
http://research.google.com/pubs/pub36356.html
http://zipkin.io
NB! Требуется серверная часть
![Page 57: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/57.jpg)
![Page 58: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/58.jpg)
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
![Page 59: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/59.jpg)
![Page 60: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/60.jpg)
This slide is intentionally left blank
![Page 61: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/61.jpg)
![Page 62: JPoint 2016 - Etudes of DIY Java profiler](https://reader033.fdocuments.net/reader033/viewer/2022042619/587c17d81a28abb5068b49f3/html5/thumbnails/62.jpg)
@antonarhipov
https://speakerdeck.com/antonarhipov
https://www.slideshare.net/arhan