ремя «невыполнения»
Давайте проделаем небольшой мысленный эксперимент для того, чтобы познакомиться с четвертой причиной наличия неучтенного времени в корректно собранных данных трассировки Oracle. Представьте себе программу P, которая ровно десять секунд занимает процессор в пользовательском режиме и формирует вывод на терминал. Пусть такая программа циклически запускается на компьютере с одним процессором. Если тот, кто запускает ее, является единственным пользователем данной системы, то он должен ожидать, что время отклика для каждого выполнения P составит 10 секунд.
Наблюдая за использованием процессора на данной однопроцессорной машине в ходе многократного выполнения P одним пользователем, можно заметить, что процессор все это время будет работать со 100% загрузкой. Но что будет, если добавить второй экземпляр циклично выполняющейся программы P в однопроцессорную систему? В рамках любого одного десятисекундного интервала времени однопроцессорный компьютер может предоставить только десять секунд процессорного времени. То есть невозможно ожидать полного выполнения двух экземпляров программы, требующих по десять секунд процессорного времени, в течение одного десятисекундного промежутка времени. Можно предположить, что время отклика для каждого из экземпляров P возрастет приблизительно до 20 секунд. Столько времени потребуется одному процессору для того, чтобы предоставить по десять секунд своего времени каждому из конкурирующих процессов, если он будет распределять его равномерно и небольшими порциями двум параллельным процессам.
Измерения в эксперименте
Предположим, что мы добавили в наш код измерительные средства, подобные применяемым в ядре Oracle, как это показано в примере 7.6.
Пример 7.6 Программа P оснащена средствами для вывода собственного времени отклика и использованного процессорного времени
Теперь попробуем предсказать значения выводимых временных статистик для каждого указанного уровня параллелизма в однопроцессорной системе (табл. 7.2). Ожидаем, что программа P будет потреблять одинаковый общий объем процессорного времени независимо от занятости системы. Но, конечно же, учитывая, что ресурсы процессора по мере увеличения уровня параллелизма разделяется между возрастающим количеством пользователей, можно ожидать замедления выполнения программы и увеличения периодов времени, прошедших прежде, чем программе удастся получить необходимые ей десять секунд времени процессора.
Таблица 7.2. Ожидаемый результат выполнения программы P, потребляющей десять секунд процессорного времени в пользовательском режиме и измеряющей время выполнения для различных уровней параллелизма
Количество пользователей, параллельно запускающих P
|
Выводимые временные статистики
|
1
|
e=10s,c=10s
|
2
|
e=20s,c=10s
|
3
|
e=30s, c=10s
|
4
|
e=40s, c=10s
|
Мы видим то, что и ожидали, но при этом в некоторых строках таблицы возникает проблема «недостающего времени». Помните, какой была наша модель производительности системы? Длительность выполне-
Однако уже для двух пользователей мы имеем несоответствие:
20 и 10 + 0
Мы имеем право подставить ноль вместо значения ela, т. к. знаем, что наша программа не исполняет «событий ожидания», длительность которых могла бы быть измерена. Единственное, что делает наша программа, - это расходует некоторое количество процессорного времени и выводит результат (и даже функция printf должна быть исключена из круга подозреваемых, т. к. она вызывается вне области действия таймеров). Очевидно, что соотношение c + Eela = 10 является очень плохим приближением для e = 20. На что ушло «потерянное время»? Из табл. 7.2 видно, что ситуация ухудшается с увеличением количества пользователей. Что же мы сделали не так, добавив в P измерительные средства?
Еще раз о состояниях процессов и переходах
Для того чтобы упросить ответ на вопрос, обратимся к рис. 7.1. Вспомним о том, что даже когда процесс спокойно выполняется в пользовательском режиме, в большинстве систем каждую сотую долю секунды происходит прерывание по системному таймеру. Такое регулярно повторяющееся прерывание переводит каждый работающий процесс в привилегированный режим. Перейдя в привилегированный режим, процесс сохраняет текущий контекст, а затем выполняет подпрограмму планировщика (см. раздел «Переход по прерыванию» выше в этой главе). Если присутствует процесс в состоянии готовности к исполнению, то политика планирования системы может потребовать приостановки обслуживания (вытеснения) исполняемого процесса и предоставления готовому к исполнению процессу возможности использовать процессор.
Обратите внимание на то, что при этом происходит с процессом, который выполнялся изначально. Когда он прерывается, то сразу же переходит в привилегированный режим. Заметьте, что у процесса нет никакой возможности выполнить какой-либо код, с тем чтобы узнать, в какое время произошел такой переход. Когда обслуживание процесса приостанавливается, он переходит в состояние готовности к выполнению, ожидая, когда планировщик продолжит его выполнение. Когда наконец наступает его время (возможно, это будет уже через каких-то 10 миллисекунд), процесс проводит в привилегированном режиме столько времени, сколько необходимо для восстановления его контекста, а затем возвращается в пользовательский режим, ровно в то место, на котором остановился.
Как вытеснение процесса влияет на получаемые хронометрические данные? Время, которое процессор проводит в привилегированном режиме, пока планировщик готовится к вытеснению процесса, учитывается как время ЦПУ, использованное процессом. А вот время, проведенное в состоянии готовности к исполнению, не считается временем ЦПУ, использованным процессом. Однако когда процесс завершает свою работу, разность e = e1-e0, естественно, включает в себя все время, проведенное процессом во всех состояниях на диаграмме состояний процесса. В результате все время, проведенное в состоянии готовности к выполнению, учитывается в значении e, но не учитывается ни в объеме процессорного времени, ни в каких-то других характеристиках, измеряемых приложением. Все обстоит так, как будто процесс ударили по голове, а затем разбудили, и при этом нет никакой информации о том, что происходило, пока он был без сознания.
Именно это и происходит с каждым процессом по мере добавления параллельных процессов, как показано в табл. 7.2. Естественно, чем больше процессов находится в состоянии готовности к ожиданию, тем дольше каждому процессу приходится дожидаться своей очереди на использование процессора. Чем дольше ожидание, тем больше общая продолжительность выполнения программы. Для трех и четырех пользователей неучтенное время увеличивается пропорционально. Все просто: один и тот же пирог (процессорное время) делится между все большим и большим количеством едоков (пользователей, исполняющих программу P). Так что «чинить» измерительные инструменты программы P незачем. Достаточно понять, как оценить количество неучтенного времени, которое можно отнести на счет времени, в течение которого процесс не выполнялся.
Наличие и точный размер такого промежутка времени чрезвычайно важны для аналитика по производительности Oracle. Величина этого промежутка позволяет определить на основе данных расширенной трассировки SQL, чем вызваны проблемы производительности -излишней подкачкой или же длительным ожиданием в очереди на использование процессора.
< Предыдущая |
---|