PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Echo, Print und die Parameter

with 5 comments

Wenn man sehr viel mit Strings und Stringausgaben arbeitet, und dabei maximale Performance braucht, gibt es einige Tricks, die dabei helfen, die letzten Prozente rauszuholen.
Bedenkt also: Diese leichten Performance-Unterschiede bringen nur bei sehr großen Scripten etwas. Bei einer kleinen Webseite oder ähnlichem ist der Unterschied zu vernachlässigen, da zählt mehr die persönliche Vorliebe und Lesbarkeit.

Zuerst einmal: in PHP gibt es zur Ausgabe von Daten (das können ja auch Zahlen sein, nicht nur Strings) zwei einfache Funktionen: echo und print.

Diese beiden Funktionen sind etwas besonderes: Es sind Sprachkonstrukte, und keine Funktionen. Man kann sie also auch ohne Klammern benutzen, beispielsweise so:

echo 'Dies ist ein Text';
echo('Dies ist ein Text');

Aber das kann auch zu Problemen führen, beispielsweise in diesem Quelltext:

(1 === $i) ? echo 'gleich' : echo 'ungleich';

Bei dieser trinären Bedingung funktioniert echo nicht, da es keinen Rückgabewert hat. print funktioniert.

echo ist print immer vorzuziehen. Warum? echo ist leicht performanter (aber nur im tausendstel Bereich, siehe unten). Außerdem bietet es die Möglichkeit, mehrere Parameter zu übergeben. Auch das ist minimal schneller als einen String mit Punkten zu verbinden.

In den folgenden Scripten nutze ich jeweils den Output Buffer von PHP, um nur im Speicher zu arbeiten. Wenn man die ob_-Funktionen weglassen würde, würde ein sehr großer Teil der CPU-Belastung (und damit des Tests) auf die eigentliche Ausgabe in der Console (bzw. dem Browser) draufgehen und die Ergebnisse verfälschen.

<?php
$string1 = "_string1_";
$string2 = "_string2_";

$timeStartComma = microtime(true);
for ($i=0; $i<1000000; $i++) {
	ob_start();
	echo $string1, 'sometexthere', $string2, "\r\n";
	ob_get_clean();
}
$timeEndComma = microtime(true);

$timeStartDot = microtime(true);
for ($i=0; $i<1000000; $i++) {
	ob_start();
	echo $string1 . 'sometexthere' . $string2 . "\r\n";
	ob_get_clean();
}
$timeEndDot = microtime(true);

$timeStartPrint = microtime(true);
for ($i=0; $i<1000000; $i++) {
	ob_start();
	print $string1 . 'sometexthere' . $string2 . "\r\n";
	ob_get_clean();
}
$timeEndPrint = microtime(true);

echo "Comma needed " . ($timeEndComma-$timeStartComma) . " seconds\n";
echo "Dot needed " . ($timeEndDot-$timeStartDot) . " seconds\n";
echo "Print needed " . ($timeEndPrint-$timeStartPrint) . " seconds\n";
?>

echo1

<?php
$string1 = "_string1_";
$string2 = '_string2_';

$timeStartDouble = microtime(true);
for ($i=0; $i<1000000; $i++) {
	ob_start();
	echo "_string1__string1__string1__string1_";
	ob_get_clean();
}
$timeEndDouble = microtime(true);

$timeStartSingle = microtime(true);
for ($i=0; $i<1000000; $i++) {
	ob_start();
	echo '_string2__string2__string2__string2_';
	ob_get_clean();
}
$timeEndSingle = microtime(true);

echo "Double needed " . ($timeEndDouble-$timeStartDouble) . " seconds\n";
echo "Single needed " . ($timeEndSingle-$timeStartSingle) . " seconds\n";
?>

echo4

Es ist übrigens minimal schneller, wenn man keine Klammern nutzt.

<?php
$timeStartWithout = microtime(true);
for ($i=0; $i<1000000; $i++) {
	ob_start();
	echo '_string1_';
	ob_get_clean();
}
$timeEndWithout = microtime(true);

$timeStartWith = microtime(true);
for ($i=0; $i<1000000; $i++) {
	ob_start();
	echo('_string1_');
	ob_get_clean();
}
$timeEndWith = microtime(true);

echo "Without brackets needed " . ($timeEndWithout-$timeStartWithout) . " seconds\n";
echo "With brackets needed " . ($timeEndWith-$timeStartWith) . " seconds\n";
?>

echo5

Man beachte wie gesagt, dass wir hier von 1 Million Schleifendurchläufen reden. In 99,9% aller Fälle ist der Unterschied zu vernachlässigen. Wer also hoch performante Riesenscripte bauen möchte, sollte sich das ganze genau anschauen (oder solche Dinge gleich in C schreiben, aber ich will ja keine Werbung für andere Programmiersprachen machen 😉 )

Written by Michael Kliewe

September 1st, 2009 at 9:02 am

Posted in PHP

Tagged with , ,

5 Responses to 'Echo, Print und die Parameter'

Subscribe to comments with RSS or TrackBack to 'Echo, Print und die Parameter'.

  1. Premature optimization is the root of all evil. Da rüttelt auch der tausendste Beitrag mit Performancevergleichen von echo, print und co. nicht viel…

    Martin Kuckert

    1 Sep 09 at 10:01

  2. Wer redet von „Premature optimization“? Irgendwo gehört, und einfach mal wiedergegeben? 😉

    Ich habe deutlich 2 mal betont, dass es nur für sehr spezielle extrem performante Scripte nötig ist, sich über solche Unterschiede klar zu werden. Außerdem beeinflusst der Austausch von print durch echo, bzw. die Nutzung von ‚ statt “ keinesfalls das Design.

    „Premature optimization“ is a phrase used to describe a situation where a programmer lets performance considerations affect the design of a piece of code. This can result in a design that is not as clean as it could have been or code that is incorrect, because the code is complicated by the optimization and the programmer is distracted by optimizing.

    An alternative approach is to design first, code from the design and then profile/benchmark the resulting code to see which parts should be optimized. A simple and elegant design is often easier to optimize at this stage, and profiling may reveal unexpected performance problems that would not have been addressed by premature optimization.

    Michael Kliewe

    1 Sep 09 at 10:17

  3. Das funktioniert aber:

    echo (1 === $i) ? ‚gleich‘ : ‚ungleich‘;

    Jacky

    1 Sep 09 at 17:39

  4. Das stimmt, weil es jetzt in beiden Fällen einen Rückgabewert gibt (nämlich den String).

    Wie oben geschrieben geht auch
    (1 === $i) ? print ‚gleich‘ : print ‚ungleich‘;

    Also einfach nur echo gegen print getauscht. print hat einen Rückgabewert (nämlich 1), und dann geht es.

    Wohin gegen das hier auch funktioniert, obwohl die Funktionen keinen Rückgabewert haben, Etwas verwirrend jedenfalls:

    (1 === $i) ? tueWas() : tueNichts();

    function tueWas() {
    echo „ich tue was“;
    }
    function tueNichts() {
    }

    Michael Kliewe

    1 Sep 09 at 17:49

  5. Wirklich schöne, da mal paar Daten zu bekommen 😀
    Ich weiß ja, warum ich echo so mag – auch wenn es eher nur kleine Scripte sind 😉

    alopix

    4 Sep 09 at 10:01

Leave a Reply

You can add images to your comment by clicking here.