Проблемы производительности open source библиотек

137
© Netcracker 2016 1 Производительность open source решений Владимир Ситников JPoint 2016

Transcript of Проблемы производительности open source библиотек

© Netcracker 2016 1

Производительность open source решений

Владимир СитниковJPoint 2016

© Netcracker 2016 2

• Владимир Ситников• Инженер по производительности в Netcracker, 10 лет

[email protected]• @VladimirSitnikv

Кто я

© Netcracker 2016 3

• Spring• Cglib• Pgjdbc• HornetQ• Wildfly• Jenkins

План

© Netcracker 2016 4

План

Наш любимый enterprise продукт

© Netcracker 2016 5

Внедряем Spring в сжатые сроки

Монолитspring

© Netcracker 2016 6

Внедряем Spring в сжатые сроки

Монолитspring

© Netcracker 2016 7

Внедряем Spring в сжатые сроки

CoreSecurity

UI

© Netcracker 2016 8

Внедряем Spring в сжатые сроки

CoreSecurity

UI

© Netcracker 2016 9

Внедряем Spring в сжатые сроки

CoreSecurity

UI

© Netcracker 2016 10

• Когда нужен бин, то выполняем

beanFactory.getBean(Security.class)

В UI spring пока не наступил

© Netcracker 2016 11

• Когда нужен бин, то выполняем

beanFactory.getBean(Security.class)

• Но где взять beanFactory?

В UI spring пока не наступил

© Netcracker 2016 12

• Когда нужен бин, то выполняем

beanFactory.getBean(Security.class)

• Но где взять beanFactory?

• Правильно, Паблик Морозов поможет нам

В UI spring пока не наступил

© Netcracker 2016 13

public class AppContext implements BeanFactoryAware { static public BeanFactory beanFactory; ...

Получаем бин

© Netcracker 2016 14

public class AppContext implements BeanFactoryAware { static public BeanFactory beanFactory; ...

AppContext.beanFactory.getBean(Security.class)

Получаем бин

© Netcracker 2016 15

• Работает

Spring.getBean

© Netcracker 2016 16

• Работает• Но медленно-медленно

Spring.getBean

© Netcracker 2016 17

• Работает• Но медленно-медленно• На getBean и 50% времени может уходить

Spring.getBean

© Netcracker 2016 18

• Java Flight Recorder

Подходящие для анализа инструменты

© Netcracker 2016 19

• Java Flight Recorder• kill -3 profiler (poormansprofiler.org)

Подходящие для анализа инструменты

© Netcracker 2016 20

• Java Flight Recorder• kill -3 profiler (poormansprofiler.org)• Инструментирующий профилировщик. Например самописный, настроенный на getBean

Подходящие для анализа инструменты

© Netcracker 2016 21

160 секунд на getBean. Здорово?

© Netcracker 2016 22

160 секунд на getBean. Здорово?

• Java 8 / Spring 4.1.7

© Netcracker 2016 23

• SPR-6870 Cache by-type lookups in DefaultListableBeanFactory

Проверяем известные проблемы

© Netcracker 2016 24

• SPR-6870 Cache by-type lookups in DefaultListableBeanFactory

Проверяем известные проблемы

ЯЗЬ!!!

© Netcracker 2016 25

• SPR-6870 Cache by-type lookups in DefaultListableBeanFactory

• Fix version: 3.2 M1, а у нас 4.1+

Проверяем известные проблемы

© Netcracker 2016 26

Flight Recorder, allocations in new TLAB

© Netcracker 2016 27

protected Object getCacheKey( Class<?> beanClass, String beanName) { return beanClass.getName() + "_" + beanName;}

AbstractAutoProxyCreator

© Netcracker 2016 28

protected Object getCacheKey( Class<?> beanClass, String beanName) { return beanClass.getName() + "_" + beanName;}

AbstractAutoProxyCreator

© Netcracker 2016 29

protected Object getCacheKey( Class<?> beanClass, String beanName) { return beanName == null ? beanClass : ...;}

github.com/spring-projects/spring-framework/pull/913

AbstractAutoProxyCreator

© Netcracker 2016 30

public class SharedSecrets { @Inject public Security security; @PostConstruct public void init() { INSTANCE = this; }

public static volatile SharedSecrets INSTANCE;

Как выжить без обновления Spring?

© Netcracker 2016 31

• Не стоит злоупотреблять prototype bean’ами. Если singleton, то singleton

Prototype vs singleton

© Netcracker 2016 32

• Не стоит злоупотреблять prototype bean’ами. Если singleton, то singleton

• Замена getBean на javax.inject.Provider<...> лишь ухудшает время работы

Prototype vs singleton

© Netcracker 2016 33

@Pointcut( "execution( public* my.service.*ServiceImpl.*(..))”)

Spring AOP

© Netcracker 2016 35

• OutOfMemory: perm gen• В хипдампе куча java.lang.reflect.Method

Spring AOP

© Netcracker 2016 36

• OutOfMemory: perm gen• В хипдампе куча java.lang.reflect.Method• Method’ы занимают 100-500MiB

Spring AOP

© Netcracker 2016 37

• OutOfMemory: perm gen• В хипдампе куча java.lang.reflect.Method• Method’ы занимают 100-500MiB• Все они лежат в AspectJExpressionPointcut

Spring AOP

© Netcracker 2016 38

@Pointcut( "execution( public* my.service.*ServiceImpl.*(..))”)

Spring AOP

© Netcracker 2016 39

• Решение: добавлять within(my.package.service.business..*)

Spring AOP vs AspectJ

© Netcracker 2016 40

• Решение: добавлять within(my.package.service.business..*)

• Разумеется, AspectJ рекомендуют использовать within всегда: http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg10969.html

Spring AOP vs AspectJ

© Netcracker 2016 41

• Cglib используется много где: рукотворный код, тот же Spring

Cglib

© Netcracker 2016 42

• Cglib используется много где: рукотворный код, тот же Spring

• Наверняка уже всё исправлено давным-давно

Cglib

© Netcracker 2016 43

• Cglib используется много где: рукотворный код, тот же Spring

• Наверняка уже всё исправлено давным-давно

• Наверняка туда давно никто не заглядывал

Cglib

© Netcracker 2016 44

@Benchmarkpublic Object newProxy() { return Beans.newProxy(Beans.class);}

Cglib: замеряем

© Netcracker 2016 45

Cglib 3.10

2000400060008000

1000012000140001600018000

1 поток 2 потока 4 потока 8 потоков

Замеры Cglib, μs/op

Бы

стре

е

© Netcracker 2016 46

Cglib 3.1 Cglib 3.2.20

2000400060008000

1000012000140001600018000

1 поток 2 потока 4 потока 8 потоков

Замеры Cglib, μs/op

Бы

стре

е

© 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

© 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

© Netcracker 2016 49

• А, может, ну его этот cglib, есть же быстрый ByteBuddy?

Но есть же ByteBuddy

© Netcracker 2016 50

• А, может, ну его этот cglib, есть же быстрый ByteBuddy?

@Benchmarkpublic ExampleClass benchmarkCglib() { Enhancer enhancer = new Enhancer(); enhancer.setUseCache(false);

ByteBuddy, jmh тест

© Netcracker 2016 51

• А, может, ну его этот cglib, есть же быстрый ByteBuddy?

@Benchmarkpublic ExampleClass benchmarkCglib() { Enhancer enhancer = new Enhancer(); enhancer.setUseCache(false);

ByteBuddy, jmh тест

© Netcracker 2016 52

• JMH тесты в ByteBuddy показывают скорость создания классов

• Постоянно создавать классы нехорошо• Значит, нужно измерять скорость кэшированного обращения

ByteBuddy, jmh тест

© Netcracker 2016 53

• КО: «Бери pgjdbc»

Подключаемся к PostgreSQL

© Netcracker 2016 54

• КО: «Бери pgjdbc»• КО: «Используй batch statements»

Подключаемся к PostgreSQL

© Netcracker 2016 55

• КО: «Бери pgjdbc»• КО: «Используй batch statements»• Что может пойти не так?

Подключаемся к PostgreSQL

© Netcracker 2016 56

Connection con = ...;PreparedStatement ps = con.prepareStatement("SELECT..."); ...ps.close();

PreparedStatement

© Netcracker 2016 57

Connection con = ...;PreparedStatement ps = con.prepareStatement("SELECT..."); ...ps.close();

PreparedStatement

© Netcracker 2016 58

PARSE S_1 as ...; // con.prepareStmt BIND/EXECDEALLOCATE // ps.close()PARSE S_2 as ...; BIND/EXECDEALLOCATE // ps.close()

Работа с PostgreSQL курильщика

© Netcracker 2016 59

PARSE S_1 as ...; BIND/EXEC BIND/EXEC BIND/EXEC BIND/EXEC BIND/EXEC ...DEALLOCATE

Работа с PostgreSQL здорового человека

© Netcracker 2016 60

PARSE S_1 as ...; 1 раз в жизни BIND/EXEC обработка REST BIND/EXEC BIND/EXEC ещё REST BIND/EXEC BIND/EXEC ...DEALLOCATE желательно «никогда»DEALLOCATE

Работа с PostgreSQL здорового человека

© Netcracker 2016 61

Вывод: чтобы работало быстрее, закрывать statement’ы не нужноps = con.prepareStatement(...)ps.execueQuery();ps = con.prepareStatement(...)ps.execueQuery();...

Счастливые statement’ов не закрывают

© Netcracker 2016 62

Вывод: чтобы работало быстрее, закрывать statement’ы не нужноps = con.prepare...ps.execueQuery();ps = con.prepare...ps.execueQuery();...

Счастливые statement’ов не закрывают

© 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 одинаково полезны

© 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

© Netcracker 2016 65

Вывод: чтобы работало быстро, нужно как-то кэшировать statement’ыps = con.prepareStatement("select id, name ...");ps.execueQuery();ps.close();ps2 = con.prepareStatement("select id, name ...");

Счастливые statement’ов не закрывают

© Netcracker 2016 66

• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319

Кэш запросов в PgJDBC

© Netcracker 2016 67

• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319

• Работает прозрачно для приложения

Кэш запросов в PgJDBC

© Netcracker 2016 68

• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319

• Работает прозрачно для приложения• Скорость такая, что PL/PgSQL не нужен

Кэш запросов в PgJDBC

© Netcracker 2016 69

• Кэш запросов появился в версии 9.4.1202 (2015-08-27)см. https://github.com/pgjdbc/pgjdbc/pull/319

• Работает прозрачно для приложения• Скорость такая, что PL/PgSQL не нужен• Server-prepare активируется после 5-го выполнения (prepareThreshold)

Кэш запросов в PgJDBC

© Netcracker 2016 70

• Конечно, затраты planning time напрямую зависят от сложности запросов

Цифры где?

© Netcracker 2016 71

• Конечно, затраты planning time напрямую зависят от сложности запросов

• У нас доходило до 20мс+ planning time на OLTP запросах: 10КиБ запрос, 170 строк explain

Цифры где?

© Netcracker 2016 72

• Конечно, затраты planning time напрямую зависят от сложности запросов

• У нас доходило до 20мс+ planning time на OLTP запросах: 10КиБ запрос, 170 строк explain

• Стало ~0мс

Цифры где?

© Netcracker 2016 73

Если типы параметров меняются, то server-prepared statement приходится менятьps.setInt(1, 42);...ps.setNull(1, Types.VARCHAR);

JDBC: Типы параметров

© Netcracker 2016 74

Если типы параметров меняются, то server-prepared statement приходится менятьps.setInt(1, 42);...ps.setNull(1, Types.VARCHAR);

JDBC: Типы параметров

© Netcracker 2016 75

• Вывод: даже у NULL’ов должен быть верный тип

JDBC: Тип параметров изменять нельзя

© Netcracker 2016 76

• Вывод: даже у NULL’ов должен быть верный тип

• Ещё раз: setObject(1, null) использовать нельзя

JDBC: Тип параметров изменять нельзя

© Netcracker 2016 77

• Перешли на prepared, и запрос замедлился в 5'000 раз. Как так?

Нежданчик

© Netcracker 2016 78

• Перешли на prepared, и запрос замедлился в 5'000 раз. Как так?

Нежданчик

A. Бага C. ФичаB. Фича D. Бага

© 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 строк

Нежданчик

© 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-е выполнение

Нежданчик

© 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-е выполнение

Нежданчик

© Netcracker 2016 82

Запрещаем использование индекса через +0:select * from plan_flipper where skewed+0 = 0 ~ /*+no_index*/ and non_skewed = 42

Чиним

© Netcracker 2016 83

Как сделать опциональные фичи?• NO_RESULTS• BOTH_ROWS_AND_STATUS• DESCRIBE_ONLY

Фичи

© Netcracker 2016 84

Конечно, enum!enum ... {

NO_RESULTS,BOTH_ROWS_AND_STATUS,DESCRIBE_ONLY;

}

Фичи

© Netcracker 2016 85

Конечно, enum!enum ... {

NO_RESULTS,BOTH_ROWS_AND_STATUS,DESCRIBE_ONLY;

}А на java 1.4?

Фичи

© 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 наносит ответный удар

© 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;

Ужасы нашего городка

© 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;

Ужасы нашего городка

© Netcracker 2016 89

• WildFly 8.2, JMS

HornetQ

© Netcracker 2016 90

• WildFly 8.2, JMS• Всего ~100 JMS/сек

HornetQ

© Netcracker 2016 91

• WildFly 8.2, JMS• Всего ~100 JMS/сек• 1 вызов sendMessage – 5-30 секунд

HornetQ

© Netcracker 2016 92

at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCredits at com ... JMSSender.sendMessage

kill -3 профайлер

© Netcracker 2016 93

at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCredits at com ... JMSSender.sendMessage

kill -3 профайлер

© Netcracker 2016 94

at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCredits at com ... JMSSender.sendMessage

kill -3 профайлер

© Netcracker 2016 95

at java.util.concurrent.Semaphore.tryAcquireat org.hornetq ... ClientProducerCreditsImpl.acquireCreditsat org.hornetq ... ClientProducerImpl.sendRegularMessage at com ... JMSSender.sendMessage

kill -3 профайлер

© 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 профайлер

© 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 профайлер

© 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 профайлер

© Netcracker 2016 99

• 'Producer Window Size’ на connection factory

Backpressure

© Netcracker 2016 100

• 'Producer Window Size’ на connection factory• address-settings -> address-setting -> max-size-bytes

Backpressure

© Netcracker 2016 101

• 'Producer Window Size’ на connection factory• address-settings -> address-setting -> max-size-bytes• Если в JMS очереди накапливается 10МиБ, то отправка

JMS начинает притормаживать

Backpressure

© 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

© Netcracker 2016 103

• Настраиваем max-size-bytes для каждой очереди

Backpressure: чиним

© Netcracker 2016 104

• Настраиваем max-size-bytes для каждой очереди

• Либо смотрим в сторону RxJava

Backpressure: чиним

© Netcracker 2016 105

• Старт приложения на WF 8.2 занимает 2-5 минут

WildFly: пытаемся взлететь

© Netcracker 2016 106

• Старт приложения на WF 8.2 занимает 2-5 минут

• Concurrent deploy работает плохо

WildFly: пытаемся взлететь

© Netcracker 2016 107

• Старт приложения на WF 8.2 занимает 2-5 минут

• Concurrent deploy работает плохо• Spring xml app config анализирует все jar’ники

WildFly: пытаемся взлететь

© Netcracker 2016 108

• Уменьшать размер jar (исключать лишние)• WildFly копирует jar в /tmp при запуске

WildFly: как чинить

© 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: как чинить

© 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: как чинить

© Netcracker 2016 111

Самое главное в CI – переменные окружения

Jenkins

© Netcracker 2016 113

Пишем по образу и подобию:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/…PATH=$PATH:$ORACLE/bin:…

Jenkins: EnvInjectPlugin

© Netcracker 2016 114

EnvInjectEnvVars.resolveVars()

Jenkins: EnvInjectPlugin

© Netcracker 2016 115

EnvInjectEnvVars.resolveVars() -> hudson.Util.replaceMacro()

Jenkins: EnvInjectPlugin

© Netcracker 2016 116

EnvInjectEnvVars.resolveVars() -> hudson.Util.replaceMacro() -> OutOfMemoryError.<init>()

Jenkins: EnvInjectPlugin

© 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

© Netcracker 2016 118

https://issues.jenkins-ci.org/browse/JENKINS-19856^^^ с вами с 2013 года

Jenkins: EnvInjectPlugin

© Netcracker 2016 119

• Общение Jenkins master и slave тщательно логируется

Jenkins: master vs slave

© Netcracker 2016 120

• Общение Jenkins master и slave тщательно логируется

• «Разумеется», в памяти хранятся последние 1000 записей

Jenkins: master vs slave

© Netcracker 2016 121

• Общение Jenkins master и slave тщательно логируется

• «Разумеется», в памяти хранятся последние 1000 записей

• Н а эти логи может уходить 100-200МиБ

Jenkins: master vs slave

© Netcracker 2016 122

• Общение Jenkins master и slave тщательно логируется

• «Разумеется», в памяти хранятся последние 1000 записей

• Н• Да, да. Логи хранятся в памяти и никогда не попадают в файл

Jenkins: master vs slave

© Netcracker 2016 123

• Хорошо, что есть опция• -Dhudson.remoting.ExportTable.unexportLog=0

Jenkins: master vs slave

© Netcracker 2016 124

• Хорошо, что есть опция• -Dhudson.remoting.ExportTable.unexportLog=0

• Разумеется, в Google ровно один результат

Jenkins: master vs slave

© Netcracker 2016 125

• Хорошо, что есть опция• -Dhudson.remoting.ExportTable.unexportLog=0

• Разумеется, в Google ровно один результат• На исходный код, где она определена :)

Jenkins: master vs slave

© Netcracker 2016 126

• Оказалось, что запуск master занимает 50 минут

• 3000 jobs, 10-500 runs per job• 24 CPU, 64 GiB RAM• -Xmx40g

Jenkins: запускаемся

© Netcracker 2016 127

• При старте, Jenkins инициализирует job’ы

Jenkins: файлы разные нужны, файлы разные важны

© Netcracker 2016 128

• При старте, Jenkins инициализирует job’ы• Maven job загружает данные по всем запускам

Jenkins: файлы разные нужны, файлы разные важны

© Netcracker 2016 129

• При старте, Jenkins инициализирует job’ы• Maven job загружает данные по всем запускам

• В каждом запуске есть fingerprint’ы, они тоже грузятся

Jenkins: файлы разные нужны, файлы разные важны

© Netcracker 2016 130

• При старте, Jenkins инициализирует job’ы• Maven job загружает данные по всем запускам

• В• В итоге много-много операций с диском• и тоже грузятся

Jenkins: файлы разные нужны, файлы разные важны

© Netcracker 2016 131

• Решение в лоб: удалить fingerprint’ы перед запуском

Jenkins: чиним

© Netcracker 2016 132

• Решение в лоб: удалить fingerprint’ы перед запуском

• Более сложное: не плодить fingerprint’ы

Jenkins: чиним

© Netcracker 2016 133

• Решение в лоб: удалить fingerprint’ы перед запуском

• Более сложное: не плодить fingerprint’ы• Поможет и сокращение хранимой истории

Jenkins: чиним

© Netcracker 2016 134

• Решение в лоб: удалить fingerprint’ы перед запуском

• Более сложное: не плодить fingerprint’ы• Поможет и сокращение хранимой истории• В идеальном мире нужно разбираться с maven-jenkins-plugin

Jenkins: чиним

© Netcracker 2016 135

Кто виноват и что делать?

© Netcracker 2016 136

• Владимир Ситников• Инженер по производительности в Netcracker• [email protected]• @VladimirSitnikv

С вами был

© Netcracker 2016 137

Вопросы?