DeepEdit!

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

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Время «невыполнения»

ремя «невыполнения»

Давайте проделаем небольшой мысленный эксперимент для того, что­бы познакомиться с четвертой причиной наличия неучтенного времени в корректно собранных данных трассировки Oracle. Представьте себе программу P, которая ровно десять секунд занимает процессор в пользовательском режиме и формирует вывод на терминал. Пусть такая программа циклически запускается на компьютере с одним процессо­ром. Если тот, кто запускает ее, является единственным пользовате­лем данной системы, то он должен ожидать, что время отклика для каждого выполнения составит 10 секунд.
Наблюдая за использованием процессора на данной однопроцессорной машине в ходе многократного выполнения одним пользователем, можно заметить, что процессор все это время будет работать со 100% загрузкой. Но что будет, если добавить второй экземпляр циклично выполняющейся программы в однопроцессорную систему? В рамках любого одного десятисекундного интервала времени однопроцессор­ный компьютер может предоставить только десять секунд процессор­ного времени. То есть невозможно ожидать полного выполнения двух экземпляров программы, требующих по десять секунд процессорного времени, в течение одного десятисекундного промежутка времени. Можно предположить, что время отклика для каждого из экземпля­ров возрастет приблизительно до 20 секунд. Столько времени потре­буется одному процессору для того, чтобы предоставить по десять се­кунд своего времени каждому из конкурирующих процессов, если он будет распределять его равномерно и небольшими порциями двум па­раллельным процессам.
Измерения в эксперименте
Предположим, что мы добавили в наш код измерительные средства, подобные применяемым в ядре Oracle, как это показано в примере 7.6.
Пример 7.6 Программа P оснащена средствами для вывода собственного времени отклика и использованного процессорного времени
Теперь попробуем предсказать значения выводимых временных ста­тистик для каждого указанного уровня параллелизма в однопроцес­сорной системе (табл. 7.2). Ожидаем, что программа будет потреб­лять одинаковый общий объем процессорного времени независимо от занятости системы. Но, конечно же, учитывая, что ресурсы процес­сора по мере увеличения уровня параллелизма разделяется между воз­растающим количеством пользователей, можно ожидать замедления выполнения программы и увеличения периодов времени, прошедших прежде, чем программе удастся получить необходимые ей десять се­кунд времени процессора.
Таблица 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 должна быть исключена из круга подозреваемых, т. к. она вызывается вне области действия таймеров). Очевидно, что соотношение + Eela = 10 является очень плохим приближением для = 20. На что ушло «потерянное время»? Из табл. 7.2 видно, что ситуация ухудшается с увеличением количест­ва пользователей. Что же мы сделали не так, добавив в измеритель­ные средства?
Еще раз о состояниях процессов и переходах
Для того чтобы упросить ответ на вопрос, обратимся к рис. 7.1. Вспом­ним о том, что даже когда процесс спокойно выполняется в пользова­тельском режиме, в большинстве систем каждую сотую долю секунды происходит прерывание по системному таймеру. Такое регулярно повто­ряющееся прерывание переводит каждый работающий процесс в приви­легированный режим. Перейдя в привилегированный режим, процесс сохраняет текущий контекст, а затем выполняет подпрограмму плани­ровщика (см. раздел «Переход по прерыванию» выше в этой главе). Ес­ли присутствует процесс в состоянии готовности к исполнению, то поли­тика планирования системы может потребовать приостановки обслу­живания (вытеснения) исполняемого процесса и предоставления гото­вому к исполнению процессу возможности использовать процессор.
Обратите внимание на то, что при этом происходит с процессом, кото­рый выполнялся изначально. Когда он прерывается, то сразу же пере­ходит в привилегированный режим. Заметьте, что у процесса нет ника­кой возможности выполнить какой-либо код, с тем чтобы узнать, в какое время произошел такой переход. Когда обслуживание процес­са приостанавливается, он переходит в состояние готовности к выпол­нению, ожидая, когда планировщик продолжит его выполнение. Когда наконец наступает его время (возможно, это будет уже через каких-то 10 миллисекунд), процесс проводит в привилегированном режиме столько времени, сколько необходимо для восстановления его контек­ста, а затем возвращается в пользовательский режим, ровно в то место, на котором остановился.

Как вытеснение процесса влияет на получаемые хронометрические данные? Время, которое процессор проводит в привилегированном ре­жиме, пока планировщик готовится к вытеснению процесса, учитыва­ется как время ЦПУ, использованное процессом. А вот время, прове­денное в состоянии готовности к исполнению, не считается временем ЦПУ, использованным процессом. Однако когда процесс завершает свою работу, разность e = e1-e0, естественно, включает в себя все вре­мя, проведенное процессом во всех состояниях на диаграмме состоя­ний процесса. В результате все время, проведенное в состоянии готов­ности к выполнению, учитывается в значении e, но не учитывается ни в объеме процессорного времени, ни в каких-то других характеристи­ках, измеряемых приложением. Все обстоит так, как будто процесс ударили по голове, а затем разбудили, и при этом нет никакой инфор­мации о том, что происходило, пока он был без сознания.
Именно это и происходит с каждым процессом по мере добавления па­раллельных процессов, как показано в табл. 7.2. Естественно, чем больше процессов находится в состоянии готовности к ожиданию, тем дольше каждому процессу приходится дожидаться своей очереди на использование процессора. Чем дольше ожидание, тем больше общая продолжительность выполнения программы. Для трех и четырех поль­зователей неучтенное время увеличивается пропорционально. Все про­сто: один и тот же пирог (процессорное время) делится между все большим и большим количеством едоков (пользователей, исполняющих программу P). Так что «чинить» измерительные инструменты про­граммы незачем. Достаточно понять, как оценить количество неуч­тенного времени, которое можно отнести на счет времени, в течение которого процесс не выполнялся.
Наличие и точный размер такого промежутка времени чрезвычайно важны для аналитика по производительности Oracle. Величина этого промежутка позволяет определить на основе данных расширенной трассировки SQL, чем вызваны проблемы производительности -излишней подкачкой или же длительным ожиданием в очереди на ис­пользование процессора.

 









jAntivirus