Quitschibo: "Grundsatzfrage?", use oder require?

Hallo Zusammen,

ich bin momentan dabei ein recht umfangreiches Community Managementsystem zu programmieren das modular aufgebaut ist, d.h. jeder Subdienst ist in ein eigenes Modul ausgelagert von dem aus wiederrum weitere Module (z.b. Templateausgabemodul) aus integriert sind. Angespochen wird das ganze über ein .pl Script das in etwa so aufgerufen wird: verteiler.pl?service=dienst1&action=auftrag&weiterevariable=weitererwert etc... so, soweit so gut, funktioniert bestens.
Nun habe ich aber eine Frage, momentan lade ich die Module erst wenn klar ist welches der Module benötigt wird, also wenn service=gästebuch, dann wird nach einer if-abfrage mit require das UM::guestbook; modul geladen. Ist es nun besser alle Module gleich von Anfang an zu laden (also über use) oder wirklich erst dann die Module wenn sie auch benötigt werden. Was ist besser für den Server, was verbraucht mehr Leistung (bei use wird das ganze ja noch vor der Laufzeit geprüft, daher müsste das ja theoretisch auch schneller sein, oder?). Ahja, noch eine weitere Frage... momentan ist es so das z.b. folgendes auftritt, der verteiler läd das Gästebuchmodul, dort wird dann per use gleich das Templatemodul geladen da das mit ziemlicher Sicherheit gebraucht wird, auch das Fehlermodul wird geladen (wenn ein Fehler auftritt wird der anhand eines Codes in eine für Menschen sinnvolle ausgabe gewandelt). So, nun ist es aber so das das Templatemodul auch das Fehlermodul laden muss da es ja dort auch noch zu einem Fehler kommen kann (z.b. Template nicht vorhanden etc...)... wie ist das nun, muss man hier das Fehlermodul nochmal explizit laden oder ist es noch von dem Gästebuchmodul geladen? Das ist eine interesante Sache da ich sonst ja alle Module gleich von Anfang an im Verteilerscript laden lassen könnte, so gäbe es keine Probleme mehr wenn neue Module integriert bzw. später für Kunden herausgenommen werden. Ich hoffe das jemand auf diese durchaus komplexeren Fragen eine Antwort weis.

Schonmal Danke, Quitschi

  1. Hallo Quitschi,

    Nun habe ich aber eine Frage, momentan lade ich die Module erst wenn klar ist welches der Module benötigt wird, also wenn service=gästebuch, dann wird nach einer if-abfrage mit require das UM::guestbook; modul geladen. Ist es nun besser alle Module gleich von Anfang an zu laden (also über use) oder wirklich erst dann die Module wenn sie auch benötigt werden. Was ist besser für den Server, was verbraucht mehr Leistung (bei use wird das ganze ja noch vor der Laufzeit geprüft, daher müsste das ja theoretisch auch schneller sein, oder?).

    Auf jeden Fall laesst sich schon mal sagen, das use moderner ist und von den Perlern auf jeden Fall empfohlen wird. Vor allem, weil es erlaubt, genau das einzubinden, was man braucht - also bestimmte Variablen oder Subroutinen des eingebundenen Moduls und nicht gleich das ganze Modul (vorausgesetzt, das Modul bietet entsprechende Exporte an). Das reduziert Namensraumkonflikte, und der insgesamt kompilierte Code ist effizient und enthaelt keinen ueberfluessigen Muell.

    Was schneller ist, kann ich auch nicht sagen. Bei use wird halt erst alles kompiliert, bevor irgendwas ausgefuehrt wird. Bei vielen Moduleinbindungen (wie etwa hier im Forum - siehe dazu auch </?m=30271&t=5381>) kann es bis zur Ausfuehrung schon mal zu merklichen Verzoegerungen kommen. Das geht bei require natuerlich schneller, weil da gleich mit dem Ausfuehren begonnen wird, und eingebundene Module erst dann dazukompiliert werden, wenn sie ausgefuehrt werden. Dem reinen Menschenverstand nach ergeben sich die Verzoegerungen bei require stattdessen waehrend der Ausfuehrung und summieren sich dabei. Was Dateizugriffe betrifft, ist wohl in beiden Faellen gleich viel erforderlich.

    Ahja, noch eine weitere Frage... momentan ist es so das z.b. folgendes auftritt, der verteiler läd das Gästebuchmodul, dort wird dann per use gleich das Templatemodul geladen da das mit ziemlicher Sicherheit gebraucht wird, auch das Fehlermodul wird geladen (wenn ein Fehler auftritt wird der anhand eines Codes in eine für Menschen sinnvolle ausgabe gewandelt). So, nun ist es aber so das das Templatemodul auch das Fehlermodul laden muss da es ja dort auch noch zu einem Fehler kommen kann (z.b. Template nicht vorhanden etc...)... wie ist das nun, muss man hier das Fehlermodul nochmal explizit laden oder ist es noch von dem Gästebuchmodul geladen?

    Als Programmierer musst du in jedem Modul, in dem du Code eines anderen Moduls verwenden willst, dieses andere Modul oder geeignete Teile davon einbinden. "Doppelteinbindungen" von Modulen in mehreren verwendeten Modulen werden von Perl automatisch erkannt und so behandelt, dass beim Kompilieren optimaler Code entsteht. Deshalb braucht man sich in Perl ja auch nicht mit Praeprozessoranweisungen wie #ifndef und #define herumzuschlagen. Da Perl das automatisch optimiert, gibt es da also auch keine Hintertuerchen, ueber die man selber irgendwas optimieren koennte.

    Ich bin allerdings nicht der Oberhaeuptling in diesen Sachen - und lasse mich gerne belehren, wenn ich Unsinn gelabert hab ;-)

    viele Gruesse
      Stefan Muenz

  2. Hallo,

    Nun habe ich aber eine Frage, momentan lade ich die Module erst wenn klar ist welches der Module benötigt wird, also wenn service=gästebuch, dann wird nach einer if-abfrage mit require das UM::guestbook; modul geladen. Ist es nun besser alle Module gleich von Anfang an zu laden (also über use) oder wirklich erst dann die Module wenn sie auch benötigt werden.

    Zuerst einmal eine Anmerkung:
    use und require arbeiten ja etwas anders. Bei use wird (siehe dazu perldoc -f use) neben dem require auch eine eventuell vorhandene import-Funktion des entsprechenden Moduls aufgerufen. Wenn das für Dich keine Rolle spielt, ist der einzige Unterschied eben, daß use im BEGIN-Block ausgeführt wird, also so früh wie möglich, während require eben zur Laufzeit ausgeführt wird, also dann, wenn die Funktion wirklich aufgerufen wird.

    So nun zur eigentlichen Frage:
    Da sind IMHO zwei verschiedene Szenarien zu beachten. Einerseits das 'normale' CGI-Umfeld, in dem ein Perlscript als Subprozeß gestartet wird, und andererseits die Verwendung von mod_perl.

    Wenn Du kein mod_perl verwendest, solltest Du dafür sorgen, daß bei jedem Aufruf des Scripts wirklich nur jene Module geladen werden, die tatsächlich benötigt werden. Wenn, wie oben erwähnt, import keine Thema für Dich ist, dann ist IMHO require die bessere Wahl, weil use ja jedesmal _alle_ Module laden würde.

    Wenn Du allerdings mod_perl verwendest, dann ist es egal, da die Module sowieso nur einmal pro Apache-Prozeß, nämlich spätestens bei der ersten Verwendung, geladen und kompiliert werden. Danach wird nur mehr auf den kompilierten Code zugegriffen. [1]

    Was ist besser für den Server, was verbraucht mehr Leistung (bei use wird das ganze ja noch vor der Laufzeit geprüft, daher müsste das ja theoretisch auch schneller sein, oder?).

    Wenn ich nur Perl berücksichtige, ist es egal wann kompiliert wird, da use auch nichts anderes macht als require (wieder ausgenommen der import-Geschichte). Somit kommt es auch nur darauf an, wie viele Module geladen werden müssen.

    Ich denke, daß, vor allem bei vielen Zugriffen, für Dich mod_perl sowieso zum Thema werden sollte, da es gerade in solchen Konstellationen einen deutlichen Vorteil bringt. Dann ist es eigentlcih egal, wie Du die Module einbindest. Außerdem hat es noch eine Menge anderer Vorteile, wie z.B. persistente Datenbankverbindungen, d.h. daß eine Datenbankverbindung nicht für jeden Request neu aufgebaut wird, sondern so lange besteht, so lange der Webserver läuft, bzw. so lange wie eben das DBMS eine VErbindung erlaubt. Das kann  vor allem bei Datenbanken, bei denen der Verbindungsaufbau lange dauert (z.B. Oracle) immens wichtig werden.

    Näheres findest Du unter http://perl.apache.org
    Interessant sind auf alle Fälle die Ausführungen unter http://perl.apache.org/guide/perl.html#use_require_do_INC_and, egal ob mit oder ohne mod_perl.

    Ach ja, das hätte ich fast vergessen: mod_perl ist eine Erweiterung vom Apache-Server. Andere Webserver können eventuell auch ähnliches bieten (Perlex für IIS). Diese Lösungen sind aber AFAIK bei weitem nicht so leistungsfähig.

    Grüße
      Klaus

    [1] Ausnahme könnte sein, daß Du das Modul änderst und, auf eine der möglichen Weisen, z.B. mit Apache::StatINC, eine Neu-Kompilierung erzwingst.