лияние измерителя
Любая прикладная программа, пытающаяся измерить длительность выполнения собственных подпрограмм, подвержена ошибке, называемой влиянием измерителя [Malony et al. (1992)]. Эффект влияния измерителя - это разновидность ошибки, возникающей из-за того, что длительность выполнения измеряемой подпрограммы отличается от длительности выполнения той же подпрограммы, когда она не подвергается измерениям. В последние годы у меня не было причин полагать, что эффект влияния измерителя сколько-нибудь заметно сказывался на проанализированных мною измерениях времени отклика Oracle. Однако знание этого эффекта помогло мне оспорить ошибочные аргументы в отношении ненадежности временных характеристик функционирования Oracle.
Наша цель в том, чтобы определить, сколько времени заняло исполнение подпрограммы dosomething. Для этого снабжаем необходимыми инструментами нашу программу U и получаем новую программу I:
Разберемся с эффектом влияния измерителя на примере. Пусть у нас есть такая программа U:
Мы ожидаем, что новая программа I выведет длительность выполнения dosomething. Но выводимое значение лишь приблизительно равно времени выполнения dosomething. Полученное значение e1 - e0, выраженное в секундах, включает в себя не только продолжительность do_something, но и продолжительность одного вызова gettimeofday. На рис. 7.3 наглядно показано, почему так происходит.
Эффект влияния измерителя сказывается на результатах измерений следующим образом:
Время выполнения I превышает время выполнения U на величину длительности двух выполнений gettimeofday.
Измеренная продолжительность dosomething в программе I превышает фактическое время выполнения dosomething на величину длительности одного вызова gettimeofday.
Этот эффект минимален в тех приложениях, где длительность одного вызова gettimeofday мала по отношению к продолжительности любой измеряемой подпрограммы, подобной dosomething. Однако в системах с неэффективно реализованными вызовами gettimeofday (думаю, что так можно охарактеризовать версии HP-UX, предшествующие версии 10), эффект может быть значительным.
Рис. 7.3. Значение e1 -e0 лишь приблизительно равно длительности исполнения do_something; она также включает в себя полную длительность одного вызова gettimeofday (затененная область)
Эффект влияния измерителя относится к систематическим ошибкам. Систематическая ошибка является результатом погрешности эксперимента, которая постоянна от измерения к измерению [Lilja (2000)]. Постоянство влияния измерителя позволяет оценить его воздействие на получаемые данные. Например, для того чтобы измерить эффект влияния измерителя ядра Oracle, вызванный вызовами gettim-eofday, необходимо знать две величины:
Количество вызовов таймера, которые ядро Oracle выполняет для определенной операции.
Ожидаемая продолжительность отдельного вызова таймера.
Зная частоту и среднюю продолжительность вызовов таймера для ядра Oracle, можно количественно оценить их влияние на измеряемую величину. Влияние измерителя - это, вероятно, одна из причин потери времени, с которой мы сталкиваемся при отсчете времени в Oracle9i вглаве 5.
Получить эти две характеристики несложно. Для того чтобы определить, сколько раз ядро Oracle вызывает таймер для заданного набора операций базы данных, можно обратиться к инструменту strace данной платформы. Ожидаемая продолжительность одного вызова таймера вычисляется с помощью программы, аналогичной коду, приведенному в примере 7.4. Этот код измеряет время выполнения нескольких последовательных вызовов gettimeofday, а затем вычисляет их среднюю продолжительность для указанного объема выборки.
В Linux, где я обычно провожу свои исследования (800 МГц Intel Pentium), этот код обычно дает значение задержки gettimeofday приблизительно 2 мкс:
Эффект влияния измерителя во многом зависит от реализации операционной системы. Например, на моем ноутбуке под управлением MS Windows 2000 (тоже 800 МГц Intel Pentium) время выполнения gettim-eofday составляет в среднем почти 6 мкс, т. е. эффект влияния измерителя в 2,5 раза превышает эффект для Linux-сервера:
Экспериментируя подобным образом с системными вызовами, вы начнете понимать, в рамках каких ограничений приходится действовать разработчикам ядра в корпорации Oracle. Именно эффектом влияния измерителя объясняется то, что разработчики стремятся создавать инструменты для измерения времени только для тех событий, длительность которых достаточно велика по сравнению с длительностью измерения. Компромиссное решение заключается в предоставлении полезной информации о времени без ухудшения производительности исследуемого приложения.
вызвана двойным учетом процессорного времени в правой части выражения. В терминологии ядра Oracle величина c содержит все время, проведенное в пользовательском и привилегированном режимах. Каждое значение ela включает в себя общее время, проведенное внутри измеряемой последовательности инструкций ядра Oracle. Когда такая последовательность инструкций, снабженная измерительными средствами, занимает ресурсы процессора, это будет учтено дважды.
Представьте себе, например вызов базы данных Oracle, выполняющий чтение диска (рис. 7.4). На рисунке исполнение вызова базы данных начинается в момент времени e0. В течение периода времени A вызов потребляет процессорное время в пользовательском режиме. В момент времени ela0 процесс ядра Oracle совершает вызов gettimeofday, который предваряет выполнение события ожидания Oracle. В зависимости от операционной системы, выполнение системного вызова gettimeofday может на несколько микросекунд переводить процесс ядра Oracle в привилегированный режим, а затем возвращать его в пользовательский режим.
Некоторые реализации ядра Linux позволяют исполнять весь системный вызов gettimeofday в пользовательском режиме, что приводит к значительному улучшению производительности (один из примеров находится по адресу http://www-124.ibm. com/linux/patches/?patch_id=597).
Процесс в течение периода B расходует процессорное время, находясь в пользовательском режиме, а затем переходит в привилегированный режим до завершения периода C. По завершении периода C процесс ядра переходит в состояние ожидания и ждет результата запроса от диска.
После завершения запроса диск отправляет сигнал прерывания, вызывающий пробуждение процесса ядра Oracle, вследствие чего тот переходит в состояние готовности к выполнению. На рис. 7.4 видно, что в этот момент времени процессор простаивает, а процесс сразу же обрабатывается планировщиком и переводится в привилегированный режим. В этом режиме процесс Oracle обрабатывает результаты вызова дискового ввода/вывода, в частности, копирует данные из канала ввода/вывода в пользовательскую область памяти процесса Oracle, на что уходит время D.
По завершении периода D вызов чтения диска завершается, и процесс Oracle переходит в пользовательский режим на период времени E. Вмомент ela1 процесс Oracle фиксирует время завершения дискового чтения вызовом gettimeofday. Затем процесс Oracle приступает к выполнению оставшихся инструкций (также в пользовательском режиме), чтобы завершить вызов базы данных. Наконец в момент e1 обработка вызова базы заканчивается.
В результате этих действий ядро Oracle сформирует следующую статистику для вызова базы данных:
Чуть позже я подробно поясню, как именно вычисляется с. Значение c будет приблизительно равно сумме длительностей A, B, C, D, E и F. Наверное, вы уже поняли, где возникает двойной учет. Как значение ela, так и с, включают в себя длительности B, C, D и E. Те участки использования процессора, которые оказались в пределах события ожидания, учтены дважды.
Насколько серьезна проблема двойного учета? К счастью, на практике ею обычно можно пренебречь. Наш опыт анализа более чем тысячи файлов трассировки в hotsos.com показывает, что длительности, помеченные как B, C, D и E на рис. 7.4, обычно бывают небольшими. Дело в том, что время отклика (т. е. значение ela) измеряемых событий ожидания в Oracle8i и Oracle9i, как правило, значительно превышает время использования процессора. В некоторых редких случаях (один из них мы вскоре рассмотрим) двойной учет проявляется в небольших фрагментах данных трассировки, но в общей схеме учета времени отклика Oracle эффект двойного учета процессорного времени, как правило, можно не принимать в расчет.
< Предыдущая | Следующая > |
---|