Среднее значение и медиана.

Среднее значение - это достаточно интересная метрика и при правильном использовании она может сказать нам много чего полезного. К сожалению, большинство людей используют её не к месту и хотят странного.

Среднее получить достаточно просто: надо взять все значения за период, сложить и поделить на их количество. Для нормальных данных всё просто и работает достаточно неплохо:

Предположим, нам за секунду падает 20 реквестов, каждый из которых выполняется около 0.3с (голубая линия - среднее значение):

Тогда если каждый реквест начнёт исполнятся за 0.4 секунды, то мы увидим изменение среднего до 0.4. Проблема в том, что мы увидим изменение и в том случае, если к нам придёт пользователь с медленным интернетом. Или два. И не обязательно с медленным интернетом, есть множество разных вещей, которые могут не зависеть от нашего сервера, но зависеть исключительно от пользователя. И это повысит среднее время ответа до, например, 1 секунды, не влияя на реальное положение дел.

Хуже то, что даже если среднее время для нормальных пользователей вырастет, мы всё равно можем не заметить этого, так как разброс будет достаточно большой. Есть такой пример:

Предположим, что в одной комнате оказалось 19 бедняков и один миллиардер. Каждый кладёт на стол деньги — бедняки из кармана, а миллиардер — из чемодана. По $5 кладёт каждый бедняк, а миллиардер — $1 млрд (109). В сумме получается $1 000 000 095. Если мы разделим деньги равными долями на 20 человек, то получим $50 000 004,75. Это будет среднее арифметическое значение суммы наличных, которая была у всех 20 человек в этой комнате.

Для более-менее точного поиска можно обратить внимание на медиану — число, которое определяется тем, что одна половина выборки больше него, а другая половина – меньше. То есть в примере выше медиана будет 5 долларов, а в нашем примере с веб-сервером обратно вернётся к значению около 0.3

Если мы попробуем проанализировать, что такое медиана, то поймём — это максимальное время, за которое может загружаться страница как минимум у половины пользователей. То есть у одной половины страница будет загружаться гарантированно быстрее 0.3, а у другой половины - гарантированно медленнее.

Но половина пользователей – это не совсем то количество, которое мы обычно покрываем SLA. Ну по крайней мере в моей компании. Ведь если ты скажешь бизнесу: “Мы гарантируем, что время загрузки страницы будет меньше 0.3 секунды как минимум у 50% юзеров”, то сразу получишь в лоб вопрос об оставшейся половине.

Соответственно, для получения адекватной метрики стоит узнать, для какого процента пользователей мы хотим гарантировать время загрузки страницы, и потом вычислить это значение.

Например, если нам надо получить время, за которое 99 процентов пользователей гарантировано получат страницу, мы просто должны найти точку, которая больше 99 процентов и меньше 1 процента оставшихся. То есть найти 99-й перцентиль. А медиана, кстати, будет 50-м перцентилем.

Для нахождения перцентилей можно использовать разные средства, но если вы хотите получить метрики в приложения, то отличным выбором будет использовать какой-то . из . вариантов . statsd. В любом случае можно сохранять данные в какую-то БД и считать уже оттуда.

Отбрасывая аномальные метрики, мы можем вычислить как максимальное время, за которое какой-то процент пользователей гарантированно получит ответ, так и среднее значение, за которое этот же процент юзеров получает страницу. Стоит обратить внимание на то, что само по себе среднее значение всегда похоже на среднюю температуру по больнице и пусть и отображает среднее время ответа, но не передаёт представление о динамике. Так средняя температура может быть равна 35.5 градусам, если учитывать морг, и 40.1, если учитывать только реанимацию.

Например, у нас есть два периода времени, 99 процентов реквестов для которых выглядят примерно так:

Соответственно, среднее время загрузки страницы для 99 процентов пользователей в обоих случаях будет 0.3с, в то время как половина пользователей из второго периода будут получать страницу намного дольше. И самое плохое - что мы никак это не увидим, если будем просто смотреть на среднее значение.

Поэтому если вы всё-таки хотите смотреть на среднее значение, то на него стоит смотреть только в паре с среднеквадратичным отклонением, которое более-менее неплохо показывает расброс значений в выборке. Оно интерпретируется достаточно просто - чем выше значение отклонения, тем больше разброс значений. Зная среднеквадратичное отклонение, мы можем предположить, какой процент пользователей попадёт в диапазое среднее значение (на графике 0) ± среднеквадратичное отклонение (на графике σ)

Осторожно с перцентилями

Перцентили - достаточно удобный инструмент, и мы можем много чего сказать, вглядываясь в графики. Но стоит обратить внимание на то, что большинство TSDB постагрегируют данные, а перцентили как-то очень плохо подходят для постагрегации и для точных значений должны быть пересчитаны.

Например, если в один период агрегации к нам пришло 100 запросов, для 99 процентов которых характерно время загрузки 0.3 секунды, и мы высчитали 99 перцентиль равным 0.3 секунды, а в следующий период к нам пришло два запроса, для которых 99-й перцентиль будет равен 10 секунд, то среднее значение после агрегации будет равно 5.1 секунды, в то время как если пересчитать перцентиль сразу для всех значений, то он будет равен 0.3

красным выделено среднее значение, а синим перцентиль для двух периодов

Поэтому перцентили надо хранить как есть без постагрегаций или хранить время запросов и заново считать перцентили на большие диапазоны.

Один из вариантов, как получать более-менeе точные значения и одновременно с этим иметь возможность постагрегации, - сразу писать количество запросов, которые укладываются в определённый интервал.

Например, мы можем разделить все запросы по таким критериям:

  • меньше 0.001 секунды
  • от 0.001 до 0.05
  • от 0.05 до 0.1
  • от 0.1 до 0.15
  • от 0.5 до 1
  • выше 1

И каждый раз, когда время выполнения запроса укладывается в заданный интервал, писать его в метрику с таким же именем. Как можно предположить, такие данные будут неплохо агрегироваться, так как их можно суммировать и в итоге получать правдивые числа. Но однажды заданные интервалы не могут быть изменены без потери истории, и это существенный минус подобного подхода.

Определите кто мухи, а кто - котлеты.

В любом случае для любых расчётов важно знать, как и что у вас может работать. Ни в коем случае не стоит пытаться одной метрикой покрыть весь сайт, так как у вас там наверняка много разного контента, который работает по разным законам. И если, например, у вас на каждой странице отдаётся 100 статических файлов, а один запрос динамический, то вероятнее всего этот динамический запрос будет отфильтровываться в 99-м перцентиле и оказывать мало влияния на восприятие любых других графиков.

Таким образом, желательно каждый важный для бизнеса запрос покрывать своими метриками и смотреть исключительно на эти метрики, потому как именно это время показывает,и сколько пользователь ждёт до итоговой загрузки страницы.