BLOG

Kann man Drupal mit eigenen PHP Extensions beschleunigen? Die Zweite

Hallo,

ich möchte mich noch einmal bedanken für das Feedback des ersten Blogposts über dieses Thema.
Wie ich das Feedback verstanden habe, würden die meisten wohl nicht den Weg über eine Extension gehen.

Ein Grund hierfür ist wohl sicherlich der Aufwand, der dahinter steckt und ein anderer, dass wohl keiner so genau weiß, wie viel Speed es wirklich bringen würde. Um einmal eine Vorstellung davon zu geben, was man mit einer Extension erreichen kann, habe ich mich mal drangesetzt, ein kurzes Script zu schreiben, das Fakultäten berechnet.

<?php
function fac($val) {
  if (
$val <= 1) return 1;
    return
$val * fac($val - 1);
}
set_time_limit(0);
$start = gettimeofday();
$var = 10000;
fac($var);
$end = gettimeofday();
$laufzeit = $end['usec']-$start['usec'];
echo
"Laufzeit: ".$laufzeit." Millisekunden!";
?>

Das Script enthält eine kleine Funktion, die sich immer wieder selbst aufruft und die dabei übergebene Variable um eins zurücksetzt. Bevor ich das Script starte, lasse ich mir die aktuelle Zeit in Millisekunden geben und frage danach noch einmal die aktuelle Zeit ab, ziehe dann die End- von der Startzeit ab und habe so die Millisekunden ermittelt, die das Script benötigt, um fertig zu sein.

Wie ihr seht, kein großes Hexenwerk und nicht viel zu tun für den Interpreter ‐ sollte man meinen. Das Script benötigt übrigens im Schnitt 20000 Millisekunden.

Nun habe ich mich ans Werk gemacht und das ganze in einer simplen PHP Extension umgesetzt und das Script nun nochmal aufgerufen, nur anstatt der PHP-Funktion die Extension-Funktion aufgerufen.

<?php
set_time_limit
(0);
$start = gettimeofday();
$var = 10000;
factor($var);
$end = gettimeofday();
$laufzeit = $end['usec']-$start['usec'];
echo
"Laufzeit: ".$laufzeit." Millisekunden!";
?>

Was soll ich sagen, dieses Script benötigt im Schnitt 200 Milisekunden und es macht genau das gleiche. Zum Vergleich hier der C-Quellcode der Funktion.

double do_factorial(double val) {
    if (val <= 1) return 1;
    return val * do_factorial(val - 1);
}

Also ich denke, das zeigt eindrucksvoll, was eine Extension so bewirken kann. Wer möchte, dem kann ich die fertige .so-Datei gerne schicken und auch das Script, um es selber zu prüfen. Und ich bedanke mich im Voraus für die Kommentare.

MfG das_ricardo

Kommentare

Datenstruktur

Da irrst du dich. Für das Problem "Schlüssel-Wert-Zuordnung" (hier konkret: Wert zu einem eindeutigen Variablennamen) gibt es keine schnellere Lösung als eine Hash Table (aka assoziatives Array). Das Durchsuchen einer Linked List ist um Größenordnungen langsamer.

Mathematisch ausgedrückt: Lesen eines Hashtable-Eintrags ist O(1), eines Listeneintrags jedoch O(n) bei n Listenelementen.

Danke

Hallo,
ich habe mindestens genauso viel Spaß wie du dabei! Also ja du hast recht es geht darum das ein Array durchsucht wird. Ich glaube aber das hier schon der erste Performance schub stattfinden kann da ich das ganze als einfach verkettete Liste implementieren würde. Das braucht sicherlich weniger Speicher und sollte schneller zu durchlaufen sein in C.

Das sind natürlich Vermutungen die ich hier anstelle und werden sich nur dann belegen lassen wenn ich es schaffen sollte irgendwann die Funktion zu implementieren. 

Danke für die Anregung!

Mir macht die Diskussion viel Spaß -- Danke für diesen interessanten Gedankenaustausch, Ricardo!

Ich hab mir drupal_static gerade angeschaut (bin ja kein Drupal-Dev). Innerhalb der paar Fallunterscheidungen finden in dieser Funktion lediglich Array-Abfragen und -Zuweisungen statt.

Zur Optimierung müsste hier also ein Hash-Algorithmus für assoziative Arrays implementiert werden, der schneller ist als der von PHP. Selbst, wenn das gelingen sollte, wäre das Ergebnis dann wohl sinnvoller ein Patch für PHP statt einer Extension für Drupal.

Herzliche Grüße,
Jochen

Hmmmm

Hallo,

@McGo, leider habe ich schon alle Links die ich besitze zu diesem Thema im ersten Blogpost veröffentlicht so dass ich leider keine weiteren Links für dich habe. Zum Kompilieren, das wird im dritten Link erklärt. Ich habe das unter einem Ubuntu System gebaut und entsprechende C Compiler und PHP Tools Installiert, als IDE nutze ich Eclipse. Die fertige Extension ist dann eine .so-Datei und wird ganz normal über die php.ini eingebunden. Wie das funktioniert findest du recht schnell in Google :)

@Jochen
Ja, du hast sicherlich recht mit dem Part, dass die Extension alleine nichts bringt und sie in Drupal eingepflegt werden muss. Allerdings rede ich ja hier nur von einigen Core Funktionen, die ich ersetzen würde, und die ändern sich ja nicht so häufig. Gehen wir mal von der drupal_static Mehtode aus. Man muss ja lediglich den Inhalt der PHP Funktion durch den Aufruf der Extension-Funktion ersetzen und das lässt sich wohl mit nem Patch leicht bewerkstelligen.

Zweitens, ja es ist eine sehr CPU-lastige Funktion die ich da mal genommen habe, und ja auch eine Extension müsste bei IO warten. Ich habe im ersten Blog ja schon erwähnt, dass man die Funktionen wohl überlegt aussuchen sollte, die man umsetzen will. Hier möchte ich wieder drupal_static nennen, in der keine IO Sachen stattfinden und ich glaube, dass sie auch sehr CPU-lastig ist. Wie ich finde, perfekte Voraussetzungen für eine Portierung.

Ich möchte nochmal für das Feedback danken.

Keine Überraschung

Hi Ricardo,

dass ein in Maschinencode compiliertes Binary um Größenordnungen schneller ist als ein Interpreter-Script ist doch nicht überraschend, oder? Genau deshalb wird zeitkritische Software (darunter auch ebendie Script-interpreter) ja in C implementiert.

Nach meinem Verständnis ist nicht der Aufwand, eine Extension zu erstellen, so abschreckend, sondern der Aufwand, sie dann auf Dauer in die komplexe Software Drupal zu integrieren.

Außerdem ist dein Anwendungsbeispiel -- eine mathematische Aufgabe, bei der ausschließlich die CPU eine Rolle spielt -- doch sehr weit vom Anwendungsfall "Webapplikation" entfernt. Dort spielen viele externe Einflüsse eine Rolle, zum Beispiel die Netzwerkanbindung. Im schlechtesten Fall (meist dann, wenn es um I/O geht) kann eine C-Lösung dann nur eines bedeutend schneller als die PHP-Variante: Warten.

Ich bin überzeugt, dass alle wesentlichen Komponenten, nämlich der LAMP-Stack, bereits performant (in C) implementiert sind. Wo das dann noch nicht reicht, ist der pragmatische Ansatz, sie clever zu umgehen (Varnish statt Apache, Memcache oder MongoDB statt MySQL) meines Erachtens sinnvoller als der, sie zu erweitern.

Das mag aber auch schlicht daran liegen, dass ich mehr Sysadmin als Entwickler bin. :-)

Herzliche Grüße,
Jochen

Interessante Werte

Das ist mal ein interessanter Ansatz. Danke für die kurze Einführung. Hast du weitere Infos und Links zu dem Thema, die du bei deiner Recherche gesammelt hast? Mich würde hier im Besonderen der Kompilierungsvorgang / Installation der Extension interessieren, sowie ein Ansatz, welche Art von PHP Scripten sich besonders für eine Extension eignen (Rechenintensiv / IO / ??).

Kommentar hinzufügen

Der Inhalt dieses Feldes wird nicht öffentlich zugänglich angezeigt.
Mit dem Absenden dieses Formulars, akzeptieren Sie die Datenschutzrichtlinie von Mollom.