1
0
mirror of https://github.com/php/doc-de.git synced 2026-03-24 07:12:15 +01:00
Files
archived-doc-de/features/dtrace.xml
Martin Samesch bff9d5eb87 Sync with EN
2025-02-22 19:43:22 +01:00

583 lines
21 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: d35d7d811ccf7662eefe4f23ff1cabc727a917ca Maintainer: samesch 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 Dynamic Tracing (Anwendungsanalyse in Echtzeit)</title>
<sect1 xml:id="features.dtrace.introduction">
<title>Einführung in PHP und DTrace</title>
<para>
DTrace ist ein Tracing-Framework, das immer verfügbar ist, einen geringen
zusätzlichen Rechenaufwand verursacht und auf vielen Plattformen wie
Solaris, macOS, Oracle Linux und BSD zur Verfügung steht. DTrace kann das
Verhalten des Betriebssystems und die Ausführung von Benutzerprogrammen
verfolgen. Es kann Parameterwerte anzeigen und zur Abschätzung von
Leistungsstatistiken verwendet werden. Prüfsonden (Probes) werden durch vom
Benutzer erstellte Skripte, die in der DTrace-Skriptsprache D geschrieben
sind, überwacht. Dies ermöglicht eine effiziente Analyse der Datenpunkte.
</para>
<para>
PHP-Sonden, die nicht aktiv vom DTrace-D-Skript eines Benutzers überwacht
werden, enthalten keinen Instrumentierungscode, sodass es während der
normalen Ausführung der Anwendungen keine Leistungseinbußen gibt. Sonden,
die überwacht werden, verursachen im Allgemeinen einen so geringen
zusätzlichen Rechenaufwand, dass die Überwachung mit DTrace auf
Produktivsystemen möglich ist.
</para>
<para>
PHP verfügt über USDT-Sonden, die zur Laufzeit ausgelöst werden (USDT:
User-level Statically Defined Tracing; statisch definiertes Tracing auf
Benutzerebene). Wenn ein D-Skript zum Beispiel PHP's
<literal>function-entry</literal>-Sonde überwacht, löst diese Sonde bei
jedem Funktionsaufruf den entsprechenden D-Skript-Aktionscode aus. Dieser
Aktionscode könnte zum Beispiel die Parameter der Sonde, also &zb; den
Speicherort der Quelldatei dieser PHP-Funktion, ausgeben. Oder die Aktion
könnte Daten sammeln, &zb; wie oft jede Funktion aufgerufen wird.
</para>
<para>
Hier werden nur die PHP-USDT-Sonden beschrieben. Um zu erfahren, wie DTrace
verwendet werden kann, um beliebige Funktionen und das Verhalten des
Betriebssystems zu überwachen, sind die allgemeine und die
betriebssystemspezifische DTrace-Literatur zu empfehlen. Es ist zu
beachten, dass nicht alle DTrace-Funktionen in allen
DTrace-Implementierungen verfügbar sind.
</para>
<para>
Die statischen DTrace-Sonden in PHP können auf einigen Linux-Distributionen
alternativ auch mit SystemTap verwendet werden.
</para>
</sect1>
<sect1 xml:id="features.dtrace.dtrace">
<title>PHP mit DTrace verwenden</title>
<para>
PHP kann auf Plattformen, die DTrace Dynamic Tracing unterstützen, mit
statischen DTrace-Sonden konfiguriert werden.
</para>
<sect2 xml:id="features.dtrace.install">
<title>PHP für statische DTrace-Sonden konfigurieren</title>
<para>
Um die DTrace-Unterstützung des Betriebssystems zu aktivieren, siehe die
externe plattformspezifische Dokumentation. Unter Oracle Linux muss zum
Beispiel ein UEK3-Kernel gebootet und anschließend Folgendes ausgeführt
werden:
<informalexample>
<programlisting role="php">
<![CDATA[
# modprobe fasttrap
# chmod 666 /dev/dtrace/helper
]]>
</programlisting>
</informalexample>
</para>
<para>
Anstatt <literal>chmod</literal> zu verwenden, kann stattdessen eine
ACL-Paketregel verwendet werden, um den Gerätezugriff auf einen bestimmten
Benutzer zu beschränken.
</para>
<para>
PHP mit dem Konfigurationsparameter <literal>--enable-dtrace</literal>
kompilieren:
<informalexample>
<programlisting role="php">
<![CDATA[
# ./configure --enable-dtrace ...
# make
# make install
]]>
</programlisting>
</informalexample>
</para>
<para>
Dadurch werden die statischen Sonden im Kern von PHP verfügbar. Alle
PHP-Erweiterungen, die ihre eigenen Sonden bereitstellen, müssen separat
als dynamische Erweiterungen gebaut werden.
</para>
<para>
Um Sonden zu aktivieren, muss die Umgebungsvariable
<option>USE_ZEND_DTRACE=1</option> für die PHP-Zielprozesse gesetzt werden.
</para>
</sect2>
<sect2 xml:id="features.dtrace.static-probes">
<title>Statische DTrace-Sonden im Kern von PHP</title>
<table>
<title>Die folgenden statischen Sonden stehen in PHP zur Verfügung</title>
<tgroup cols="2">
<thead>
<row>
<entry>Name der Probe</entry>
<entry>Beschreibung der Probe</entry>
<entry>Parameter der Probe</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>request-startup</literal></entry>
<entry>Wird ausgelöst, wenn eine Anfrage beginnt.</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>Wird ausgelöst, wenn eine Anfrage endet.</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>Wird ausgelöst, wenn die Kompilierung eines Skripts beginnt.</entry>
<entry>char *<varname>compile_file</varname>, char *<varname>compile_file_translated</varname></entry>
</row>
<row>
<entry><literal>compile-file-return</literal></entry>
<entry>Wird ausgelöst, wenn die Kompilierung eines Skripts endet.</entry>
<entry>char *<varname>compile_file</varname>, char *<varname>compile_file_translated</varname></entry>
</row>
<row>
<entry><literal>execute-entry</literal></entry>
<entry>
Wird ausgelöst, wenn ein OpCode-Array ausgeführt wird, &zb; bei
Funktionsaufrufen, Includes und wenn ein Generator fortfährt.
</entry>
<entry>char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
</row>
<row>
<entry><literal>execute-return</literal></entry>
<entry>Wird nach der Ausführung eines OpCode-Arrays ausgelöst.</entry>
<entry>char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
</row>
<row>
<entry><literal>function-entry</literal></entry>
<entry>
Wird ausgelöst, wenn die PHP-Engine in eine PHP-Funktion oder -Methode
gelangt.
</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>
Wird ausgelöst, wenn die PHP-Engine aus einer PHP-Funktion oder -Methode
zurückkehrt.
</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>Wird ausgelöst, wenn eine Exception ausgelöst wird.</entry>
<entry>char *<varname>classname</varname></entry>
</row>
<row>
<entry><literal>exception-caught</literal></entry>
<entry>Wird ausgelöst, wenn eine Exception abgefangen wird.</entry>
<entry>char *<varname>classname</varname></entry>
</row>
<row>
<entry><literal>error</literal></entry>
<entry>
Wird ausgelöst, wenn ein Fehler auftritt, unabhängig von der
<link linkend="ini.error-reporting">error_reporting</link>-Stufe.
</entry>
<entry>char *<varname>errormsg</varname>, char *<varname>request_file</varname>, int <varname>lineno</varname></entry>
</row>
</tbody>
</tgroup>
</table>
<para>
PHP-Erweiterungen verfügen möglicherweise über zusätzliche statische Sonden.
</para>
</sect2>
<sect2 xml:id="features.dtrace.list-probes">
<title>Liste statischer DTrace-Sonden in PHP</title>
<para>
Um die verfügbaren Sonden aufzulisten, ist es nötig, einen PHP-Prozess zu
starten und dann Folgendes auszuführen:
<informalexample>
<programlisting>
<![CDATA[
# dtrace -l
]]>
</programlisting>
</informalexample>
</para>
<para>
Die Ausgabe wird ungefähr so aussehen:
<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>
Die Werte der Spalte PROVIDER setzen sich aus <literal>php</literal> und
der Prozess-ID des aktuell laufenden PHP-Prozesses zusammen.
</para>
<para>
Wenn der Apache-Webserver läuft, könnte der Modulname zum Beispiel
<filename>libphp5.so</filename> sein, und es gäbe pro laufendem
Apache-Prozess einen Auflistungs-Block.
</para>
<para>
Die Spalte FUNCTION verweist auf den Funktionsnamen der PHP-internen
C-Implementierung, in der sich der jeweilige Provider befindet.
</para>
<para>
Wenn kein PHP-Prozess läuft, werden auch keine PHP-Sonden angezeigt.
</para>
</sect2>
<sect2 xml:id="features.dtrace.examples">
<title>DTrace-Beispiel für PHP</title>
<para>
Dieses Beispiel zeigt die grundlegenden Möglichkeiten der
DTrace-Skriptsprache D.
<example>
<title><filename>all_probes.d</filename> für die Verfolgung aller statischen PHP-Sonden mit 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>
Dieses Skript verwendet <filename>dtrace</filename> mit der Option
<literal>-Z</literal>, damit es auch dann ausgeführt werden kann, wenn
gerade kein PHP-Prozess läuft. Ohne diese Option würde das Skript sofort
beendet, weil es erkennt, dass keine der zu überwachenden Sonden vorhanden
ist.
</para>
<para>
Das Skript verfolgt während der gesamten Zeit, in der ein PHP-Skript
läuft, alle statischen Sondenpunkte des PHP-Kerns.
<informalexample>
<programlisting>
<![CDATA[
# ./all_probes.d
]]>
</programlisting>
</informalexample>
</para>
<para>
Sobald nun ein PHP-Skript oder eine Anwendung ausgeführt wird, beginnt das
überwachende D-Skript, alle Parameter der ausgelösten Sonden auszugeben.
</para>
<para>
Um die Überwachung abzuschließen, kann das D-Skript mittels
<keycombo action='simul'><keycap>CTRL</keycap><keycap>C</keycap></keycombo>
beendet werden.
</para>
<para>
Auf Rechnern mit mehreren CPUs ist die Reihenfolge der Tests möglicherweise
nicht sequentiell. Dies hängt davon ab, welche CPU die Sonden verarbeitet
hat und wie die Threads zwischen den CPUs wechseln. Die Anzeige der
Zeitstempel der Sonden hilft, Verwechslungen zu vermeiden, zum Beispiel:
<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 und DTrace Dynamic Tracing</link></member>
</simplelist>
</sect2>
</sect1>
<sect1 xml:id="features.dtrace.systemtap">
<title>Verwendung von SystemTap mit statischen PHP-DTrace-Sonden</title>
<para>
Auf einigen Linux-Distributionen kann das Tracing-Tool SystemTap verwendet
werden, um die statischen DTrace-Sonden von PHP zu überwachen. Diese
Möglichkeit steht mit PHP 5.4.20 und PHP 5.5 zur Verfügung.
</para>
<sect2 xml:id="features.dtrace.systemtap-install">
<title>Installation von PHP mit SystemTap</title>
<para>
Installieren des SystemTap-SDT-Entwicklungspakets:
<informalexample>
<programlisting role="shell">
<![CDATA[
# yum install systemtap-sdt-devel
]]>
</programlisting>
</informalexample>
</para>
<para>
Installieren von PHP mit aktivierten DTrace-Sonden:
<informalexample>
<programlisting role="shell">
<![CDATA[
# ./configure --enable-dtrace ...
# make
]]>
</programlisting>
</informalexample>
</para>
</sect2>
<sect2 xml:id="features.dtrace.systemtap-list-probes">
<title>Auflistung statischer Sonden mittels SystemTap</title>
<para>
Die statischen Sonden in PHP können mittels <filename>stap</filename>
aufgelistet werden:
<informalexample>
<programlisting>
<![CDATA[
# stap -l 'process.provider("php").mark("*")' -c 'sapi/cli/php -i'
]]>
</programlisting>
</informalexample>
</para>
<para>
This outputs:
<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>Beispiel für die Verwendung von SystemTap mit PHP</title>
<para>
<example>
<title><filename>all_probes.stp</filename> - Verfolgung aller statischen PHP-Sonden mit SystemTap</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>
Das obige Skript verfolgt während der gesamten Dauer eines laufenden
PHP-Skripts alle statischen Sondenpunkte des PHP-Kerns:
<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
-->