ак программное обеспечение измеряет само себя
Понять, каким образом ядро Oracle осуществляет измерение собственных характеристик, не слишком сложно. Основой этого раздела послужили наши исследования ядер Oracle8i и Oracle9i, работающих в ОС Linux. Программное обеспечение Oracle в разных операционных системах может использовать разные системные вызовы. Для того чтобы разобраться с этим, необходимо с помощью программы, выполняющей трассировку системных вызовов определенного процесса, посмотреть, что делает система Oracle. Например, Linux предоставляет для трассировки системных вызовов инструментальное средство strace. В других операционных системах такие программы называются иначе: truss для ОС Sun Solaris (в действительности truss изначально был инструментом трассировки системных вызовов для Unix), sctrace для IBM AIX, tusc для HP-UX и st race для Windows. В дальнейшем я буду говорить о принятом в Linux
strace как о семействе инструентов трассировки системных вызовов.
Н
а
момент написания этой книги инструментарий st race для различных операционных систем доступен по адресу http:// www.pugcentral.org/howto/truss.htm.
Программа strace проста в употреблении. Например, можно непосредственно наблюдать за деятельностью ядра Oracle, выполнив такую команду:
В данном случае strace сообщает о том, что приложение Linux с идентификатором процесса ID 12417 (в моей системе это процесс ядра Oracle) вызвала функцию чтения read и ожидает выполнения этого вызова (поэтому в выводе отсутствует правая скобка).
Чрезвычайно полезно просматривать вывод st race и вывод трассировки Oracle SQL одновременно в двух окнах, чтобы видеть, когда строки появляются в обоих потоках вывода. Вызовы write, посредством которых ядро Oracle передает данные трассировки, естественно, появляются в выводе strace именно тогда, когда и ожидается. Благодаря присутствию этих вызовов легче понять, в какой момент действия ядра Oracle порождают данные трассировки. В Oracle9i для Linux (и Oracle9i для некоторых других операционных систем) сопоставить вывод strace и вывод трассировки SQL очень просто, т. к. значения, возвращаемые gettimeofday, сразу же появляются файле трассировки в качестве значений tim. Применяя таким образом одновременно strace и трассировку SQL, можно подтвердить или опровергнуть тот факт, что ваше ядро Oracle ведет себя так же, как приведенный в последующих разделах псевдокод.
Применение strace вызовет значительный эффект влияния измерителя (measurement intrusion effect) на производительность исследуемой программы. Этот эффект обсуждается ниже в данной главе.
Ядро Oracle получает все свои временные статистики с помощью вызовов операционной системы, в которой оно выполняется. В примере 7.1 показано, как программа, подобная ядру Oracle, вычисляет продолжительность собственных действий.
Пример 7.1. Программа измеряет собственное время отклика
Функция gettimeofday - это системный вызов, имеющийся в POSIX-со-вместимых системах. Обратившись к документации на ОС, вы узнаете, что gettimeofday возвращает вызывающей программе структуру данных языка C, содержащую количество секунд и микросекунд, прошедших с начала эры Unix - 00:00:00 UTC 1 января 1970 года.
Обычно сведения о таких системных вызовах доступны в документации на ОС. Например, в Unix-системах для получения информации о gettimeofday можно ввести в командной строке man gettimeofday. Получить определение POSIX можно по адресу http://www.unix-systems.org/single_unix_specification/
Имейте в виду, что в своем псевдокоде я, чтобы не отвлекать вас, опустил ряд второстепенных деталей. Например, на самом деле функция gettimeofday возвращает не время, а 0 в случае успешного выполнения и -1 при неудаче. «Возвращаемое» время записывается в двухэлементную (составляющая секунд и составляющая микросекунд) структуру по адресу, указанному первым аргументом вызова gettimeofday. Я считаю, что приведение всех этих подробностей в псевдокоде лишь усложнило бы
описание.
Попробуем изобразить выполнение примера 7.1 на оси времени, как показано на рис. 7.2. На рисунке значение gettimeofday t0 = 1492 в момент начала выполнения функции под названием do_something. В момент окончания работы do_something значение gettimeofday t1 = 1498. Следовательно, измеренная длительность исполнения do_something -это t = t1 - t0 = 6 тактов системных часов.
Чтобы упростить восприятие, я взял для времени значения в интервале 1492-1499. Конечно же, они не похожи на реальные значения секунд и микросекунд, которые gettimeofday возвращает в двадцать первом веке. Можно считать, что это последние несколько разрядов реальных значений времени.
Ядро Oracle выводит две разновидности фактической продолжительности: величина e отражает длительность отдельного вызова базы данных, а величина ela - протяженность последовательности инструкций, исполняемой процессом ядра Oracle и снабженной измерительными средствами (часто это системный вызов). Ядро выполняет такие вычисления, исполняя код, организованный приблизительно так же, как псевдокод в примере 7.2. Обратите внимание, что ядро задейству-
Ядро Oracle выводит не только фактическую продолжительность e для каждого вызова базы данных и ela для каждого системного вызова, но и общий объем процессорного времени, израсходованного каждым вызовом базы данных. В контексте диаграммы состояний и переходов, представленной на рис. 7.1, величина c может быть определена как приблизительное количество времени, в течение которого процесс находился в одном из двух режимов:
пользовательском привилегированном
В POSIX-совместимых системах ядро Oracle получает информацию об использовании процессора от функции getrusage (как, например, в ОС Linux и многих других) или от аналогичной функции times в HP-UX и некоторых других ОС. Несмотря на то, что спецификации этих двух системных вызовов значительно отличаются друг от друга, я буду употреблять имя getrusage, подразумевая при этом обе функции. Каждая функция предоставляет вызывающей программе разнообразную статистику процесса, включая структуры данных, содержащие следующие четыре характеристики:
Приблизительное время, проведенное процессом в пользовательском режиме.
Приблизительное время, проведенное процессом в привилегированном режиме.
Приблизительное время, проведенное потомками процесса в пользовательском режиме.
• Приблизительное время, проведенное потомками процесса в привилегированном режиме.
Каждая из этих величин выражается в микросекундах независимо от точности полученных данных.
Скоро вы узнаете, что, хотя стандарт POSIX и предписывает функции getrusage возвращать результат в микросекундах, точность информации в нем редко превышает доли сантисекунд.
Ядро Oracle вычисляет c, e и ela, выполняя код, устроенный приблизительно так же, как псевдокод, приведенный в примере 7.3. Обратите внимание, что этот пример основан на примере 7.2 - он включает в себя исполнение системного вызова getrusage и последующую обработку результатов. Аналогично вычислениям, производимым gettimeofday, ядро Oracle отмечает объем времени процессора, израсходованного процессом на момент начала вызова базы данных, а затем - на момент завершения вызова. Разность между этими двумя значениями (cO и c1)- это приблизительный объем процессорного времени, израсходованного вызовом базы данных. Чуть позже я расскажу о том, насколько приблизительна эта величина.
Пример 7.3. Псевдокод, показывающий, как ядро Oracle измеряет собственное время исполнения и использованное процессорное время
< Предыдущая | Следующая > |
---|