Test von PHP-Operationen

Ich komme nach ein paar Experimenten zu teilweise recht interessanten Einsichten, darunter teilweise zu Widersprüchen zu im Internet kursierenden Empfehlungen.
Meine Empfehlung: Die Empfehlungen mit Vorsicht genießen und selbst testen.

Wie eine Art Hammer kamen Erkenntnisse der Art, daß mitunter die Reihenfolge von Operationen, die für sich ganz harmlos sind, den Gesamtaufwand drastisch nach oben oder auch nach unten treiben kann.
Am drastischsten war dabei eine Erfahrung in einem konkreten praktischen Anwendungsfall, wo "!isset()" und das davon abhängige Setzen desselben Elements kombiniert wurden, was in jenem konkreten Fall (im Oblivion-Alchemierechner) einen Zeitanstieg auf das 200-fache (!) mit sich brachte...
Seltsamerweise tritt dieses Verhalten bisher nur genau in dieser Anwendung in genau einem bestimmten Kontext auf. Dabei ist das äußere funktionelle Verhalten korrekt (es liegt also kein Programmierfehler vor).
Weniger markante, aber dafür synthetische und damit nachvollziehbare Beispiele sind die beiden Zeilen mit "foreach ($testarray3..." weiter unten: Durch bloßes Ausführen eines zwischenzeitlichen Referenz-Zugriffs sinkt der Aufwand für die Iteration mit Kopie der Daten auf den mit Referenz der Daten (um den Faktor 10!) - obwohl sonst absolut nichts verändert wird und auch die Ergebnisse gleich bleiben! Ich schätze mal, daß bei dem mystischen Verhalten im Oblivion-Rechner was ähnliches wirkt, nur mit umgedrehtem Vorzeichen...

Recht stark überrascht hat mich der Umstand, daß "array_key_exists" dermaßen langsamer implementiert ist als "isset", alldieweil ein "isset" mindestens die Funktionalität von "array_key_exists" beinhalten und darüberhinaus aber auch noch auf "Null" testen muß, während "array_key_exists" letzteres weglassen kann.

Ebenfalls recht überraschend kam die Erkenntnis, daß PHP so um 2'000 Elementaroperationen benötigt, um sich über den Inhalt eines einzelnen ASCII-Zeichens klar zu werden! Was machen die da für schreckliche Zauberei?!

Nicht nachvollziehen kann ich die Empfehlung, die doppelte Anführungszeichen für Strings mit darin eingeschlossenen Variablennamen anstelle von einfachen Anführungszeichen für konstante Strings mit davon getrennt angeführten Variablen zu verwenden.

Nicht nachvollziehen kann ich die Empfehlung, auf den Referenz-Operator zu verzichten - auch und gerade nicht, wenn Arrays iteriert werden sollen.

Nur bedingt nahvollziehen kann ich die Empfehlung, Strings statt Arrays zu verwenden: Der indizierte Zugriff in einem String kostet rund die doppelte Zeit. Allerdings geht der Aufbau eines Strings mitunter wesentlich schneller.

Letztlich muß man wohl akzeptieren, daß die PHP-Interpretation immer mindestens um 200 Elementaroperationen selbst für einfachste Statements schluckt. PHP verbietet sich von daher offenbar für jede komplexere Anwendung.

Vorbereitung für den Test von Array-Zugriffen:
$n = 100000; $testarray = array(); for($i = 0; $i < $n; $i++) $testarray['_'.$i] = $i; $testkeys = array_keys($testarray); $m = 100; $testarray2 = array(); for($i = 0; $i < $m; $i++) $testarray2[$i] = $i; $testarray3 = array(); for($i = 0; $i < $n; $i++) $testarray3[$i] = &$testarray2; $z = '_'.($n/2); $zv = $testarray[$z]; $byteset = str_repeat('0',$n); $byteset[$zv] = '1'; function func($key, &$val) {}

Zeitbedarf:
MarkeZeitpunkt
keine Operation...0.029098033905
$c++...0.0406708717346
if (array_key_exists($z, $testarray)) $c++;...0.218841075897
if (array_key_exists($zv, $testkeys)) $c++;...0.276590108871
if (isset($testarray[$z])) $c++;...0.0828719139099
if (isset($testkeys[$zv])) $c++;...0.0678148269653
if ($byteset[$zv]) $c++;...0.102327108383
$s .= 'Text '.$i;...0.193111896515
$s .= "Text $i";...0.216892957687
$testarray1[$i] = $i;...0.121790885925
$testarray1[$testkeys[$i]] = $i;...0.170150995255
$testarray1['_'.$i] = $i;...0.283246040344
foreach ($testarray3 as $name => $val) func($name, $val);...2.7006380558
foreach ($testarray3 as $name => &$val) func($name, $val);...0.166589975357
foreach ($testarray3 as $name => $val) func($name, $val); (2. Aufruf)...0.165761947632