Разберемся с измерением случайных величин (ч. 1/4)

Задача: определить, сколько раз необходимо провести измерения производительности веб-сервиса, чтобы быть уверенным в полученных результатах на 95%.

Эта серия записей не претендует на звание статьи, методического пособия или еще чего-то. Я хочу рассказать об измерениях случайных величин просто, «на пальцах». Так, чтобы даже без знания теории вероятности после прочтения записи было бы всё понятно и можно было бы попробовать свои силы на практике.

Для начала необходимо признать один простой факт – результат любого измерения – это случайная величина. В моём случае результат измерения среднего времени обработки запросов веб-сервисом – случайнее вдвойне!)

Тут в дело не только в погрешности оборудования клиента и сервера, сети, но и во времени суток! В «час пик» среднее время обработки запроса может быть значительно больше. И тут в игру вступают условные вероятности. Впрочем, стоп. Сегодня пройдемся только по простому измерению без всяких условных факторов.

Начнем с вероятности наступления какого-либо события. Для простоты будем рассматривать любой веб-сайт как веб-сервис с одной единственной функцией – возвращением различных страниц. Может быть не совсем очевидно, но время открытия любой страницы в рамках даже одного сайта – это случайная величина. Проверить это просто. Попробуйте эту простую программу на Python:

# coding:utf-8

import httplib
import time

for i in range(10):
    conn = httplib.HTTPConnection("ag.ru")
    conn.request("GET", "/")
    start_time = time.time()
    r1 = conn.getresponse()
    latency = time.time() - start_time
    print("Время обработки запроса: {0}мс".format(round(latency * 1000)))

И получите примерно такой результат:

Время обработки запроса: 14.0мс
Время обработки запроса: 10.0мс
Время обработки запроса: 10.0мс
Время обработки запроса: 10.0мс
Время обработки запроса: 15.0мс
Время обработки запроса: 9.0мс
Время обработки запроса: 14.0мс
Время обработки запроса: 9.0мс
Время обработки запроса: 10.0мс
Время обработки запроса: 11.0мс

Обозначим прописной буквой X возможное время обработки запроса, маленькой же буквой x обозначим конкретные принимаемые значения времени обработки запроса. Для приведенного примера для сайта http://ag.ru X может принимать значения от 9 до 15 мс, для первого измерения x_1=14мс.

Нетрудно заметить, что какие-то времена запросов встречаются чаще, а какие-то –– реже. Давайте сменим сайт на не такой быстрый (чтобы данные были по-богаче), увеличим число запросов до 100 и построим супер полезный график, который позволит нам оценить – как часто время обработки запроса находилось в том или ином интервале. Такой график называется гистограммой.

Для запуска нового кода вам понадобится установленная библиотека matplotlib, которую в простейшем случае можно установить с помощью команды в консоли pip install matplotlib. Я же рекомендую скачать полный набор необходимых библиотек, который содержится в Enthought Python Distribution (тут и numpy, и matplotlib, и еще немало полезных и часто используемых библиотек), дистрибутив которого разработчики подготовили для всех популярных платформы (Windows, MacOS, Linux).

Код обновленной программы будет следующий:

# coding:utf-8

import httplib
import time
import matplotlib.pyplot as plt

latencies = []
for i in range(100):
    conn = httplib.HTTPConnection("habrahabr.ru")
    conn.request("GET", "/")
    start_time = time.time()
    r1 = conn.getresponse()
    latency = round((time.time() - start_time) * 1000)
    latencies.append(latency)
    print("Время обработки запроса: {0}мс".format(latency))

plt.hist(latencies, 50)
plt.title(u"Гистограмма времен обработки запросов")
plt.xlabel(u"Задержка")
plt.ylabel(u"Частота")
plt.show()

И получим следующий график:

Гистограмма времен обработки запросов для сайта habrahabr.ru

Какие же выводы мы можем сделать из этого графика? Получается, чаще всего вы сможете увидеть главную страницу сайта habrahabr.ru где-то спустя 900 мс, вероятность такого события самая высокая, поскольку именно за 900 мс +- несколько десятков миллисекунд согласно нашим измерениям мы 20 раз получали главную страницу! Также есть небольшие вероятности, что страница загрузится или за 100 мс, 200 мс и т.д.

Наша гистограмма весьма похожа на нормальное распределение! Нормальное распределение – это такое распределение случайной величины, где есть единственное наиболее вероятное значение случайного события – среднее значение, или математическое ожидание. Вероятности принятия случайной величиной других значений плавно убывают симметрично относительно среднего значения. Нормальным его называют потому, что именно такое распределение чаще всего встречается в природе. Например, рост человека – это случайная величина с нормальным распределением. Чаще всего вы встретите на улице человека с ростом 170-180 см, но есть же и люди с ростом 155 см и под два метра.

В самом обычном случае нормальное распределение выглядит так (разные формы получаются с помощью вариации двух основных параметров нормального распределения: математического ожидания и дисперсии):

Конечно, разные веб-сервисы будут по разному выглядеть на такой гистограмме, и здесь нам весьма повезло, что получили близкую к канонической форме «купола» нормального распределения.

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

Используемая литература

  1. Кельтон В., Лоу А. Имитационное моделирование. Классика CS. 3-е изд. – СПб.: Питер; Киев: Издательская группа BHV, 2004.-847 c:ил.
  2. Спирин H.A. Методы планирования и обработки результатов инженерного эксперимента : Конспект лекций. / H.A. Спирин, В.В. Лавров. Екатеринбург : ГОУ ВПО УГТУ-УПИ, 2004. — 257 с.

Используемое программное обеспечение (ПО)

  1. Язык программирования Python
  2. Библиотека построения графиков matplotlib в составе дистрибутива The Enthought Python Distribution