Hallo MB,
wie man solche Benchmarks schreibt, hat Regina Schaukrug erläutert. Ich mache sowas zweistufig:
// 1. Laufzeit der leeren Schleife bestimmen
$start = microtime(false);
for ($i=0; $i<10000000; $i++)
{
}
$emptyLoop = microtime(false) - $start;
$start = microtime(false);
for ($i=0; $i<10000000; $i++)
{
// zu messender code
}
$laufzeit = microtime(false) - $start - $emptyloop;
Das geht natürlich schief, wenn man einen Compiler hat, der eine leere Schleife erkennt und wegoptimiert 😀
Was ist eine virtuelle Methode. Ich mache ein Beispiel:
class A
{
public function Hugo() {
return "Hugo in ".get_class($this)." ruft Otto: " . $this->Otto();
}
public function Otto() {
return "Schnauze!";
}
}
class B extends A
{
public function Willi() {
return "Willi in ".get_class($this)." ruft Otto: " . $this->Otto();
}
public function Otto() {
return "Hallo, mein Lieber!";
}
}
$a = new A();
$b = new B();
echo $a->Hugo() . "<br>\n";
echo $b->Hugo() . "<br>\n";
echo $b->Willi() . "<br>\n";
Ergebnis ist:
Hugo in A ruft Otto: Schnauze!<br>
Hugo in B ruft Otto: Hallo, mein Lieber!<br>
Willi in B ruft Otto: Hallo, mein Lieber!<br>
Warum ist das bemerkenswert? Hugo ist eine Methode der Klasse A. Ein sturer Compiler (C, C++, C#) würde sagen: Hugo ruft Otto, Otto ist eine Methode von A, also ruft Hugo IMMER A::Otto auf. Das ist ein statisch gebundener Methodenaufruf. Die zweite Ausgabezeile würde dann lauten: Hugo in B ruft Otto: Schnauze!
.
Ist eine Methode virtuell, dann wird erst zur Laufzeit geprüft, welche Klasse das Objekt nun wirklich hat. $a->Hugo() ruft Hugo auf einem Objekt der Klasse A auf, darum wird A::Otto aufgerufen. $b->Hugo() ruft Hugo auf einem Objekt der Klasse B auf, darum wird B::Otto gerufen. Das ist ein virtuell gebundener Methodenaufruf. Um sowas machen zu können, darf der Compiler den Aufruf $this->Otto() in Hugo nicht in Inline-Code umwandeln (er würde dann einfach den Code von Otto in Hugo hineinkopieren), sondern muss in dem Moment, wo aufgerufen wird, gucken, welcher Otto es denn nun wirklich ist. Das ist langsamer.
In C, C++ und C# kann ich dem Compiler sagen, ob ich eine virtuelle oder statische Bindung haben möchte. Java, PHP und JavaScript kann ich das nicht sagen, die binden immer virtuell. Da kann ich mittels "final" Schlüsselwort höchstens sagen, dass eine Methode in abgeleiteten Klassen nicht neu definiert werden darf.
Rolf
Dosen sind silbern