mirror of
https://github.com/php/doc-ru.git
synced 2026-03-24 07:42:22 +01:00
575 lines
24 KiB
XML
575 lines
24 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: d35d7d811ccf7662eefe4f23ff1cabc727a917ca Maintainer: rjhdby Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<chapter xml:id="features.dtrace" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||
<title>Динамическая трассировка DTrace</title>
|
||
|
||
<sect1 xml:id="features.dtrace.introduction">
|
||
<title>Введение в PHP и DTrace</title>
|
||
|
||
<para>
|
||
DTrace — доступный фреймворк трассировки, который практически
|
||
не потребляет ресурсов. Фреймворк
|
||
доступен на множестве платформ, включая Solaris, macOS,
|
||
Oracle Linux и BSD. DTrace умеет отслеживать поведение
|
||
операционной системы и запущенных пользовательских
|
||
приложений. Фреймворк умеет показывать значения параметров
|
||
и выводит статистику производительности.
|
||
Зонды отслеживаются пользовательскими скриптами,
|
||
которые написали на скриптовом языке DTrace D. Это помогает
|
||
эффективно анализировать срезы данных.
|
||
</para>
|
||
|
||
<para>
|
||
Зонды PHP, которые не отслеживаются пользовательскими
|
||
скриптами DTrace D, не содержат дополнительного
|
||
кода и поэтому во время нормальной работы
|
||
приложения производительность
|
||
не деградирует. Отслеживаемые зонды, в свою очередь,
|
||
дают очень низкую просадку производительности, что
|
||
позволяет использовать их в промышленных средах.
|
||
</para>
|
||
|
||
<para>
|
||
PHP включает в себя зонды «Статически определённой
|
||
трассировки уровня пользователя» (User-level Statically
|
||
Defined Tracing, или USDT), которые работают во время
|
||
исполнения. Например, когда D-скрипт отслеживает зонд
|
||
<literal>function-entry</literal>, каждый раз при вызове
|
||
функции этот зонд запускает действие D-скрипта, которое соответствует
|
||
функции. Это действие, например, печатает аргументы
|
||
зонда наподобие расположения этой функции в PHP-скрипте.
|
||
Или же агрегирует данные наподобие
|
||
количества запусков каждой функции.
|
||
</para>
|
||
|
||
<para>
|
||
Здесь описываются только зонды PHP USDT. Информацию
|
||
об отслеживании произвольных функций
|
||
и поведения операционной системы даёт
|
||
литература, специфичная для каждой
|
||
операционной системы, и внешняя полноценная
|
||
документация DTrace. Обратите внимание, что
|
||
реализации DTrace иногда отличаются набором доступного
|
||
функционала.
|
||
</para>
|
||
|
||
<para>
|
||
Статические зонды DTrace в PHP также умеют
|
||
работать со средством SystemTap в отдельных дистрибутивах ОС Linux.
|
||
</para>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="features.dtrace.dtrace">
|
||
<title>PHP и DTrace</title>
|
||
<para>
|
||
PHP конфигурируется со статическими зондами
|
||
DTrace на платформах, которые поддерживают динамическую
|
||
трассировку DTrace.
|
||
</para>
|
||
|
||
<sect2 xml:id="features.dtrace.install">
|
||
<title>Конфигурирование PHP со статическими зондами DTrace</title>
|
||
|
||
<para>
|
||
Обратитесь к документации платформы, чтобы
|
||
включить поддержку DTrace в операционной системе.
|
||
Например, в Oracle Linux требуется загрузить ядро UEK3
|
||
и сделать следующее:
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
# modprobe fasttrap
|
||
# chmod 666 /dev/dtrace/helper
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
<para>
|
||
Вместо <literal>chmod</literal> доступен
|
||
пакет правил ACL для ограничения доступа для конкретного
|
||
пользователя.
|
||
</para>
|
||
|
||
<para>
|
||
Сборка PHP с ключом <literal>--enable-dtrace</literal>:
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
# ./configure --enable-dtrace ...
|
||
# make
|
||
# make install
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
<para>
|
||
Это делает статические зонды доступными в ядре PHP. Любой
|
||
модуль PHP, который предоставляет свои зонды,
|
||
потребуется собрать отдельно как разделяемый модуль.
|
||
</para>
|
||
<para>
|
||
Установите переменную среды <option>USE_ZEND_DTRACE=1</option> для целевых PHP-процессов, чтобы включить зонды.
|
||
</para>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="features.dtrace.static-probes">
|
||
<title>Статические зонды DTrace в ядре PHP</title>
|
||
<table>
|
||
<title>Следующие статические зонды доступны в PHP</title>
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>Название зонда</entry>
|
||
<entry>Описание зонда</entry>
|
||
<entry>Аргументы зонда</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>request-startup</literal></entry>
|
||
<entry>Срабатывает при начале запроса.</entry>
|
||
<entry>char *<varname>file</varname>, char *<varname>request_uri</varname>, char *<varname>request_method</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>request-shutdown</literal></entry>
|
||
<entry>Срабатывает при окончании запроса.</entry>
|
||
<entry>char *<varname>file</varname>, char *<varname>request_uri</varname>, char *<varname>request_method</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>compile-file-entry</literal></entry>
|
||
<entry>Срабатывает, когда начинается компиляция скрипта.</entry>
|
||
<entry>char *<varname>compile_file</varname>, char *<varname>compile_file_translated</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>compile-file-return</literal></entry>
|
||
<entry>Срабатывает, когда заканчивается компиляция скрипта.</entry>
|
||
<entry>char *<varname>compile_file</varname>, char *<varname>compile_file_translated</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>execute-entry</literal></entry>
|
||
<entry>Срабатывает, когда запускается массив байт-кода. К примеру, когда вызываются функции, возобновляется работа генератора или происходит include.</entry>
|
||
<entry>char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>execute-return</literal></entry>
|
||
<entry>Срабатывает, после отработки массива байт-кода.</entry>
|
||
<entry>char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>function-entry</literal></entry>
|
||
<entry>Срабатывает, когда движок PHP начинает запуск функции или метода.</entry>
|
||
<entry>char *<varname>function_name</varname>, char *<varname>request_file</varname>, int <varname>lineno</varname>, char *<varname>classname</varname>, char *<varname>scope</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>function-return</literal></entry>
|
||
<entry>Срабатывает, когда движок PHP возвращается из функции или метода.</entry>
|
||
<entry>char *<varname>function_name</varname>, char *<varname>request_file</varname>, int <varname>lineno</varname>, char *<varname>classname</varname>, char *<varname>scope</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>exception-thrown</literal></entry>
|
||
<entry>Срабатывает, когда выброшено исключение.</entry>
|
||
<entry>char *<varname>classname</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>exception-caught</literal></entry>
|
||
<entry>Срабатывает, когда исключение поймано.</entry>
|
||
<entry>char *<varname>classname</varname></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>error</literal></entry>
|
||
<entry>Срабатывает, если возникла ошибка, независимо от уровня <link linkend="ini.error-reporting">error_reporting</link>.</entry>
|
||
<entry>char *<varname>errormsg</varname>, char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
<para>
|
||
Модули PHP могут содержать дополнительные зонды.
|
||
</para>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="features.dtrace.list-probes">
|
||
<title>Список статических зондов DTrace в PHP</title>
|
||
<para>
|
||
Запустите PHP-процесс и выполните следующую команду, чтобы получить список зондов:
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
# dtrace -l
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
Команда выведет примерно следующее:
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
ID PROVIDER MODULE FUNCTION NAME
|
||
[ . . . ]
|
||
4 php15271 php dtrace_compile_file compile-file-entry
|
||
5 php15271 php dtrace_compile_file compile-file-return
|
||
6 php15271 php zend_error error
|
||
7 php15271 php ZEND_CATCH_SPEC_CONST_CV_HANDLER exception-caught
|
||
8 php15271 php zend_throw_exception_internal exception-thrown
|
||
9 php15271 php dtrace_execute_ex execute-entry
|
||
10 php15271 php dtrace_execute_internal execute-entry
|
||
11 php15271 php dtrace_execute_ex execute-return
|
||
12 php15271 php dtrace_execute_internal execute-return
|
||
13 php15271 php dtrace_execute_ex function-entry
|
||
14 php15271 php dtrace_execute_ex function-return
|
||
15 php15271 php php_request_shutdown request-shutdown
|
||
16 php15271 php php_request_startup request-startup
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
Колонка Provider содержит надпись <literal>php</literal>
|
||
и PID-идентификатор текущего запущенного PHP-процесса.
|
||
</para>
|
||
|
||
<para>
|
||
При работе веб-сервера Apache название модуля выводится как,
|
||
например, <filename>libphp5.so</filename>, и выводятся
|
||
серия блоков списка, по одному на каждый процесс Apache.
|
||
</para>
|
||
|
||
<para>
|
||
Колонка Function ссылается на название внутренней С-функции PHP,
|
||
которая реализует соответствующий зонд.
|
||
</para>
|
||
|
||
<para>
|
||
Список не будет содержать зонды, которые связаны с PHP, если PHP не запустили.
|
||
</para>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="features.dtrace.examples">
|
||
<title>Примеры работы DTrace с PHP</title>
|
||
<para>
|
||
Пример показывает базовые возможности скриптового языка DTrace D.
|
||
<example>
|
||
<title>Скрипт <filename>all_probes.d</filename> — трассировка статических PHP-зондов через DTrace</title>
|
||
<programlisting>
|
||
<![CDATA[
|
||
#!/usr/sbin/dtrace -Zs
|
||
|
||
#pragma D option quiet
|
||
|
||
php*:::compile-file-entry
|
||
{
|
||
printf("PHP compile-file-entry\n");
|
||
printf(" compile_file %s\n", copyinstr(arg0));
|
||
printf(" compile_file_translated %s\n", copyinstr(arg1));
|
||
}
|
||
|
||
php*:::compile-file-return
|
||
{
|
||
printf("PHP compile-file-return\n");
|
||
printf(" compile_file %s\n", copyinstr(arg0));
|
||
printf(" compile_file_translated %s\n", copyinstr(arg1));
|
||
}
|
||
|
||
php*:::error
|
||
{
|
||
printf("PHP error\n");
|
||
printf(" errormsg %s\n", copyinstr(arg0));
|
||
printf(" request_file %s\n", copyinstr(arg1));
|
||
printf(" lineno %d\n", (int)arg2);
|
||
}
|
||
|
||
php*:::exception-caught
|
||
{
|
||
printf("PHP exception-caught\n");
|
||
printf(" classname %s\n", copyinstr(arg0));
|
||
}
|
||
|
||
php*:::exception-thrown
|
||
{
|
||
printf("PHP exception-thrown\n");
|
||
printf(" classname %s\n", copyinstr(arg0));
|
||
}
|
||
|
||
php*:::execute-entry
|
||
{
|
||
printf("PHP execute-entry\n");
|
||
printf(" request_file %s\n", copyinstr(arg0));
|
||
printf(" lineno %d\n", (int)arg1);
|
||
}
|
||
|
||
php*:::execute-return
|
||
{
|
||
printf("PHP execute-return\n");
|
||
printf(" request_file %s\n", copyinstr(arg0));
|
||
printf(" lineno %d\n", (int)arg1);
|
||
}
|
||
|
||
php*:::function-entry
|
||
{
|
||
printf("PHP function-entry\n");
|
||
printf(" function_name %s\n", copyinstr(arg0));
|
||
printf(" request_file %s\n", copyinstr(arg1));
|
||
printf(" lineno %d\n", (int)arg2);
|
||
printf(" classname %s\n", copyinstr(arg3));
|
||
printf(" scope %s\n", copyinstr(arg4));
|
||
}
|
||
|
||
php*:::function-return
|
||
{
|
||
printf("PHP function-return\n");
|
||
printf(" function_name %s\n", copyinstr(arg0));
|
||
printf(" request_file %s\n", copyinstr(arg1));
|
||
printf(" lineno %d\n", (int)arg2);
|
||
printf(" classname %s\n", copyinstr(arg3));
|
||
printf(" scope %s\n", copyinstr(arg4));
|
||
}
|
||
|
||
php*:::request-shutdown
|
||
{
|
||
printf("PHP request-shutdown\n");
|
||
printf(" file %s\n", copyinstr(arg0));
|
||
printf(" request_uri %s\n", copyinstr(arg1));
|
||
printf(" request_method %s\n", copyinstr(arg2));
|
||
}
|
||
|
||
php*:::request-startup
|
||
{
|
||
printf("PHP request-startup\n");
|
||
printf(" file %s\n", copyinstr(arg0));
|
||
printf(" request_uri %s\n", copyinstr(arg1));
|
||
printf(" request_method %s\n", copyinstr(arg2));
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<para>
|
||
Скрипт указывает опцию <literal>-Z</literal>
|
||
для команды <filename>dtrace</filename>, разрешая работать даже
|
||
если ни однин PHP-процесс не запущен. Без этой опции
|
||
скрипт сразу же завершит выполнение, поскольку
|
||
не увидит ни одного зонда, который требуется отслеживать.
|
||
</para>
|
||
|
||
<para>
|
||
Скрипт отслеживает каждый статический PHP-зонд на всём
|
||
протяжении работы PHP-скрипта.
|
||
Запускаем D-скрипт:
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
# ./all_probes.d
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
Запустите скрипт или PHP-приложение. Отслеживающий D-скрипт
|
||
будет выводить аргументы каждого сработавшего зонда.
|
||
</para>
|
||
|
||
<para>
|
||
После получения информации работу скрипта
|
||
прерывают комбинацией <keycombo action='simul'><keycap>CTRL</keycap><keycap>C</keycap></keycombo>.
|
||
</para>
|
||
|
||
<para>
|
||
На многопроцессорных машинах порядок зондов
|
||
непоследователен и зависит от процессоров,
|
||
на которых работают зонды и как мигрируют потоки между процессорами.
|
||
Отображение временных меток помогает избегать конфузов.
|
||
К примеру:
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
php*:::function-entry
|
||
{
|
||
printf("%lld: PHP function-entry ", walltimestamp);
|
||
[ . . .]
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="features.dtrace.references">
|
||
&reftitle.seealso;
|
||
<simplelist>
|
||
<member><link linkend="oci8.dtrace">OCI8 и динамическая трассировка DTrace</link></member>
|
||
</simplelist>
|
||
</sect2>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="features.dtrace.systemtap">
|
||
<title>Работа средства SystemTap со статическими зондами PHP DTrace</title>
|
||
<para>
|
||
В отдельных дистрибутивах Linux для отслеживания статических зондов
|
||
DTrace доступна утилита трассировки SystemTap.
|
||
Этот вариант доступен в PHP 5.4.20 и PHP 5.5.
|
||
</para>
|
||
|
||
<sect2 xml:id="features.dtrace.systemtap-install">
|
||
<title>Установка PHP с SystemTap</title>
|
||
|
||
<para>
|
||
Установите разработческий пакет SystemTap SDT:
|
||
<informalexample>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
# yum install systemtap-sdt-devel
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
Установите PHP с DTrace:
|
||
<informalexample>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
# ./configure --enable-dtrace ...
|
||
# make
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="features.dtrace.systemtap-list-probes">
|
||
<title>Получение списка статических зондов через SystemTap</title>
|
||
|
||
<para>
|
||
Статические PHP-зонды умеет выводить команда <filename>stap</filename>:
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
# stap -l 'process.provider("php").mark("*")' -c 'sapi/cli/php -i'
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
|
||
<para>
|
||
Примерный вывод:
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
process("sapi/cli/php").provider("php").mark("compile__file__entry")
|
||
process("sapi/cli/php").provider("php").mark("compile__file__return")
|
||
process("sapi/cli/php").provider("php").mark("error")
|
||
process("sapi/cli/php").provider("php").mark("exception__caught")
|
||
process("sapi/cli/php").provider("php").mark("exception__thrown")
|
||
process("sapi/cli/php").provider("php").mark("execute__entry")
|
||
process("sapi/cli/php").provider("php").mark("execute__return")
|
||
process("sapi/cli/php").provider("php").mark("function__entry")
|
||
process("sapi/cli/php").provider("php").mark("function__return")
|
||
process("sapi/cli/php").provider("php").mark("request__shutdown")
|
||
process("sapi/cli/php").provider("php").mark("request__startup")
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="features.dtrace.systemtap-examples">
|
||
<title>Пример работы SystemTap с PHP</title>
|
||
|
||
<para>
|
||
<example>
|
||
<title>Скрипт <filename>all_probes.stp</filename> — трассировка статических PHP-зондов</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
probe process("sapi/cli/php").provider("php").mark("compile__file__entry") {
|
||
printf("Probe compile__file__entry\n");
|
||
printf(" compile_file %s\n", user_string($arg1));
|
||
printf(" compile_file_translated %s\n", user_string($arg2));
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("compile__file__return") {
|
||
printf("Probe compile__file__return\n");
|
||
printf(" compile_file %s\n", user_string($arg1));
|
||
printf(" compile_file_translated %s\n", user_string($arg2));
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("error") {
|
||
printf("Probe error\n");
|
||
printf(" errormsg %s\n", user_string($arg1));
|
||
printf(" request_file %s\n", user_string($arg2));
|
||
printf(" lineno %d\n", $arg3);
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("exception__caught") {
|
||
printf("Probe exception__caught\n");
|
||
printf(" classname %s\n", user_string($arg1));
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("exception__thrown") {
|
||
printf("Probe exception__thrown\n");
|
||
printf(" classname %s\n", user_string($arg1));
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("execute__entry") {
|
||
printf("Probe execute__entry\n");
|
||
printf(" request_file %s\n", user_string($arg1));
|
||
printf(" lineno %d\n", $arg2);
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("execute__return") {
|
||
printf("Probe execute__return\n");
|
||
printf(" request_file %s\n", user_string($arg1));
|
||
printf(" lineno %d\n", $arg2);
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("function__entry") {
|
||
printf("Probe function__entry\n");
|
||
printf(" function_name %s\n", user_string($arg1));
|
||
printf(" request_file %s\n", user_string($arg2));
|
||
printf(" lineno %d\n", $arg3);
|
||
printf(" classname %s\n", user_string($arg4));
|
||
printf(" scope %s\n", user_string($arg5));
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("function__return") {
|
||
printf("Probe function__return: %s\n", user_string($arg1));
|
||
printf(" function_name %s\n", user_string($arg1));
|
||
printf(" request_file %s\n", user_string($arg2));
|
||
printf(" lineno %d\n", $arg3);
|
||
printf(" classname %s\n", user_string($arg4));
|
||
printf(" scope %s\n", user_string($arg5));
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("request__shutdown") {
|
||
printf("Probe request__shutdown\n");
|
||
printf(" file %s\n", user_string($arg1));
|
||
printf(" request_uri %s\n", user_string($arg2));
|
||
printf(" request_method %s\n", user_string($arg3));
|
||
}
|
||
probe process("sapi/cli/php").provider("php").mark("request__startup") {
|
||
printf("Probe request__startup\n");
|
||
printf(" file %s\n", user_string($arg1));
|
||
printf(" request_uri %s\n", user_string($arg2));
|
||
printf(" request_method %s\n", user_string($arg3));
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Приведённый скрипт выводит данные статических
|
||
PHP-зондов на всём протяжении работы PHP-скрипта:
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
# stap -c 'sapi/cli/php test.php' all_probes.stp
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</sect2>
|
||
</sect1>
|
||
</chapter>
|
||
<!-- Keep this comment at the end of the file
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|