Производительность open source решений
TRANSCRIPT
![Page 1: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/1.jpg)
© Netcracker 2016 1
Производительность open source решений
Владимир СитниковJPoint 2016
![Page 2: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/2.jpg)
© Netcracker 2016 2
• Владимир Ситников• Инженер по производительности в Netcracker, 10 лет
• [email protected]• @VladimirSitnikv
Кто я
![Page 3: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/3.jpg)
© Netcracker 2016 3
• Spring• Cglib• Pgjdbc• HornetQ• Wildfly• Jenkins
План
![Page 4: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/4.jpg)
© Netcracker 2016 4
План
Наш любимый enterprise продукт
![Page 5: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/5.jpg)
© Netcracker 2016 5
Внедряем Spring в сжатые сроки
Монолитspring
![Page 6: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/6.jpg)
© Netcracker 2016 6
Внедряем Spring в сжатые сроки
Монолитspring
![Page 7: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/7.jpg)
© Netcracker 2016 7
Внедряем Spring в сжатые сроки
CoreSecurity
UI
![Page 8: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/8.jpg)
© Netcracker 2016 8
Внедряем Spring в сжатые сроки
CoreSecurity
UI
![Page 9: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/9.jpg)
© Netcracker 2016 9
Внедряем Spring в сжатые сроки
CoreSecurity
UI
![Page 10: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/10.jpg)
© Netcracker 2016 10
• Когда нужен бин, то выполняем
beanFactory.getBean(Security.class)
В UI spring пока не наступил
![Page 11: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/11.jpg)
© Netcracker 2016 11
• Когда нужен бин, то выполняем
beanFactory.getBean(Security.class)
• Но где взять beanFactory?
В UI spring пока не наступил
![Page 12: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/12.jpg)
© Netcracker 2016 12
• Когда нужен бин, то выполняем
beanFactory.getBean(Security.class)
• Но где взять beanFactory?
• Правильно, Паблик Морозов поможет нам
В UI spring пока не наступил
![Page 13: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/13.jpg)
© Netcracker 2016 13
public class AppContext implements BeanFactoryAware { static public BeanFactory beanFactory; ...
Получаем бин
![Page 14: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/14.jpg)
© Netcracker 2016 14
public class AppContext implements BeanFactoryAware { static public BeanFactory beanFactory; ...
AppContext.beanFactory.getBean(Security.class)
Получаем бин
![Page 15: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/15.jpg)
© Netcracker 2016 15
• Работает
Spring.getBean
![Page 16: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/16.jpg)
© Netcracker 2016 16
• Работает• Но медленно-медленно
Spring.getBean
![Page 17: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/17.jpg)
© Netcracker 2016 17
• Работает• Но медленно-медленно• На getBean и 50% времени может уходить
Spring.getBean
![Page 18: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/18.jpg)
© Netcracker 2016 18
• Java Flight Recorder
Подходящие для анализа инструменты
![Page 19: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/19.jpg)
© Netcracker 2016 19
• Java Flight Recorder• kill -3 profiler (poormansprofiler.org)
Подходящие для анализа инструменты
![Page 20: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/20.jpg)
© Netcracker 2016 20
• Java Flight Recorder• kill -3 profiler (poormansprofiler.org)• Инструментирующий профилировщик. Например самописный, настроенный на getBean
Подходящие для анализа инструменты
![Page 21: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/21.jpg)
© Netcracker 2016 21
160 секунд на getBean. Здорово?
![Page 22: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/22.jpg)
© Netcracker 2016 22
160 секунд на getBean. Здорово?
• Java 8 / Spring 4.1.7
![Page 23: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/23.jpg)
© Netcracker 2016 23
• SPR-6870 Cache by-type lookups in DefaultListableBeanFactory
Проверяем известные проблемы
![Page 24: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/24.jpg)
© Netcracker 2016 24
• SPR-6870 Cache by-type lookups in DefaultListableBeanFactory
Проверяем известные проблемы
ЯЗЬ!!!
![Page 25: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/25.jpg)
© Netcracker 2016 25
• SPR-6870 Cache by-type lookups in DefaultListableBeanFactory
• Fix version: 3.2 M1, а у нас 4.1+
Проверяем известные проблемы
![Page 26: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/26.jpg)
© Netcracker 2016 26
Flight Recorder, allocations in new TLAB
![Page 27: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/27.jpg)
© Netcracker 2016 27
protected Object getCacheKey( Class<?> beanClass, String beanName) { return beanClass.getName() + "_" + beanName;}
AbstractAutoProxyCreator
![Page 28: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/28.jpg)
© Netcracker 2016 28
protected Object getCacheKey( Class<?> beanClass, String beanName) { return beanClass.getName() + "_" + beanName;}
AbstractAutoProxyCreator
![Page 29: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/29.jpg)
© Netcracker 2016 29
protected Object getCacheKey( Class<?> beanClass, String beanName) { return beanName == null ? beanClass : ...;}
github.com/spring-projects/spring-framework/pull/913
AbstractAutoProxyCreator
![Page 30: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/30.jpg)
© Netcracker 2016 30
public class SharedSecrets { @Inject public Security security; @PostConstruct public void init() { INSTANCE = this; }
public static volatile SharedSecrets INSTANCE;
Как выжить без обновления Spring?
![Page 31: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/31.jpg)
© Netcracker 2016 31
• Не стоит злоупотреблять prototype bean’ами. Если singleton, то singleton
Prototype vs singleton
![Page 32: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/32.jpg)
© Netcracker 2016 32
• Не стоит злоупотреблять prototype bean’ами. Если singleton, то singleton
• Замена getBean на javax.inject.Provider<...> лишь ухудшает время работы
•
Prototype vs singleton
![Page 33: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/33.jpg)
© Netcracker 2016 33
@Pointcut( "execution( public* my.service.*ServiceImpl.*(..))”)
Spring AOP
![Page 34: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/34.jpg)
© Netcracker 2016 34
• OutOfMemory: perm gen
Spring AOP
![Page 35: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/35.jpg)
© Netcracker 2016 35
• OutOfMemory: perm gen• В хипдампе куча java.lang.reflect.Method
Spring AOP
![Page 36: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/36.jpg)
© Netcracker 2016 36
• OutOfMemory: perm gen• В хипдампе куча java.lang.reflect.Method• Method’ы занимают 100-500MiB
Spring AOP
![Page 37: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/37.jpg)
© Netcracker 2016 37
• OutOfMemory: perm gen• В хипдампе куча java.lang.reflect.Method• Method’ы занимают 100-500MiB• Все они лежат в AspectJExpressionPointcut
Spring AOP
![Page 38: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/38.jpg)
© Netcracker 2016 38
@Pointcut( "execution( public* my.service.*ServiceImpl.*(..))”)
Spring AOP
![Page 39: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/39.jpg)
© Netcracker 2016 39
• Решение: добавлять within(my.package.service.business..*)
Spring AOP vs AspectJ
![Page 40: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/40.jpg)
© Netcracker 2016 40
• Решение: добавлять within(my.package.service.business..*)
• Разумеется, AspectJ рекомендуют использовать within всегда: http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg10969.html
•
Spring AOP vs AspectJ
![Page 41: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/41.jpg)
© Netcracker 2016 41
• Cglib используется много где: рукотворный код, тот же Spring
Cglib
![Page 42: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/42.jpg)
© Netcracker 2016 42
• Cglib используется много где: рукотворный код, тот же Spring
• Наверняка уже всё исправлено давным-давно
Cglib
![Page 43: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/43.jpg)
© Netcracker 2016 43
• Cglib используется много где: рукотворный код, тот же Spring
• Наверняка уже всё исправлено давным-давно
• Наверняка туда давно никто не заглядывал
Cglib
![Page 44: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/44.jpg)
© Netcracker 2016 44
@Benchmarkpublic Object newProxy() { return Beans.newProxy(Beans.class);}
Cglib: замеряем
![Page 45: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/45.jpg)
© Netcracker 2016 45
Cglib 3.10
2000400060008000
1000012000140001600018000
1 поток 2 потока 4 потока 8 потоков
Замеры Cglib, μs/op
Бы
стре
е
![Page 46: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/46.jpg)
© Netcracker 2016 46
Cglib 3.1 Cglib 3.2.20
2000400060008000
1000012000140001600018000
1 поток 2 потока 4 потока 8 потоков
Замеры Cglib, μs/op
Бы
стре
е
![Page 47: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/47.jpg)
© Netcracker 2016 47
Benchmark ScorenewProxy 2.1 ± 0.3 μs/opnewProxy.alloc.rate 1240 B/op
Стало newProxy 0.14 ± 0.02 μs/opnewProxy.alloc.rate 256 B/op
Cglib 3.2.2: ждём в очередном Spring
![Page 48: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/48.jpg)
© Netcracker 2016 48
• Skip finalize while building proxyhttps://github.com/cglib/cglib/pull/51
• Concurrent cache of generated classeshttps://github.com/cglib/cglib/pull/53
План захвата Cglib
![Page 49: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/49.jpg)
© Netcracker 2016 49
• А, может, ну его этот cglib, есть же быстрый ByteBuddy?
Но есть же ByteBuddy
![Page 50: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/50.jpg)
© Netcracker 2016 50
• А, может, ну его этот cglib, есть же быстрый ByteBuddy?
@Benchmarkpublic ExampleClass benchmarkCglib() { Enhancer enhancer = new Enhancer(); enhancer.setUseCache(false);
ByteBuddy, jmh тест
![Page 51: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/51.jpg)
© Netcracker 2016 51
• А, может, ну его этот cglib, есть же быстрый ByteBuddy?
@Benchmarkpublic ExampleClass benchmarkCglib() { Enhancer enhancer = new Enhancer(); enhancer.setUseCache(false);
ByteBuddy, jmh тест
![Page 52: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/52.jpg)
© Netcracker 2016 52
• JMH тесты в ByteBuddy показывают скорость создания классов
• Постоянно создавать классы нехорошо• Значит, нужно измерять скорость кэшированного обращения
ByteBuddy, jmh тест
![Page 53: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/53.jpg)
© Netcracker 2016 53
• КО: «Бери pgjdbc»
Подключаемся к PostgreSQL
![Page 54: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/54.jpg)
© Netcracker 2016 54
• КО: «Бери pgjdbc»• КО: «Используй batch statements»
Подключаемся к PostgreSQL
![Page 55: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/55.jpg)
© Netcracker 2016 55
• КО: «Бери pgjdbc»• КО: «Используй batch statements»• Что может пойти не так?
Подключаемся к PostgreSQL
![Page 56: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/56.jpg)
© Netcracker 2016 56
Connection con = ...;PreparedStatement ps = con.prepareStatement("SELECT..."); ...ps.close();
PreparedStatement
![Page 57: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/57.jpg)
© Netcracker 2016 57
Connection con = ...;PreparedStatement ps = con.prepareStatement("SELECT..."); ...ps.close();
PreparedStatement
![Page 58: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/58.jpg)
© Netcracker 2016 58
PARSE S_1 as ...; // con.prepareStmt BIND/EXECDEALLOCATE // ps.close()PARSE S_2 as ...; BIND/EXECDEALLOCATE // ps.close()
Работа с PostgreSQL курильщика
![Page 59: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/59.jpg)
© Netcracker 2016 59
PARSE S_1 as ...; BIND/EXEC BIND/EXEC BIND/EXEC BIND/EXEC BIND/EXEC ...DEALLOCATE
Работа с PostgreSQL здорового человека
![Page 60: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/60.jpg)
© Netcracker 2016 60
PARSE S_1 as ...; 1 раз в жизни BIND/EXEC обработка REST BIND/EXEC BIND/EXEC ещё REST BIND/EXEC BIND/EXEC ...DEALLOCATE желательно «никогда»DEALLOCATE
Работа с PostgreSQL здорового человека
![Page 61: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/61.jpg)
© Netcracker 2016 61
Вывод: чтобы работало быстрее, закрывать statement’ы не нужноps = con.prepareStatement(...)ps.execueQuery();ps = con.prepareStatement(...)ps.execueQuery();...
Счастливые statement’ов не закрывают
![Page 62: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/62.jpg)
© Netcracker 2016 62
Вывод: чтобы работало быстрее, закрывать statement’ы не нужноps = con.prepare...ps.execueQuery();ps = con.prepare...ps.execueQuery();...
Счастливые statement’ов не закрывают
![Page 63: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/63.jpg)
© Netcracker 2016 63
@Benchmarkpublic Statement leakStatement() { return con.createStatement();}
pgjdbc < 9.4.1202, -Xmx128m, OracleJDK 1.8u40# Warmup Iteration 1: 1147,070 ns/op# Warmup Iteration 2: 12101,537 ns/op# Warmup Iteration 3: 90825,971 ns/op# Warmup Iteration 4: <failure>java.lang.OutOfMemoryError: GC overhead limit exceeded
OpenJDK: не все JRE одинаково полезны
![Page 64: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/64.jpg)
© Netcracker 2016 64
@Benchmarkpublic Statement leakStatement() { return con.createStatement();}pgjdbc >= 9.4.1202, -Xmx128m, OracleJDK 1.8u40# Warmup Iteration 1: 30 ns/op# Warmup Iteration 2: 27 ns/op...github.com/pgjdbc/pgjdbc/pull/299
Убираем finalize из класса PgConnection
![Page 65: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/65.jpg)
© Netcracker 2016 65
Вывод: чтобы работало быстро, нужно как-то кэшировать statement’ыps = con.prepareStatement("select id, name ...");ps.execueQuery();ps.close();ps2 = con.prepareStatement("select id, name ...");
Счастливые statement’ов не закрывают
![Page 66: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/66.jpg)
© Netcracker 2016 66
• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319
Кэш запросов в PgJDBC
![Page 67: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/67.jpg)
© Netcracker 2016 67
• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319
• Работает прозрачно для приложения
Кэш запросов в PgJDBC
![Page 68: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/68.jpg)
© Netcracker 2016 68
• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319
• Работает прозрачно для приложения• Скорость такая, что PL/PgSQL не нужен
Кэш запросов в PgJDBC
![Page 69: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/69.jpg)
© Netcracker 2016 69
• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319
• Работает прозрачно для приложения• Скорость такая, что PL/PgSQL не нужен• Server-prepare активируется после 5-го выполнения (prepareThreshold)
Кэш запросов в PgJDBC
![Page 70: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/70.jpg)
© Netcracker 2016 70
• Конечно, затраты planning time напрямую зависят от сложности запросов
Цифры где?
![Page 71: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/71.jpg)
© Netcracker 2016 71
• Конечно, затраты planning time напрямую зависят от сложности запросов
• У нас доходило до 20мс+ planning time на OLTP запросах: 10КиБ запрос, 170 строк explain
•
Цифры где?
![Page 72: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/72.jpg)
© Netcracker 2016 72
• Конечно, затраты planning time напрямую зависят от сложности запросов
• У нас доходило до 20мс+ planning time на OLTP запросах: 10КиБ запрос, 170 строк explain
• Стало ~0мс
Цифры где?
![Page 73: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/73.jpg)
© Netcracker 2016 73
Если типы параметров меняются, то server-prepared statement приходится менятьps.setInt(1, 42);...ps.setNull(1, Types.VARCHAR);
JDBC: Типы параметров
![Page 74: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/74.jpg)
© Netcracker 2016 74
Если типы параметров меняются, то server-prepared statement приходится менятьps.setInt(1, 42);...ps.setNull(1, Types.VARCHAR);
JDBC: Типы параметров
![Page 75: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/75.jpg)
© Netcracker 2016 75
• Вывод: даже у NULL’ов должен быть верный тип
JDBC: Тип параметров изменять нельзя
![Page 76: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/76.jpg)
© Netcracker 2016 76
• Вывод: даже у NULL’ов должен быть верный тип
• Ещё раз: setObject(1, null) использовать нельзя
JDBC: Тип параметров изменять нельзя
![Page 77: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/77.jpg)
© Netcracker 2016 77
• Перешли на prepared, и запрос замедлился в 5'000 раз. Как так?
Нежданчик
![Page 78: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/78.jpg)
© Netcracker 2016 78
• Перешли на prepared, и запрос замедлился в 5'000 раз. Как так?
Нежданчик
A. Бага C. ФичаB. Фича D. Бага
![Page 79: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/79.jpg)
© Netcracker 2016 79
https://gist.github.com/vlsi -> 01_plan_flipper.sql
select * from plan_flipper -- <- таблица where skewed = 0 -- 1 млн строк and non_skewed = 42 -- 20 строк
Нежданчик
![Page 80: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/80.jpg)
© Netcracker 2016 80
https://gist.github.com/vlsi -> 01_plan_flipper.sql0.1мс 1-е выполнение 0.05мс 2-е выполнение 0.05мс 3-е выполнение 0.05мс 4-е выполнение 0.05мс 5-е выполнение 250 мс 6-е выполнение
Нежданчик
![Page 81: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/81.jpg)
© Netcracker 2016 81
https://gist.github.com/vlsi -> 01_plan_flipper.sql0.1мс 1-е выполнение 0.05мс 2-е выполнение 0.05мс 3-е выполнение 0.05мс 4-е выполнение 0.05мс 5-е выполнение 250 мс 6-е выполнение
Нежданчик
![Page 82: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/82.jpg)
© Netcracker 2016 82
Запрещаем использование индекса через +0:select * from plan_flipper where skewed+0 = 0 ~ /*+no_index*/ and non_skewed = 42
Чиним
![Page 83: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/83.jpg)
© Netcracker 2016 83
Как сделать опциональные фичи?• NO_RESULTS• BOTH_ROWS_AND_STATUS• DESCRIBE_ONLY
Фичи
![Page 84: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/84.jpg)
© Netcracker 2016 84
Конечно, enum!enum ... {
NO_RESULTS,BOTH_ROWS_AND_STATUS,DESCRIBE_ONLY;
}
Фичи
![Page 85: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/85.jpg)
© Netcracker 2016 85
Конечно, enum!enum ... {
NO_RESULTS,BOTH_ROWS_AND_STATUS,DESCRIBE_ONLY;
}А на java 1.4?
Фичи
![Page 86: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/86.jpg)
© Netcracker 2016 86
В java 1.4, конечно, interface!interface ... {
int NO_RESULTS = 1;int BOTH_ROWS_AND_STATUS = 2;int DESCRIBE_ONLY = 4;
}
Фичи: java 1.4 наносит ответный удар
![Page 87: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/87.jpg)
© Netcracker 2016 87
Меняем 1 строку, и скорость работы batch insert возрастает в 10 раз:https://github.com/pgjdbc/pgjdbc/pull/380
- static int QUERY_FORCE_DESCRIBE_PORTAL = 128;+ static int QUERY_FORCE_DESCRIBE_PORTAL = 512;
Ужасы нашего городка
![Page 88: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/88.jpg)
© Netcracker 2016 88
Меняем 1 строку, и скорость работы batch insert возрастает в 10 раз:https://github.com/pgjdbc/pgjdbc/pull/380
- static int QUERY_FORCE_DESCRIBE_PORTAL = 128;+ static int QUERY_FORCE_DESCRIBE_PORTAL = 512;
// оказалось, значение 128 уже было занято static int QUERY_DISALLOW_BATCHING = 128;
Ужасы нашего городка
![Page 89: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/89.jpg)
© Netcracker 2016 89
• WildFly 8.2, JMS
HornetQ
![Page 90: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/90.jpg)
© Netcracker 2016 90
• WildFly 8.2, JMS• Всего ~100 JMS/сек
HornetQ
![Page 91: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/91.jpg)
© Netcracker 2016 91
• WildFly 8.2, JMS• Всего ~100 JMS/сек• 1 вызов sendMessage – 5-30 секунд
HornetQ
![Page 92: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/92.jpg)
© Netcracker 2016 92
at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCredits at com ... JMSSender.sendMessage
kill -3 профайлер
![Page 93: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/93.jpg)
© Netcracker 2016 93
at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCredits at com ... JMSSender.sendMessage
kill -3 профайлер
![Page 94: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/94.jpg)
© Netcracker 2016 94
at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCredits at com ... JMSSender.sendMessage
kill -3 профайлер
![Page 95: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/95.jpg)
© Netcracker 2016 95
at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCreditsat org.hornetq ... ClientProducerImpl.sendRegularMessage at com ... JMSSender.sendMessage
kill -3 профайлер
![Page 96: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/96.jpg)
© Netcracker 2016 96
at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCreditsat org.hornetq ... ClientProducerImpl.sendRegularMessageat org.hornetq ... ClientProducerImpl.doSend at com ... JMSSender.sendMessage
kill -3 профайлер
![Page 97: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/97.jpg)
© Netcracker 2016 97
at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCreditsat org.hornetq ... ClientProducerImpl.sendRegularMessageat org.hornetq ... ClientProducerImpl.doSendat org.hornetq ... ClientProducerImpl.send at com ... JMSSender.sendMessage
kill -3 профайлер
![Page 98: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/98.jpg)
© Netcracker 2016 98
at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCreditsat org.hornetq ... ClientProducerImpl.sendRegularMessageat org.hornetq ... ClientProducerImpl.doSendat org.hornetq ... ClientProducerImpl.sendat org.hornetq ... HornetQMessageProducer.doSendxat com ... JMSSender.sendMessage
kill -3 профайлер
![Page 99: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/99.jpg)
© Netcracker 2016 99
• 'Producer Window Size’ на connection factory
Backpressure
![Page 100: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/100.jpg)
© Netcracker 2016 100
• 'Producer Window Size’ на connection factory• address-settings -> address-setting -> max-size-bytes
Backpressure
![Page 101: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/101.jpg)
© Netcracker 2016 101
• 'Producer Window Size’ на connection factory• address-settings -> address-setting -> max-size-bytes• Если в JMS очереди накапливается 10МиБ, то отправка
JMS начинает притормаживать
Backpressure
![Page 102: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/102.jpg)
© Netcracker 2016 102
• 'Producer Window Size’ на connection factory• address-settings -> address-setting -> max-size-bytes• Если в JMS очереди накапливается 10МиБ, то отправка
JMS начинает притормаживать
<address-settings> <address-setting match="#"> <max-size-bytes>10 485 760</max-size-bytes> …
Backpressure
![Page 103: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/103.jpg)
© Netcracker 2016 103
• Настраиваем max-size-bytes для каждой очереди
Backpressure: чиним
![Page 104: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/104.jpg)
© Netcracker 2016 104
• Настраиваем max-size-bytes для каждой очереди
• Либо смотрим в сторону RxJava
Backpressure: чиним
![Page 105: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/105.jpg)
© Netcracker 2016 105
• Старт приложения на WF 8.2 занимает 2-5 минут
WildFly: пытаемся взлететь
![Page 106: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/106.jpg)
© Netcracker 2016 106
• Старт приложения на WF 8.2 занимает 2-5 минут
• Concurrent deploy работает плохо
WildFly: пытаемся взлететь
![Page 107: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/107.jpg)
© Netcracker 2016 107
• Старт приложения на WF 8.2 занимает 2-5 минут
• Concurrent deploy работает плохо• Spring xml app config анализирует все jar’ники
WildFly: пытаемся взлететь
![Page 108: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/108.jpg)
© Netcracker 2016 108
• Уменьшать размер jar (исключать лишние)• WildFly копирует jar в /tmp при запуске
WildFly: как чинить
![Page 109: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/109.jpg)
© Netcracker 2016 109
• Уменьшать размер jar (исключать лишние)• WildFly копирует jar в /tmp при запуске
• Делать патчи на WF, чтобы он не складывал строки
• https://github.com/jbossas/jboss-vfs/pull/25• https://github.com/wildfly/wildfly-core/pull/1219
WildFly: как чинить
![Page 110: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/110.jpg)
© Netcracker 2016 110
• Уменьшать размер jar (исключать лишние)• WildFly копирует jar в /tmp при запуске
• Делать патчи на WF, чтобы он не складывал строки
• https://github.com/jbossas/jboss-vfs/pull/25• https://github.com/wildfly/wildfly-core/pull/1219
• Профилировать запуск вашего WF (kill -3 profiler)
WildFly: как чинить
![Page 111: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/111.jpg)
© Netcracker 2016 111
Самое главное в CI – переменные окружения
Jenkins
![Page 112: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/112.jpg)
© Netcracker 2016 112
https://wiki.jenkins-ci.org/display/JENKINS/EnvInject+Plugin
Jenkins: EnvInjectPlugin
![Page 113: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/113.jpg)
© Netcracker 2016 113
Пишем по образу и подобию:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/…PATH=$PATH:$ORACLE/bin:…
Jenkins: EnvInjectPlugin
![Page 114: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/114.jpg)
© Netcracker 2016 114
EnvInjectEnvVars.resolveVars()
Jenkins: EnvInjectPlugin
![Page 115: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/115.jpg)
© Netcracker 2016 115
EnvInjectEnvVars.resolveVars() -> hudson.Util.replaceMacro()
Jenkins: EnvInjectPlugin
![Page 116: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/116.jpg)
© Netcracker 2016 116
EnvInjectEnvVars.resolveVars() -> hudson.Util.replaceMacro() -> OutOfMemoryError.<init>()
Jenkins: EnvInjectPlugin
![Page 117: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/117.jpg)
© Netcracker 2016 117
$LD_LIBRARY_PATH:$ORACLE_HOME/lib :$ORACLE_HOME/lib:$ORACLE_HOME/lib :$ORACLE_HOME/lib:$ORACLE_HOME/lib :$ORACLE_HOME/lib:$ORACLE_HOME/lib :$ORACLE_HOME/lib:$ORACLE_HOME/lib :$ORACLE_HOME/lib:$ORACLE_HOME/lib :$ORACLE_HOME/lib:$ORACLE_HOME/lib :$ORACLE_HOME/lib:...
Jenkins: EnvInjectPlugin
![Page 118: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/118.jpg)
© Netcracker 2016 118
https://issues.jenkins-ci.org/browse/JENKINS-19856^^^ с вами с 2013 года
Jenkins: EnvInjectPlugin
![Page 119: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/119.jpg)
© Netcracker 2016 119
• Общение Jenkins master и slave тщательно логируется
Jenkins: master vs slave
![Page 120: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/120.jpg)
© Netcracker 2016 120
• Общение Jenkins master и slave тщательно логируется
• «Разумеется», в памяти хранятся последние 1000 записей
Jenkins: master vs slave
![Page 121: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/121.jpg)
© Netcracker 2016 121
• Общение Jenkins master и slave тщательно логируется
• «Разумеется», в памяти хранятся последние 1000 записей
• Н а эти логи может уходить 100-200МиБ
Jenkins: master vs slave
![Page 122: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/122.jpg)
© Netcracker 2016 122
• Общение Jenkins master и slave тщательно логируется
• «Разумеется», в памяти хранятся последние 1000 записей
• Н• Да, да. Логи хранятся в памяти и никогда не попадают в файл
Jenkins: master vs slave
![Page 123: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/123.jpg)
© Netcracker 2016 123
• Хорошо, что есть опция• -Dhudson.remoting.ExportTable.unexportLog=0
Jenkins: master vs slave
![Page 124: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/124.jpg)
© Netcracker 2016 124
• Хорошо, что есть опция• -Dhudson.remoting.ExportTable.unexportLog=0
• Разумеется, в Google ровно один результат
Jenkins: master vs slave
![Page 125: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/125.jpg)
© Netcracker 2016 125
• Хорошо, что есть опция• -Dhudson.remoting.ExportTable.unexportLog=0
• Разумеется, в Google ровно один результат• На исходный код, где она определена :)
Jenkins: master vs slave
![Page 126: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/126.jpg)
© Netcracker 2016 126
• Оказалось, что запуск master занимает 50 минут
• 3000 jobs, 10-500 runs per job• 24 CPU, 64 GiB RAM• -Xmx40g
Jenkins: запускаемся
![Page 127: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/127.jpg)
© Netcracker 2016 127
• При старте, Jenkins инициализирует job’ы
Jenkins: файлы разные нужны, файлы разные важны
![Page 128: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/128.jpg)
© Netcracker 2016 128
• При старте, Jenkins инициализирует job’ы• Maven job загружает данные по всем запускам
Jenkins: файлы разные нужны, файлы разные важны
![Page 129: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/129.jpg)
© Netcracker 2016 129
• При старте, Jenkins инициализирует job’ы• Maven job загружает данные по всем запускам
• В каждом запуске есть fingerprint’ы, они тоже грузятся
Jenkins: файлы разные нужны, файлы разные важны
![Page 130: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/130.jpg)
© Netcracker 2016 130
• При старте, Jenkins инициализирует job’ы• Maven job загружает данные по всем запускам
• В• В итоге много-много операций с диском• и тоже грузятся
Jenkins: файлы разные нужны, файлы разные важны
![Page 131: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/131.jpg)
© Netcracker 2016 131
• Решение в лоб: удалить fingerprint’ы перед запуском
Jenkins: чиним
![Page 132: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/132.jpg)
© Netcracker 2016 132
• Решение в лоб: удалить fingerprint’ы перед запуском
• Более сложное: не плодить fingerprint’ы
Jenkins: чиним
![Page 133: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/133.jpg)
© Netcracker 2016 133
• Решение в лоб: удалить fingerprint’ы перед запуском
• Более сложное: не плодить fingerprint’ы• Поможет и сокращение хранимой истории
Jenkins: чиним
![Page 134: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/134.jpg)
© Netcracker 2016 134
• Решение в лоб: удалить fingerprint’ы перед запуском
• Более сложное: не плодить fingerprint’ы• Поможет и сокращение хранимой истории• В идеальном мире нужно разбираться с maven-jenkins-plugin
Jenkins: чиним
![Page 135: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/135.jpg)
© Netcracker 2016 135
Кто виноват и что делать?
![Page 136: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/136.jpg)
© Netcracker 2016 136
• Владимир Ситников• Инженер по производительности в Netcracker• [email protected]• @VladimirSitnikv
С вами был
![Page 137: Производительность open source решений](https://reader035.vdocument.in/reader035/viewer/2022081512/58f257571a28ab7d458b4675/html5/thumbnails/137.jpg)
© Netcracker 2016 137
Вопросы?