Size: a a a

QA — Load & Performance

2021 March 23

AS

Anton Serputko in QA — Load & Performance
Oleh Koren
Привет всем!
Есть вопрос, буду благодарен за помощь.
Я заметил, что в моей панельке в графана неправильно выводятся percentiles и average response time, сравнивал я с агрегейт репортом в jmeter и html репортом.

У меня значения этих метрик отличаются в графана и агрегейт репорте / html репорте, моя query в influx:
SELECT
sum ( "count") as NumberOfSamples,
min (min) as Min,
max (max) as Max,
last (avg) as Average,
last ( "pct90.0") as Percentile90,
last ( "pct95.0") as Percentile95,
last ( "pct99.0") as Percentile99
FROM jmeter
WHERE "statut" = 'ok'
AND $timeFilter
AND transaction! ~ / (Setup) /
AND ( "application" = ~ / ^$application$ /)
GROUP BY "transaction"

Также я еще пробовал писать так:
percentile ( "pct90.0", 90) as "Percentile 90",
percentile ( "pct95.0", 95) as "Percentile 95",
percentile ( "pct99.0", 99) as "Percentile 99"

Значение percentiles конечно меняется, но оно все равно не совпадает с тем, что я вижу в агрегейт репорте, или в html репорте.

Также я пробовал раскомментировать в jmeter.properties такие строки(font-bold), но это не помогло:
# BackendListener - configuration
#---------------------------------------------------------------------------
#
# Backend metrics window mode (fixed=fixed-size window, timed=time boxed)
backend_metrics_window_mode=timed
# Backend metrics sliding window size for Percentiles, Min, Max
backend_metrics_window=50000

# Backend metrics sliding window size for Percentiles, Min, Max
# when backend_metrics_window_mode is timed
# Setting this value too high can lead to OOM
backend_metrics_large_window=50000

Кто нибудь сталкивался с такой проблемой?
154
154
152
152
151
150
150
150
149
147
147

Джиметр агрегейт репорт показывает 90%=147ms,95%=151ms,99%=154ms, что вроде как правильно:
155
154 - 99% 1%, или в нашем случае просто 1 семпл лежит выше в отсортированом списке респонс таймов
154
152
152
151 - 95% 5%, или в нашем случае просто 5 семплов лежат выше в отсортированом списке респонс таймов
150
150
150
149
147 - 90%. 10%, или в нашем случае просто 10 семплов лежат выше в отсортированом списке респонс таймов
147

Но что показывает инфлюкс?
Запрос такой select "pct90.0","pct95.0","pct99.0",transaction,statut from jmeter where application='20' and statut='all' and transaction='jp@gc - Dummy Sampler'
И мы видим что ЗРАДА, последнее значение 90 персентиля 148.8, но никак не 147 как в джиметре, то же самое и для других персентилей.
name: jmeter
time                pct90.0            pct95.0            pct99.0 transaction           statut
----                -------            -------            ------- -----------           ------
1616507446817000000 151.70000000000002 153.9              154     jp@gc - Dummy Sampler all
1616507451817000000 148.7              151.89999999999998 154     jp@gc - Dummy Sampler all
1616507456814000000 145                149.95             154     jp@gc - Dummy Sampler all
1616507461816000000 148.70000000000002 151.95             155     jp@gc - Dummy Sampler all
1616507466817000000 148.8              151.95             154.99  jp@gc - Dummy Sampler all

Что же произошло? Ответ кроется в том как DescriptiveStatistics считает персентили. Они юзают следующий алгоритм
http://www.itl.nist.gov/div898/handbook/prc/section2/prc252.htm

The pth percentile is a value, Y(p), such that at
most (100p)% of the measurements are less than this
value and at most 100(1 - p)% are greater. The 50th
percentile is called the median.

Percentiles split a set of ordered data into
hundredths. For example, 70% of the data should fall
below the 70th percentile.
Note the use of "at most," which is necessary in order to make the definition work. In particular, the lowest and highest values are the 0th and 100th percentiles.

It does NOT say that 100% of the values are LESS than the 100th percentile; the "should" in the last sentence above is a general statement, not the actual definition.

То есть их логика немного отличается от того как считает джиметр. Джиметр берет в качестве персентиля конкретное значение респонс тайма семпла, а DescriptiveStatistics считает свое значение. И, к примеру, значение 90% должно быть такое что остальные 10% респонс таймов должны быть больше, НО само значение персентиля не будет одним из списка.
Теперь давайте проверим:
155
154
154
152
152
151
150
150
150
149
148.8 - 90% influxdb. Действительно, значение немного отличается, но это всеравно правильный и валидный 90 персентиль
147 - 90% jmeter 10%, или в нашем случае просто 10 семплов лежат выше в отсортированом списке респонс таймов
147

Так что подсумируя еще раз:
- в jmeter.properties меняем
backend_metrics_window_mode=timed
backend_metrics_window=50000(или другое большое число, больше чем количество семплов за тест)
backend_metrics_large_window=50000(или другое большое число, больше чем количество семплов за тест)
- в графане в панельках, где вы трекаете тренды юзаете avg, так как оно станет показывать значение за 5 сек
- в графане в таблицах считаете персентили через last("pct90.0"), а среднее через mean("avg")
и будет вам счастье 🙂
источник

OK

Oleh Koren in QA — Load & Performance
@serputko спасибо за ответ!
источник

VG

Viktor Ganeles in QA — Load & Performance
Anton Serputko
Уже общались по этому поводу в другом чате, но решил еще тут пошарить информацию, так как складывается ощущение что много кто не понимает как работает агрегация в стандартном influxdb backend listener.

На деле стандартный бекенд лисенер по дефолту агрегирует данные не за 5 секунд, как может показаться на первый взгляд, а немного по другому. Лисенер под капотом использует либу DescriptiveStatistics, которая позволяет получать в рантайме разного вида агрегации. Джиметр создает себе несколько датасетов:
- okResponsesStats
- koResponsesStats
- allResponsesStats
- pctResponseStats
По сути датасет это такой себе бакет, куда джиметр будет добавлять респонс таймы, а DescriptiveStatistics будет считать разные агрегации по требованию джиметра, например "koResponsesStats.getPercentile(percentile);"
У каждого датасета есть свой максимальный размер, который можно передать в jmeter.properties файле.

В jmeter.properties есть вот такие параметры:
# Backend metrics window mode (fixed=fixed-size window, timed=time boxed)
#backend_metrics_window_mode=fixed
# Backend metrics sliding window size for Percentiles, Min, Max
#backend_metrics_window=100
# Backend metrics sliding window size for Percentiles, Min, Max
# when backend_metrics_window_mode is timed
# Setting this value too high can lead to OOM
#backend_metrics_large_window=5000

Так вот, если максимальный размер датасета к примеру 100 и в него уже добавлено 100 значений, новое значение пойдет перетирать первое в нем и так далее.
А теперь разберем пример:
За первые 5 сек теста джиметр выполнил 2 запроса Login с респонс таймами 100 и 200мс
- okResponsesStats(100,200)
- koResponsesStats()
- allResponsesStats(100,200)
- pctResponseStats(100,200)
при отправке данных джиметр попросит DescriptiveStatistics посчитать avg, pct(90,95,99), min, max. Avg например получится 150мс, что и отправится в инфлюкс

Дальше за вторые 5 сек отправилось еще 3 запроса, один из них свалился, в итоге датасеты выглядят вот так:
- okResponsesStats(100,200,120,160)
- koResponsesStats(190)
- allResponsesStats(100,200,120,160,190)
- pctResponseStats(100,200,120,160,190)
при отправке данных джиметр попросит DescriptiveStatistics посчитать агрегации и либа опять посчитает их на основании всех данных что есть в бакете, то есть avg будет не по (120,160,190) а по всем (100,200,120,160), что тупо с точки зрения мониторинга, так как на графиках в графане я хочу видеть значения среднего как раз за промежутки в 5 сек, а не пересчитывание данных с начала теста.

Для того что б исправить это, нужно изменить значение проперти backend_metrics_window_mode с fixed на timed.
После этого джиметр начнет очищать датасеты okResponsesStats, koResponsesStats, allResponsesStats после каждой отправки данных в инфлюкс, что нам и нужно.

Теперь по поводу персентилей, датасет pctResponseStats не очищается при любых значениях backend_metrics_window_mode, так как персентили нас интересуют не за 5 сек, а за весь тест. Нас интересует последнее значение персентиля для транзакции, которое бекенд лисенер отправляет в инфлюкс. Основная проблема в том что значения не совпадают с тем что показывает джиметр это то что дефолтное значение backend_metrics_window=100, а это значит что 101 и все остальные семплы будут просто начинать перетирать 1,2... значения в pctResponseStats датасете, и в результате в конце теста лисенер посчитает персентиль только за последние 100 семплов. Для того что б значение персентиля было максимально правдивым, нужно поставить в backend_metrics_window большое значение, в идеале больше чем количество семплов что выполняются за тест. При таком раскладе до конца теста pctResponseStats будет в себе хранить все респонс таймы и сможет спокойно посчитать правильный персентиль.
Так что мой совет ставить timed и большие значения в оба backend_metrics_window и backend_metrics_large_window

Ура, но если проверите, то скажете что всеравно не работает, цифры отличаются от того что дает джиметр.
Что я только что протестил для демо: запустил тест на 100 семплов, отсортировал по убыванию респонс таймы и вот мои топ 12 запросов в мс:
155
@instaHipsta Стёпа, видел?
инфа огонь
источник

СФ

Степа Фомичев... in QA — Load & Performance
Viktor Ganeles
@instaHipsta Стёпа, видел?
инфа огонь
Да)) я пока не стал комментировать, так как нужно переварить, слишком глубоко
источник

СФ

Степа Фомичев... in QA — Load & Performance
Выглядит очень многообещающе. У меня сейчас точность метрик скачет от -5 до +5% от значений в джиметре (в среднем). Если получится ещё больше сократить, в то же время не умножая данные, будет очень круто
источник

VG

Viktor Ganeles in QA — Load & Performance
Я вот только не понял про перцентили.

в LR понятия "график времени отклика по какому-то перцентилю" не существовало - так как это всегда была одна цифра (время отклика по 90му перцентилю за выбранный вами отрезок)

увидев в Jmeter график перцентилей я предполагал, что тут, как с графиков "среднее время отклика" - просто все времена группируются по 5 сек и берётся 90й перцентиль за 5 сек. Что, в общем-то, фигня при интенсивностях менее 10 операций за эти 5 секунд.
А для 99 перцентиля фигня, если операций меньше 100 за 5 секунд.
источник

VG

Viktor Ganeles in QA — Load & Performance
Теперь же картина меняется:
если сейчас размер окна 100 времён отклика - то график перцентилей это скользящее окно "90й перцентиль за последние 100 событий".
Не очень круто, но в общем сойдёт.
Если же делать как советует Антон - график перцентилей превращается в ХЗ что.
То есть на любой момент теста мы в финальной точке будем получать "время отклика по 90му перцентилю за отрезок с начала теста до сего момента"

Мне такое нужно примерно никогда.
источник

VG

Viktor Ganeles in QA — Load & Performance
Потому что времена отклика за время разгона нужны только при стресс-тестах.
А времена отклика за время выхода на очередную ступень теста не нужны вообще никогда.
источник

VG

Viktor Ganeles in QA — Load & Performance
В общем, может и правда стоит перейти на вариант Славы - забить на перцентили и смотреть график "среднее время отклика дополненный квадратичными отклонениями"

но у них свой минус: такой график удобно смотреть по одной операции.

У меня в тестах одновременно операций штук.. много.
выводить по каждой график не в кайф.
источник

СФ

Степа Фомичев... in QA — Load & Performance
Надо кликхаус брать, писать вообще без агрегации данные и потом агрегировало самому))
источник

СФ

Степа Фомичев... in QA — Load & Performance
Идеальный мир
источник

VG

Viktor Ganeles in QA — Load & Performance
@serputko
Антон, спасибо за инфо!

Главный вопрос по итогам этого всего:
метрика "Count" выдаётся тоже как-то неожиданно?
или там всё норм :)
источник

VG

Viktor Ganeles in QA — Load & Performance
Степа Фомичев
Надо кликхаус брать, писать вообще без агрегации данные и потом агрегировало самому))
ну, вообще тоже интересно.
Писать без агрегации, но батчами.
Не знаешь, в кликхаус пишется батчами или каждое событие отдельно?

А то мы тут  порой тестируем не системы а технологии - kafka / consul / ignite / elastic
там десятки тысяч RPS
и лишние 10ms  времязатрат на отправку данных по сети уже становятся критичными.
источник

СФ

Степа Фомичев... in QA — Load & Performance
Не знаю чисто про кликхаус, но вообще 100% бд с которыми я сталкивался умеют записывать батчами данные
источник

СФ

Степа Фомичев... in QA — Load & Performance
Viktor Ganeles
ну, вообще тоже интересно.
Писать без агрегации, но батчами.
Не знаешь, в кликхаус пишется батчами или каждое событие отдельно?

А то мы тут  порой тестируем не системы а технологии - kafka / consul / ignite / elastic
там десятки тысяч RPS
и лишние 10ms  времязатрат на отправку данных по сети уже становятся критичными.
Да, есть
источник

СФ

Степа Фомичев... in QA — Load & Performance
источник

СФ

Степа Фомичев... in QA — Load & Performance
Кстати, у них даже рекомендации по перформансу прямо а доке есть, очень достойно:
Снижения производительности не будет, если:
• Данные поступают в режиме реального времени.
• Вы загружаете данные, которые как правило отсортированы по времени
источник

VG

Viktor Ganeles in QA — Load & Performance
нене, это способности кликхауса

а я про способности
я именно про бэкенд листнер жметра. Нужно, что бы он сперва набирал пачку данных а потом уже их массово отправлял.
Не хочу, чтобы в тесте Ignite он вместо того, чтобы 35 000 раз в секунду стучался в целевую систему, стучался 70 000 раз в секунду, и половину из них - в кликхаус :)
источник

СФ

Степа Фомичев... in QA — Load & Performance
Viktor Ganeles
нене, это способности кликхауса

а я про способности
я именно про бэкенд листнер жметра. Нужно, что бы он сперва набирал пачку данных а потом уже их массово отправлял.
Не хочу, чтобы в тесте Ignite он вместо того, чтобы 35 000 раз в секунду стучался в целевую систему, стучался 70 000 раз в секунду, и половину из них - в кликхаус :)
Если пинганещь на следующий неделе, я посмотрю реализацию бэкенд лисёнка для кликхауса и скажу уже точно
источник

VG

Viktor Ganeles in QA — Load & Performance
попробую, спасибо
источник