<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SysEleven - Hosting für Fortgeschrittene &#187; PHP</title>
	<atom:link href="http://www.syseleven.de/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.syseleven.de</link>
	<description></description>
	<lastBuildDate>Tue, 24 Jan 2012 16:33:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2</generator>
		<item>
		<title>Performance-Profliling bei SysEleven</title>
		<link>http://www.syseleven.de/blog/1906/performance-profliling-bei-syseleven/</link>
		<comments>http://www.syseleven.de/blog/1906/performance-profliling-bei-syseleven/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 12:40:26 +0000</pubDate>
		<dc:creator>Thomas Lohner</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Profiling]]></category>

		<guid isPermaLink="false">http://www.syseleven.de/?p=1906</guid>
		<description><![CDATA["Bei uns hört die Dienstleistung nicht auf, wenn die Lampe am Server grün leuchtet" - Lesen Sie in diesem Blogbeitrag wie wir bei SysEleven die Performance Ihrer Webseite analysieren.]]></description>
			<content:encoded><![CDATA[<p>&#8220;Bei uns hört die Dienstleistung nicht auf, wenn die Lampe am Server grün leuchtet&#8221; &#8211; das ist nicht nur einer der Sätze, mit denen ich in letzter Zeit am Liebsten zitiert werde, sondern auch der Titel einer neuen Blogreihe, in der ich erklären möchte, was bei SysEleven anders ist als bei herkömmlichen Hostinganbietern. Wir haben eine besondere Einstellung zu dem was wir tun und wie wir es tun &#8211; wir nennen das den SysEleven Faktor.</p>
<p>Im heutigen Teil dieser Reihe geht es um die Steigerung der Performance von Webseiten oder E-Commerce Shops. Manche unserer Kunden nennen das „Serverpower“ oder gerne auch „Vollgas Hosting“. Und da haben wir auch schon das Missverständnis: Natürlich gehören zu einer schnellen Webseite auch schnelle Server &#8211; aber nicht nur. Die Performance der Software ist ebenso wichtig. Die besten und schnellsten Server machen Ihre Webseite nicht schneller, wenn die Software mit angezogener Handbremse fährt &#8211; und umgekehrt genauso.</p>
<blockquote><p><span style="font-size:1.2em;">Die Performance einer Webseite wird durch das schwächste Glied der Kette bestimmt und nicht etwa durch die schnellste Komponente des Setups, wie viele irrtümlich glauben.</span></p></blockquote>
<p>Die erste und wichtigste Teilaufgabe bei der Optimierung von Webperformance lautet also: Finde das schwächste Glied der Kette. Fachleute nennen das den Flaschenhals bzw. das Bottleneck. Je mehr Änderungen es beispielsweise an einem Online-Shop gab und je mehr Köche den Brei gerührt haben, umso komplexer und schwieriger wird die Suche nach dem Bottleneck. Erschwerend kommt hinzu, dass es laut unserer Erfahrung im Grunde nie ein einzelnes, sichtbares Bottleneck gibt. Meistens finden wir eine Verkettung „unglücklicher Umstände“ und „gewachsener Strukturen“, die gemeinsam die Performance in den Keller ziehen. Nicht selten finden wir sogar Features, die schon lange nicht mehr benutzt werden, aber immer noch aktiv sind und Last erzeugen.</p>
<p>
<h1>Was ist das Ziel?</h1>
</p>
<p>Das Ziel des Performance-Profilings ist die Identifikation der Bottlenecks. Als Ergebnis dieser Analyse sollte ein Maßnahmenkatalog mit konkreten Verbesserungsvorschlägen und Aufgaben vorliegen. Im Übrigen gehört zum SysEleven Faktor auch, dass es an dieser Stelle eine strikte Trennung gibt: Wir helfen dabei die Bottlenecks zu finden und liefern eine Anleitung wie sie behoben werden können. Die hardware- bzw. serverseitige Umsetzung erfolgt direkt durch uns und die softwareseitige Umsetzung erfolgt durch die Agentur des Kunden bzw. durch die Entwickler, die das jeweilige Setup viel detaillierter kennen. Das beste Ergebnis lässt sich erzielen, wenn Hostinganbieter, Agentur und Entwickler zusammenarbeiten.</p>
<p>
<h1> Wie finden wir die Bottlenecks?</h1>
</p>
<p>Zunächst erfolgt eine Bestandsaufnahme: Server, Software, Versionsnummern, Konfigurationen, aktuelle Auslastung, Besonderheiten. Für die detaillierte Untersuchung der Performance unterteilen wir das Setup in zwei Kategorien: Komponenten und Seitentypen. Die einzelnen Komponenten etwa eines Shops sind die Shopsoftware (z.B. PHP), die Datenbank (z.B. MySQL) und externe Webservices (z.B. Suchanbieter). Jede dieser Komponenten kann Bottlenecks verursachen und wird deshalb einzeln analysiert und getestet. Im zweiten Schritt unterscheidet man zwischen verschieden Seitentypen, bei einem Shop sind das meist die Startseite, Kategorieseite, Produktseite und die Suche. Jeder dieser Seitentypen hat individuelle Funktionen und Anforderungen &#8211; und damit auch potentiell individuelle Bottlenecks.</p>
<p>
<h1>Seitenladezeit</h1>
</p>
<p>Einer der sichtbarsten Indikatoren für die Performance der Webseite ist die Seitenladezeit. Als Referenzwerte für eine spätere Erfolgsmessung wird die Ladezeit jedes Seitentyps einzeln gemessen:<br />
<img src="http://www.syseleven.de/wp-content/uploads/curl.gif" alt="" title="Seitenladezeit" width="386" height="125" class="aligncenter size-full wp-image-1908" /></p>
<p>
<h1>Bottlenecks in MySQL finden</h1>
</p>
<p>Bei der Analyse von MySQL unterscheiden wir im Wesentlichen zwischen zwei Arten von Last:</p>
<ul>
<li>Den Datenbankabfragen, die ein einzelner Aufruf eines Seitentyps verursacht.</li>
<li>Der Gesamtauslastung aller Datenbankabfragen während des Livebetriebs.</li>
</ul>
<p>Für jeden der ermittelten Seitentypen wird analysiert, welche Datenbankabfragen bei einem einzelnen Seitenaufruf ausgeführt werden. Die „teuersten“ Queries kommen auf die Merkliste für eine genauere Untersuchung. Ich habe schon so Einiges gesehen und bin dennoch immer wieder überrascht wie viele Datenbankabfragen von einem einzigen Seitenaufruf verursacht werden können. Mehrere Hundert sind hier leider keine Seltenheit! Da gibt es oft  &#8211; ich formuliere es mal so &#8211; Verbesserungspotential. ;-)</p>
<p><img src="http://www.syseleven.de/wp-content/uploads/SQL-Profile.png" alt="" title="SQL-Profile" width="434" height="196" class="aligncenter size-full wp-image-1912" /></p>
<p>In diesem Beispiel hat ein einzelner Aufruf der Startseite eines Online Shop 296 Datenbankabfragen verursacht, hier gibt es sicher den einen oder anderen Ansatzpunkt für eine genauere Untersuchung.</p>
<p>Die Gesamtbelastung der Datenbank wird untersucht, indem alle Datenbankabfragen, idealerweise während einer Lastspitze, in einem Logfile protokolliert werden. Aus diesem Logfile wird ein Query-Profil erstellt. Das ist eine nach Rechenzeit sortierte Liste ähnlicher Queries. Dabei ist die Verteilung der verbrauchten Rechenzeit relevant und nicht etwa die Ausführungszeit der einzelnen Queries. Dauert eine Abfrage beispielsweise sehr lange, wird aber nur selten ausgeführt, hat sie wenig Einfluss auf die Gesamtperformance. Uns interessiert also vielmehr, wieviel Anteil an der gesamten Datenbankrechenzeit auf ähnliche Queries entfallen.</p>
<p><img src="http://www.syseleven.de/wp-content/uploads/sql_profile.gif" alt="" title="sql_profile" width="427" height="233" class="aligncenter size-full wp-image-1915" /></p>
<p>Hier sieht man zum Beispiel, dass die obere Query (nur der Anfang ist dargestellt) 32,5% der gesamten MySQL-Rechenzeit ausgemacht hat. Diese Query ist somit unser Kandidat #1 auf dem Prüfstand ist. Ob es zusätzlich auch Queries gab, die 10 Sekunden gedauert haben, im Testzeitraum aber nur dreimal aufgerufen wurden, ist in der Gesamtbetrachtung der Performance unerheblich.</p>
<p>
<h1>Zwischenstand</h1>
</p>
<p>Bevor es an das PHP-Profiling geht, lohnt sich an dieser Stelle eine Zwischenrechnung, die für jeden der anfangs ermittelten Seitentypen einzeln angewendet wird:</p>
<p>Seitenladezeit &#8211; Summe der Zeit aller MySQL-Queries &asymp; Ausführungszeit in PHP</p>
<p>Das Ergebnis entspricht nur sehr grob der PHP-Ausführungszeit, dennoch können wir den Wert an dieser Stelle als Entscheidungsgrundlage benutzen, ob sich jeder weitere Aufwand überhaupt noch lohnt oder ob die Bottlenecks bereits gefunden sind.</p>
<p>
<h1>Bottlenecks in PHP finden</h1>
</p>
<p>Für das Profiling in PHP gelten im Grunde dieselben Regeln wie für MySQL. Jeder Seitentyp wird einzeln untersucht. Auch hier ist besonders die Verteilung interessant. Welche Klasse oder Methode verursacht wie viel Prozent der gesamten Ausführungszeit?</p>
<p><img src="http://www.syseleven.de/wp-content/uploads/php_profile.gif" alt="" title="php_profile" width="425" height="266" class="aligncenter size-full wp-image-1918" /></p>
<p>
<h1>Fazit</h1>
</p>
<p>Die Performance einer Webseite zu steigern ist einfach &#8211; wenn man vorher die tatsächlichen Bottlenecks gefunden hat. Sehr oft begegnen uns Projekte, bei denen alle möglichen Best-Practices angewendet wurden und die Seite dennoch unbefriedigend langsam ist. Kein Wunder, wenn an den echten Bottlenecks vorbei-optimiert wurde. Der Erfolg bleibt aus und der Frust ist groß. Ein detailliertes Performance-Profiling ist zwar sehr komplex und aufwendig, es rentiert sich aber sehr schnell durch echte Ergebnisse.</p>
<p>
<h1>Wann bekommt Ihre Webseite den SysEleven Faktor?</h1>
</p>
<p>SysEleven ist spezialisiert auf High-Performance-Webseiten und wir sind stolz auf jedes einzelne bei uns betreute Projekt. Wir freuen uns persönlich über jede neue Herausforderung. Derzeit liegt der Rekord bei 1440 MySQL Queries für einen einzigen Seitenaufruf.</p>
<p>Wer bietet mehr? ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syseleven.de/blog/1906/performance-profliling-bei-syseleven/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP RAM-Verbrauch in Logfile protokollieren</title>
		<link>http://www.syseleven.de/blog/1820/php-ram-verbrauch-in-logfile-protokollieren/</link>
		<comments>http://www.syseleven.de/blog/1820/php-ram-verbrauch-in-logfile-protokollieren/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 12:18:46 +0000</pubDate>
		<dc:creator>Thomas Lohner</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Logfile]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[RAM]]></category>
		<category><![CDATA[Tipps]]></category>

		<guid isPermaLink="false">http://www.syseleven.de/?p=1820</guid>
		<description><![CDATA[So können Sie den RAM Verbrauch einer PHP Applikation im Apache Logfile protokollieren.]]></description>
			<content:encoded><![CDATA[<p>
Beim Debugging eines aktuellen Problems, fiel uns auf, dass PHP Prozesse auf dem betroffenen Drupal Application Server ungewöhnlich viel Arbeitsspeicher verschlungen haben. Üblicherweise rechnen wir mit zwischen 20 und 60  MB pro Apache (PHP) Prozess. Hier fanden sich Ausreißer mit teilweise über 200 MB.
</p>
<p><br/><br />
<img src="http://www.syseleven.de/wp-content/uploads/2011/07/Prozessliste.gif" alt="" title="Prozessliste" width="430" height="144" class="aligncenter size-full wp-image-1821" /><br />
<br/></p>
<p><h1>Zuordnung zu URLs</h1>
<p>In der Prozessliste fehlt uns jedoch eine entscheidende Information: Welche URL hat diesen Prozess ausgelöst, der außergewöhnlich viel Arbeitsspeicher verbraucht? Was wir suchen ist eine Zuordnung zwischen dem Prozess und der im Browser aufgerufenen URL. Da alle Zugriffe auf die Webseite im Apache Logfile protokoliert werden, liegt Nahe an dieser Stelle anzusetzen.
</p>
<p>
Unser Ziel ist also, innerhalb der Applikation den maximal verbrauchten Arbeitsspeicher zu ermitteln und den Wert an Apache zu übergeben, damit dieser im Logfile protokoliert werden kann. Wir nutzen hierfür die beiden PHP Funktionen memory_get_peak_usage() und apache_note():<br />
<code><br />
# get the maximum ram<br />
$debug_ram = memory_get_peak_usage();</p>
<p># make it visible to apache<br />
apache_note("x-php-ram", $debug_ram);<br />
</code>
</p>
<p><h1>Implementierung in die Applikation</h1>
<p>Wir wollen natürlich nicht in der Applikation suchen, an wie vielen Stellen wir den Code einfügen müssen, damit wir bei jedem Aufruf den RAM-Verbrauch messen können. Für unsere Debugzwecke machen wir uns eine globale Funktion zu nutze: In der <strong>php.ini</strong> können wir definieren, dass am Ende von jedem PHP Aufruf zusätzlicher Code ausgeführt wird:
</p>
<p><code><br />
; Automatically add files<br />
;auto_prepend_file =<br />
auto_append_file = /var/www/x-php-ram.php<br />
</code></p>
<p><h1>Implementierung in Apache</h1>
<p>Um die Werte auch wirklich im Logfile zu sehen, verändern wir das Logfileformat in Apache:</p>
<p><code><br />
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" PHP-RAM: %{x-php-ram}n" combined_memory</p>
<p>CustomLog /var/log/apache2/access.log combined_memory<br />
</code>
</p>
<p><h1>Ergebnis</h1>
<p>Jetzt sehen wir wie viel Arbeitsspeicher jeder einzelne Aufruf einer Webseite verbraucht hat:
</p>
<p><code><br />
/ PHP-RAM: 91106128<br />
/fotos/deutschland-besiegt-kanada PHP-RAM: 110486240<br />
/page/hitfinder PHP-RAM: 81736024<br />
/fotos/wetten-dass-abschied PHP-RAM: 96412776<br />
/shows/schreckliche-urlaubsmode PHP-RAM: 98604800<br />
/musik PHP-RAM: 95526032<br />
</code></p>
<p>
In diesem konkreten Fall hat uns diese Debug-Information leider nicht weitergeholfen. Es gab keine Ausreißer, im Grunde haben alle Aufrufe ungewöhnlich viel Arbeitsspeicher verbraucht. In dieser Drupal-Installation sind sehr viele Module installiert, so dass tatsächlich viel RAM verbraucht wird. Durch den Einsatz von <a href="http://pecl.php.net/package/APC">APC</a> konnten wir letztendlich den RAM-Verbrauch auf die Hälfte reduzieren und das Problem entschärfen. Dazu aber mehr in einem anderen Blogpost&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syseleven.de/blog/1820/php-ram-verbrauch-in-logfile-protokollieren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>APC: Turbo für PHP Webseiten</title>
		<link>http://www.syseleven.de/blog/1009/apc-turbo-fur-php-webseiten/</link>
		<comments>http://www.syseleven.de/blog/1009/apc-turbo-fur-php-webseiten/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 09:25:46 +0000</pubDate>
		<dc:creator>Thomas Lohner</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[APC]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.syseleven.de/?p=1009</guid>
		<description><![CDATA[Die Geschwindigkeit einer PHP basierten Webseite lässt mich mit einfachen Mitteln verbessern. Wordpress zum Beispiel wird mit APC viermal schneller.]]></description>
			<content:encoded><![CDATA[<p>Im Gegensatz zu anderen Programmiersprachen werden PHP-Skripte während des Aufrufs kompiliert, d.h. in eine ausführbare Form übersetzt und ausgeführt. Dieser Prozess wird bei jedem einzelnen Aufruf der Datei wiederholt. Das ist wenig effizient und lässt sich mit verschiedenen Mitteln leicht ändern.</p>
<p><a href="http://de.php.net/manual/de/book.apc.php">APC</a> ist ein so genannter &#8220;Opcode Cache&#8221;. Die Aufgabe von APC ist es, sich den aufwendigen Kompiliervorgang für spätere Zugriffe zu merken, damit dieser nur einmal ausgeführt werden muss. Bei jedem weiteren Aufruf der Datei liegt diese bereits vorkompiliert im Arbeitsspeicher.</p>
<h2>Wie viel schneller wird meine Webseite?</h2>
<p>Als Beispiel habe ich die Performance <del>einer</del> unserer WordPress-Installationen gemessen. Mit dem Tool Apache Bench (alternativ http_load oder jmeter) kann man ermitteln wie oft eine Webseite in einem festgelegten Zeitraum aufgerufen werden kann. Daraus ergibt sich die Geschwindigkeit der Webseite in der Einheit &#8220;Aufrufe pro Sekunde&#8221; (Requests per second). Je höher diese Zahl, desto schneller ist die Webseite. Oder anders herum, desto mehr Anfragen können je Zeiteinheit bearbeitet werden.</p>
<p><br/><b>Test 1: WordPress mit standard PHP</b><br />
<div class="special-outer"><div class="special-inner"><code>ab -t 60 -c 20 http://SysEleven.de/</p>
<p>Time taken for tests:   60 seconds<br />
Complete requests:      341<br />
Requests per second:    5.66 [#/sec]<br />
</code><br />
</div></div></p>
<p><br/><b>Test 2: WordPress mit aktiviertem APC</b><br />
<div class="special-outer"><div class="special-inner"><code>ab -t 60 -c 20 http://SysEleven.de/</p>
<p>Time taken for tests:   60 seconds<br />
Complete requests:      1294<br />
Requests per second:    21.57 [#/sec]<br />
</code><br />
</div></div></p>
<h2>Ein Fazit</h2>
<p>WordPress ist mit APC knapp <b>viermal schneller</b> als ohne. Aber: Wie viel schneller eine Webseite tatsächlich wird, hängt von der verwendeten Software ab. <b>Wichtig:</b> Nicht jede Software ist kompatibel zu APC, aber ein Versuch lohnt sich allemal. </p>
<p>Die Auslastung des Caches und die Erfolgsquote (Hits/Misses) ist, stellt APC in Diagrammen dar:</p>
<p><img src="http://www.syseleven.de/wp-content/uploads/2010/03/apc_status.gif" alt="" title="apc_status" width="425" height="224" class="aligncenter size-full wp-image-1031" /></p>
<h2>Alternativen</h2>
<p>Neben APC gibt es noch <a href="http://eaccelerator.net/">eAccelerator</a> und <a href="http://xcache.lighttpd.net/">XCache</a>. Performancemäßig nehmen die drei sich wenig, welche Software man einsetzt ist eher Geschmacksache bzw. eine Frage der Kompatibilität &#8211; was mit dem einen Cache nicht kompatibel ist, wird mit einem anderen vielleicht doch funktionieren. Das hartnäckige Gerücht, <a href="http://www.zend.com/de/products/guard/zend-optimizer">Zend Optmizer</a> gehöre auch dazu, ist übrigens falsch. Zend Optimizer &#8220;optimiert&#8221; zwar den Quellcode, ist aber kein Cache und merkt sich diese Verbesserungen nicht. Im Gegenteil: Die gleiche Arbeit wird bei jedem Aufruf erneut ausgeführt. Aus Sicht der Performance ist das wenig förderlich, weil es durch die ständige Mehrarbeit die Ausführung von PHP sogar noch verlangsamen kann.</p>
<h1>Links</h1>
<p><a href="http://de.php.net/manual/de/book.apc.php">http://de.php.net/manual/de/book.apc.php</a><br />
<a href="http://www.zend.com/de/community/php">http://www.zend.com/de/community/php</a><br />
<a href="http://eaccelerator.net/">http://eaccelerator.net/</a><br />
<a href="http://xcache.lighttpd.net/">http://xcache.lighttpd.net/</a><br />
<a href="http://httpd.apache.org/docs/2.2/programs/ab.html">http://httpd.apache.org/docs/2.2/programs/ab.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.syseleven.de/blog/1009/apc-turbo-fur-php-webseiten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

