1
0
mirror of https://github.com/php/doc-ja.git synced 2026-03-24 07:02:08 +01:00
Files
archived-doc-ja/features/dtrace.xml
Yoshinari Takaoka e62ed7ce7c ビルド時の Wrong XML file: エラーを解消。
php doc-base/scripts/broken.php --dos2unix ja

ビルド時の冪等性を保つと Andre は言っているが、これだと Windows で安易に phpdoc を編集できなくなるねぇ。
2025-08-05 18:38:57 +09:00

576 lines
22 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: d35d7d811ccf7662eefe4f23ff1cabc727a917ca Maintainer: satoruyoshida Status: ready -->
<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 は、OS の挙動およびユーザー・プログラムの実行を追跡できます。
それは、引数の値を表示したり、パフォーマンス統計を推定することに使用できます。
プローブは、DTrace D スクリプト言語で書かれた
ユーザー作成のスクリプトによりモニターされます。
これにより、データ・ポイントの効率的な分析が可能になります。
</para>
<para>
ユーザーの DTrace D スクリプトによりアクティブにモニターされていない
PHP プローブには計装化コードを含みません。
それは、通常のアプリケーション実行中は、パフォーマンス低下がないからです。
モニターされているプローブのオーバーヘッド負荷は、
一般的に作業中の本番システム上で DTrace をモニターしてもよいほど十分な低さです。
</para>
<para>
PHP は、ランタイムで駆動された
"User-level Statically Defined Tracing (USDT。ユーザーレベルの静的に定義されたトレーシング)"
プローブを組み入れます。
例えば、D スクリプトが PHP の <literal>function-entry</literal> プローブをモニター中の場合、
PHP スクリプトの関数が呼ばれるたびにこのプローブは発射され、
関連付けられた D スクリプトの実行コードが実行されます。
この実行コードは、例えば PHP 関数のソースファイルの場所のような、
プローブの引数を印刷したり、
各関数が呼ばれる回数のようなデータを集計できるでしょう。
</para>
<para>
PHP USDT プローブの記述はここだけです。
任意の関数をトレースするために DTrace を使用する方法、
および OS の挙動をトレースするための使用方法については、
外部の一般および OS 固有の DTrace の文献を参照ください。
すべての DTrace の機能がすべての DTrace 実装で使用可能とは
限らないことに注意してください。
</para>
<para>
PHP での静的な DTrace プローブは、
一部の Linux ディストリビューションの SystemTap 機能に対して
代わりに使用できます。
</para>
</sect1>
<sect1 xml:id="features.dtrace.dtrace">
<title>PHP および DTrace の使用</title>
<para>
DTrace 動的トレーシングをサポートするプラットフォームでは、
DTrace 静的プローブ付きで PHP を構成できます。
</para>
<sect2 xml:id="features.dtrace.install">
<title>DTrace 静的プローブのために PHP を構成</title>
<para>
OS の 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>
<literal>--enable-dtrace</literal> 構成パラメータとともに PHP をビルドします。
<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>コア PHP の DTrace 静的プローブ</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>op コードの配列が実行される際に発射されます。
例えば、関数の呼び出し、インクルードおよびジェネレータ続行時に発射されます。</entry>
<entry>char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
</row>
<row>
<entry><literal>execute-return</literal></entry>
<entry>op コードの配列の実行後に発射されます。</entry>
<entry>char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
</row>
<row>
<entry><literal>function-entry</literal></entry>
<entry>PHP エンジンが、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 エンジンが、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>PHP の DTrace 静的プローブ一覧</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> および
現在実行中の PHP プロセスのプロセス ID から構成されます。
</para>
<para>
Apache Web サーバーが実行中の場合、モジュール名は、例えば
<filename>libphp5.so</filename> かもしれません。
そして、実行中の Apache プロセスごとに 1 つ、
一覧表の複数のブロックが存在するかもしれません。
</para>
<para>
FUNCTION 列は、各プロバイダが配置された PHP 内部の C 実装関数名を参照します。
</para>
<para>
PHP プロセスが実行されていない場合、PHP プローブは表示されません。
</para>
</sect2>
<sect2 xml:id="features.dtrace.examples">
<title>PHP についての DTrace の例</title>
<para>
この例では、DTrace の D スクリプト言語の基本を示します。
<example>
<title>
DTrace を使用してすべての PHP 静的プローブをトレースするための<filename>all_probes.d</filename>
</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>
このスクリプトは、<filename>dtrace</filename> に対して
<literal>-Z</literal> オプションを使用します。
それにより、実行中の 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> を使用して
D スクリプトを終わらせることができます。
</para>
<para>
マルチ CPU マシンでは、プローブの順序は規則的に連続して表示されないことがあります。
これは、どの CPU がプローブを処理し、
CPU の間をスレッドがどのように移動したかに依存します。
プローブのタイムスタンプを表示すると、
混乱を減らすことができます。
その例です。
<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>PHP DTrace 静的プローブとともに SystemTap を使用</title>
<para>
一部の Linux ディストリビューションでは、
PHP の静的な DTrace プローブをトレースするために
SystemTap トレーシング・ユーティリティを使用できます。
これは、PHP 5.4.20 および PHP 5.5 で使用できます。
</para>
<sect2 xml:id="features.dtrace.systemtap-install">
<title>SystemTap とともに PHP をインストール</title>
<para>
SystemTap SDT 開発パッケージをインストールします。
<informalexample>
<programlisting role="shell">
<![CDATA[
# yum install systemtap-sdt-devel
]]>
</programlisting>
</informalexample>
</para>
<para>
DTrace プローブが有効化された状態で PHP をインストールします。
<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>
<filename>stap</filename> を使用して PHP の静的プローブを一覧表示できます。
<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>PHP についての SystemTap の例</title>
<para>
<example>
<title>SystemTap を使用してすべての PHP 静的プローブをトレースするための<filename>all_probes.stp</filename></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
-->