Warum ist die Verwendung von require_once so schlecht?

143

Alles, was ich über bessere PHP-Codierungspraktiken lese, sagt immer wieder, dass ich es nicht benutze require_once wegen der Geschwindigkeit .

Warum ist das?

Was ist der richtige / bessere Weg, um das Gleiche zu tun require_once? Wenn es darauf ankommt, verwende ich PHP 5.

Uberfuzzy
quelle
9
Diese Frage ist jetzt ziemlich alt und die Antworten sind zweifelhaft relevant. Es wäre toll, eine aktualisierte Reihe von Antworten von den Teilnehmern zu sehen :)
Purefan

Antworten:

108

require_onceund include_oncebeide erfordern, dass das System ein Protokoll darüber führt, was bereits enthalten / erforderlich ist. Jeder *_onceAnruf bedeutet, dieses Protokoll zu überprüfen. So gibt es auf jeden Fall einige zusätzliche Arbeit dort getan , aber genug , um die Geschwindigkeit der gesamten App benachteiligt wurde ?

... Ich bezweifle es wirklich ... Nicht, wenn Sie nicht auf wirklich alter Hardware sind oder viel tun .

Wenn Sie sind Tausende tun *_once, könnten Sie die Arbeit selbst in einer leichteren Art und Weise tun. Für einfache Apps sollte es ausreichen , nur sicherzustellen, dass Sie sie nur einmal eingefügt haben. Wenn Sie jedoch immer noch Fehler bei der Neudefinition erhalten, können Sie Folgendes tun:

if (!defined('MyIncludeName')) {
    require('MyIncludeName');
    define('MyIncludeName', 1);
}

Ich werde mich persönlich an die *_onceAussagen halten, aber beim albernen Millionen-Pass-Benchmark können Sie einen Unterschied zwischen den beiden feststellen:

                php                  hhvm
if defined      0.18587779998779     0.046600103378296
require_once    1.2219581604004      3.2908599376678

10-100 × langsamer mit require_onceund es ist merkwürdig, dass require_oncees scheinbar langsamer ist hhvm. Auch dies ist für Ihren Code nur relevant, wenn Sie *_oncetausende Male ausgeführt werden.


<?php // test.php

$LIMIT = 1000000;

$start = microtime(true);

for ($i=0; $i<$LIMIT; $i++)
    if (!defined('include.php')) {
        require('include.php');
        define('include.php', 1);
    }

$mid = microtime(true);

for ($i=0; $i<$LIMIT; $i++)
    require_once('include.php');

$end = microtime(true);

printf("if defined\t%s\nrequire_once\t%s\n", $mid-$start, $end-$mid);

<?php // include.php

// do nothing.
Oli
quelle
29
Ich bezweifle, dass Ihre defined () -Methode schneller ist als die integrierte Nachschlagetabelle, aber ich stimme Ihrem allgemeinen Punkt zu - sicherlich kein Problem?!
Bobby Jack
1
Ich bin mir ziemlich sicher, dass Sie Recht haben, Bobby, aber ich befürworte die Definitionen nicht einmal. Es ist nur eine Option. Die Zeit, die für die Interpretation des Codes benötigt wird, kann ihn sogar geringfügig verlangsamen, aber ich weiß nicht, wie gründlich die interne Methode ist. Es kann zusätzliche Arbeit leisten, um sicherzustellen, dass keine Duplikate vorhanden sind.
Oli
8
Der andere Nachteil ist, dass APC include_once nicht zwischenspeichert und require_once IIRC
dcousineau
3
Ich habe gerade einen sehr einfachen Test der beiden Methoden durchgeführt - ich habe 1.000.000 Iterationen durchgeführt, einschließlich einer Datei, die einfach eine Konstante 'testinclude' als true definiert hat. Im ersten Test habe ich require_once verwendet, im zweiten if (! Defined ('testinclude')) und die Ergebnisse waren interessant: Require: 0.81639003753662 Not Defined: 0.17906713485718 Defined ist 0.63732290267944 Mikrosekunden schneller.
Travis Weston
Der Fall mit define ist schneller, da Sie keine zusätzlichen Überprüfungen durchführen, z. B. die Verwendung von realpath. Es geht nicht darum, zwei Dinge zu vergleichen, die wirklich gleich sind.
jgmjgm
150

Dieser Thread lässt mich zusammenzucken, weil bereits eine "Lösung veröffentlicht" wurde und er in jeder Hinsicht falsch ist. Lassen Sie uns aufzählen:

  1. Definitionen sind in PHP sehr teuer. Sie können es nachschlagen oder selbst testen, aber die einzige effiziente Möglichkeit, eine globale Konstante in PHP zu definieren, ist eine Erweiterung. (Klassenkonstanten sind in Bezug auf die Leistung eigentlich ziemlich anständig, aber dies ist wegen 2 ein strittiger Punkt.)

  2. Wenn Sie require_once()entsprechend verwenden, dh für die Aufnahme von Klassen, benötigen Sie nicht einmal eine Definition. Überprüfen Sie einfach, ob class_exists('Classname'). Wenn die Datei, die Sie einschließen, Code enthält, dh Sie sie prozedural verwenden, gibt es absolut keinen Grund, require_once()der für Sie erforderlich sein sollte. Jedes Mal, wenn Sie die Datei einschließen, wird angenommen, dass Sie einen Unterprogrammaufruf ausführen.

Für eine Weile verwendeten viele Leute die class_exists()Methode für ihre Einschlüsse. Ich mag es nicht, weil es flüchtig ist, aber sie hatten guten Grund dazu: require_once()war vor einigen der neueren Versionen von PHP ziemlich ineffizient. Aber das wurde behoben, und ich bin der Meinung, dass der zusätzliche Bytecode, den Sie für die Bedingung kompilieren müssten, und der zusätzliche Methodenaufruf jede interne Hashtabellenprüfung bei weitem überwiegen würden.

Nun ein Eingeständnis: Dieses Zeug ist schwer zu testen, weil es so wenig Zeit für die Ausführung ausmacht.

Hier ist die Frage, über die Sie nachdenken sollten: Includes sind in PHP in der Regel teuer, da der Interpreter jedes Mal, wenn er einen trifft, wieder in den Analysemodus wechseln, die Opcodes generieren und dann zurückspringen muss. Wenn Sie über 100 Includes verfügen, hat dies definitiv Auswirkungen auf die Leistung. Der Grund, warum die Verwendung oder Nichtverwendung von require_once eine so wichtige Frage ist, liegt darin, dass es Opcode-Caches das Leben schwer macht. Eine Erklärung dafür finden Sie hier, aber worauf es ankommt, ist Folgendes:

  • Wenn Sie während der Analysezeit genau wissen, welche Include-Dateien Sie für die gesamte Lebensdauer der Anforderung benötigen, übernehmen die Dateien require()ganz am Anfang und der Opcode-Cache alles andere für Sie.

  • Wenn Sie keinen Opcode-Cache ausführen, befinden Sie sich an einem schwierigen Ort. Das Einfügen aller Ihrer Includes in eine Datei (tun Sie dies nicht während der Entwicklung, sondern nur in der Produktion) kann sicherlich dazu beitragen, die Zeit zu analysieren, aber es ist mühsam, dies zu tun, und Sie müssen genau wissen, was Sie während des Vorgangs einschließen Anfrage.

  • Autoload ist sehr praktisch, aber langsam, da die Autoload-Logik jedes Mal ausgeführt werden muss, wenn ein Include durchgeführt wird. In der Praxis habe ich festgestellt, dass das automatische Laden mehrerer spezialisierter Dateien für eine Anforderung kein allzu großes Problem darstellt. Sie sollten jedoch nicht alle benötigten Dateien automatisch laden.

  • Wenn Sie vielleicht 10 enthält (dies ist eine sehr Rückseite des Umschlags Berechnung), all dies Wichsen ist es nicht wert: nur Ihre Datenbankabfragen oder etwas optimieren.

Edward Z. Yang
quelle
14
Dies ist 4 Jahre alt und zum größten Teil nicht mehr gilt, define(), require_once()und defined()alle nehmen etwa 1-2 Mikrosekunden je auf meinem Rechner.
Daniel Beardsley
72
Aber das sind 2 Mikrosekunden früher, als der Benutzer die Seite haben würde. Über ein Jahr Seitenaufrufe könnte der Benutzer ganze 3 Sekunden sparen! Sie konnten in dieser Zeit ein Zehntel eines Werbespots sehen! Denken Sie an den Benutzer. Verschwenden Sie keine Mikrosekunden.
Andrew Ensley
15
Damit jeder den Sarkasmus bemerkt, beträgt eine Mikrosekunde 1/1000000 Sekunde.
Andy Chase
1
@ AndrewEnsley Sie irren sich einfach mit all Ihrem Sarkasmus. Sie wissen nicht, dass PHP auch auf Mikroprozessoren ausgeführt wird. 1 Mikrosekunde auf Ihrem PC entspricht mehreren Millisekunden auf einem Mikroprozessor. Was ist nun mit 20 Include-Dateien, einem größeren Projekt? Das ist die 20-fache Verzögerung von mehreren Millisekunden, sodass wir bereits einen Punkt erreichen, der für einen Menschen erkennbar ist. Wenn dieses Skript häufig aufgerufen wird, führt dies zu Leistungsproblemen auf dem System. Optimierung ist kein Scherz und die ganze Welt dreht sich nicht um Ihren PC. Es werden zehntausende CPUs verwendet.
John
2
@John. Es war ein Witz in guter Stimmung. Keine Bosheit beabsichtigt. Wenn es sich für Sie lohnt, Ihre Includes zu optimieren, fahren Sie fort.
Andrew Ensley
66

Ich wurde neugierig und überprüfte Adam Backstroms Link zu Tech Your Universe . Dieser Artikel beschreibt einen der Gründe, warum require anstelle von require_once verwendet werden sollte. Ihre Behauptungen hielten meiner Analyse jedoch nicht stand. Es würde mich interessieren, wo ich die Lösung möglicherweise falsch analysiert habe. Ich habe PHP 5.2.0 für Vergleiche verwendet.

Ich begann damit, 100 Header-Dateien zu erstellen, die require_once verwendeten, um eine weitere Header-Datei einzuschließen. Jede dieser Dateien sah ungefähr so ​​aus:

<?php
    // /home/fbarnes/phpperf/hdr0.php
    require_once "../phpperf/common_hdr.php";

?>

Ich habe diese mit einem schnellen Bash-Hack erstellt:

for i in /home/fbarnes/phpperf/hdr{00..99}.php; do
    echo "<?php
    // $i" > $i
    cat helper.php >> $i;
done

Auf diese Weise konnte ich leicht zwischen require_once und require wechseln, wenn ich die Header-Dateien einbezog. Ich habe dann eine app.php erstellt, um die hundert Dateien zu laden. Das sah so aus:

<?php
    // Load all of the php hdrs that were created previously
    for($i=0; $i < 100; $i++)
    {
        require_once "/home/fbarnes/phpperf/hdr$i.php";
    }

    // Read the /proc file system to get some simple stats
    $pid = getmypid();
    $fp = fopen("/proc/$pid/stat", "r");
    $line = fread($fp, 2048);
    $array = split(" ", $line);

    // Write out the statistics; on RedHat 4.5 with kernel 2.6.9
    // 14 is user jiffies; 15 is system jiffies
    $cntr = 0;
    foreach($array as $elem)
    {
        $cntr++;
        echo "stat[$cntr]: $elem\n";
    }
    fclose($fp);
?>

Ich habe die Header require_once den Headern require_ gegenübergestellt, die eine Header-Datei verwendet haben, die wie folgt aussieht:

<?php
    // /home/fbarnes/phpperf/h/hdr0.php
    if(!defined('CommonHdr'))
    {
        require "../phpperf/common_hdr.php";
        define('CommonHdr', 1);
    }
?>

Ich habe keinen großen Unterschied festgestellt, als ich dies mit require vs. require_once ausgeführt habe. Tatsächlich schienen meine ersten Tests zu implizieren, dass require_once etwas schneller war, aber ich glaube das nicht unbedingt. Ich habe das Experiment mit 10000 Eingabedateien wiederholt. Hier habe ich einen konsequenten Unterschied gesehen. Ich habe den Test mehrmals ausgeführt. Die Ergebnisse sind nahe beieinander, aber bei Verwendung von require_once werden durchschnittlich 30,8 Benutzer-Jiffies und 72,6 System-Jiffies verwendet. Die Verwendung erfordert durchschnittlich 39,4 Benutzer-Jiffies und 72,0 System-Jiffies. Daher scheint die Last mit require_once etwas geringer zu sein. Die Wanduhrzeit ist jedoch leicht erhöht. Die 10.000 erforderlichen Anrufe benötigen durchschnittlich 10,15 Sekunden, und die 10.000 erforderlichen Anrufe benötigen durchschnittlich 9,84 Sekunden.

Der nächste Schritt besteht darin, diese Unterschiede zu untersuchen. Ich habe strace verwendet , um die Systemaufrufe zu analysieren, die gerade getätigt werden.

Vor dem Öffnen einer Datei aus require_once werden folgende Systemaufrufe ausgeführt:

time(NULL)                              = 1223772434
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=88, ...}) = 0
time(NULL)                              = 1223772434
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

Dies steht im Gegensatz zu erfordern:

time(NULL)                              = 1223772905
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=146, ...}) = 0
time(NULL)                              = 1223772905
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

Tech Your Universe impliziert, dass require_once mehr lstat64-Aufrufe tätigen sollte. Beide führen jedoch die gleiche Anzahl von lstat64-Aufrufen durch. Möglicherweise besteht der Unterschied darin, dass ich APC nicht ausführe, um den obigen Code zu optimieren. Als nächstes verglich ich jedoch die Strace-Ausgabe für die gesamten Läufe:

[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
  190709 strace_1000r.out
  210707 strace_1000ro.out
  401416 total

Tatsächlich gibt es bei Verwendung von require_once ungefähr zwei weitere Systemaufrufe pro Header-Datei. Ein Unterschied besteht darin, dass require_once einen zusätzlichen Aufruf der Funktion time () hat:

[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20009
strace_1000ro.out:30008

Der andere Systemaufruf ist getcwd ():

[fbarnes@myhost phpperf]$ grep -c getcwd strace_1000r.out strace_1000ro.out
strace_1000r.out:5
strace_1000ro.out:10004

Dies wird aufgerufen, weil ich mich für einen relativen Pfad entschieden habe, auf den in den hdrXXX-Dateien verwiesen wird. Wenn ich dies zu einer absoluten Referenz mache, ist der einzige Unterschied der zusätzliche Zeitaufruf (NULL) im Code:

[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
  190705 strace_1000r.out
  200705 strace_1000ro.out
  391410 total
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20008
strace_1000ro.out:30008

Dies scheint zu implizieren, dass Sie die Anzahl der Systemaufrufe reduzieren können, indem Sie absolute Pfade anstelle relativer Pfade verwenden. Der einzige Unterschied besteht in den Zeitaufrufen (NULL), die anscheinend zur Instrumentierung des Codes verwendet werden, um zu vergleichen, was schneller ist.

Ein weiterer Hinweis ist, dass das APC-Optimierungspaket eine Option namens "apc.include_once_override" enthält, die behauptet, dass es die Anzahl der Systemaufrufe reduziert, die von den Aufrufen require_once und include_once ausgeführt werden (siehe PHP-Dokumentation ).

terson
quelle
6
Und jede "Optimierung", die Sie 10.000 Mal ausführen müssen, um einen so winzigen Unterschied zu erkennen, ist nicht einmal besorgniserregend. Verwenden Sie einen Profiler und finden Sie heraus, wo die tatsächlichen Engpässe in Ihrer Anwendung liegen. Ich bezweifle, dass diese Frage der Engpass ist.
DGM
1
Das alles bedeutet, dass es überhaupt keine Rolle spielt. Verwenden Sie alles, was für Sie logisch besser funktioniert.
Buttle Butkus
wat are jiffies
OverCoder
21

Können Sie uns Links zu diesen Codierungspraktiken geben, um dies zu vermeiden? Für mich ist das kein Problem . Ich habe mir den Quellcode nicht selbst angesehen, aber ich würde mir vorstellen, dass der einzige Unterschied zwischen includeund darin include_oncebesteht, dass include_oncedieser Dateiname einem Array hinzugefügt und das Array jedes Mal überprüft wird. Es wäre einfach, dieses Array sortiert zu halten, daher sollte die Suche darüber O (log n) sein, und selbst eine mittelgroße Anwendung würde nur ein paar Dutzend Includes enthalten.

nickf
quelle
Eines ist, chazzuka.com/blog/?p=163 sie haben es wirklich nicht getan, aber zu viele teure Dinge summieren sich. und tatsächlich werden alle enthaltenen / erforderlichen Dateien zu einem internen Array hinzugefügt (es gibt eine Funktion, um es zurückzugeben). Ich denke, die _once's müssen dieses Array schleifen und strcmp's machen, was sich summieren würde
Uberfuzzy
7

Eine bessere Möglichkeit besteht darin, einen objektorientierten Ansatz zu verwenden und __autoload () zu verwenden .

Greg
quelle
3
Aber das allererste Beispiel auf der Seite zum
automatischen Laden von
Ich kaufe das nicht. Es gibt VIELE Situationen, in denen OO nicht so gut passt wie andere Paradigmen. Sie sollten es daher nicht erzwingen, nur um die winzigen Vorteile von __autoload () zu nutzen.
Bobby Jack
1
Sie würden denken, dass das automatische Laden tatsächlich länger dauern würde als * _once (vorausgesetzt, Sie benötigen nur das, was Sie benötigen).
Nickf
Nein, es ist nicht, zumindest nicht definitiv, dass Autoload noch irgendwie enthalten sein muss, und es ist ein letzter Ausweg für PHP, bevor Fehler fehlschlagen. In Wirklichkeit führt PHP tatsächlich potenziell unnötige Überprüfungen an allen Stellen durch, die für Include / Require und AFTER gelten würden DASS es Autoload nennen würde (falls definiert) ... PS: __autoload()wird nicht empfohlen und es könnte in Zukunft veraltet sein, sollten Sie spl_autoload_register(...)heutzutage verwenden ... PS2: Verstehen Sie mich nicht falsch, ich verwende manchmal Autoload-Funktionen; )
jave.web
6

Es ist nicht die Funktion zu verwenden, die schlecht ist. Es ist ein falsches Verständnis, wie und wann es in einer gesamten Codebasis verwendet werden soll. Ich werde diesem möglicherweise missverstandenen Begriff nur etwas mehr Kontext hinzufügen:

Die Leute sollten nicht denken, dass require_once eine langsame Funktion ist. Sie müssen Ihren Code auf die eine oder andere Weise einfügen. Die Geschwindigkeit von require_once()vs. require()ist nicht das Problem. Es geht um die Leistung, die Einschränkungen behindert, die sich aus der blinden Verwendung ergeben können. Wenn es ohne Berücksichtigung des Kontexts allgemein verwendet wird, kann dies zu großer Speicherverschwendung oder verschwenderischem Code führen.

Was ich gesehen habe, ist wirklich schlecht, wenn riesige monolithische Frameworks require_once()auf die falsche Weise verwendet werden, insbesondere in einer komplexen objektorientierten Umgebung (OO).

Nehmen Sie das Beispiel der Verwendung require_once()an der Spitze jeder Klasse, wie es in vielen Bibliotheken zu sehen ist:

require_once("includes/usergroups.php");
require_once("includes/permissions.php");
require_once("includes/revisions.php");
class User{
  // User functions
}

Die UserKlasse ist also so konzipiert, dass alle drei anderen Klassen verwendet werden. Meinetwegen!

Aber was ist nun, wenn ein Besucher die Website durchsucht und nicht einmal angemeldet ist und das Framework geladen wird: require_once("includes/user.php");für jede einzelne Anfrage.

Es enthält 1 + 3 unnötige Klassen, die während dieser speziellen Anfrage niemals verwendet werden. Auf diese Weise verbrauchen aufgeblähte Frameworks 40 MB pro Anforderung im Gegensatz zu 5 MB oder weniger.


Die andere Möglichkeit, es zu missbrauchen, besteht darin, dass eine Klasse von vielen anderen wiederverwendet wird! Angenommen, Sie haben ungefähr 50 Klassen, die helperFunktionen verwenden. Um sicherzustellen helpers, dass diese Klassen beim Laden verfügbar sind, erhalten Sie:

require_once("includes/helpers.php");
class MyClass{
  // Helper::functions(); // etc..
}

Hier ist an sich nichts falsch. Wenn jedoch eine Seitenanforderung 15 ähnliche Klassen enthält. Sie laufen require_once15 Mal oder für ein schönes Bild:

require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");

Die Verwendung von require_once () wirkt sich technisch auf die Leistung aus, wenn diese Funktion 14 Mal ausgeführt wird, zusätzlich dazu, dass diese unnötigen Zeilen analysiert werden müssen. Mit nur 10 anderen häufig verwendeten Klassen mit diesem ähnlichen Problem könnten mehr als 100 Zeilen eines solchen sinnlosen sich wiederholenden Codes berücksichtigt werden.

Damit lohnt es sich wahrscheinlich, stattdessen require("includes/helpers.php");am Bootstrap Ihrer Anwendung oder Ihres Frameworks zu arbeiten. Da jedoch alles relativ ist, hängt alles davon ab, ob das Gewicht helpersim Verhältnis zur Nutzungshäufigkeit der Klasse es wert ist, 15 bis 100 Zeilen zu sparen require_once(). Aber wenn die Wahrscheinlichkeit, dass die helpersDatei bei einer bestimmten Anfrage nicht verwendet wird, keine ist, requiresollte sie auf jeden Fall in Ihrer Hauptklasse sein. Nachdem require_oncein jeder Klasse wird separat eine Verschwendung von Ressourcen.


Die require_onceFunktion ist bei Bedarf nützlich, sollte jedoch nicht als monolithische Lösung angesehen werden, die überall zum Laden aller Klassen verwendet werden kann.

Hexalys
quelle
5

Das PEAR2-Wiki (sofern vorhanden) listete gute Gründe auf, um alle erforderlichen / eingeschlossenen Anweisungen zugunsten des automatischen Ladens aufzugeben , zumindest für den Bibliothekscode. Diese binden Sie an starre Verzeichnisstrukturen, wenn alternative Verpackungsmodelle wie Phar in Sicht sind.

Update: Da die im Web archivierte Version des Wikis augenfällig hässlich ist, habe ich die überzeugendsten Gründe unten kopiert:

  • include_path ist erforderlich, um ein (PEAR) -Paket zu verwenden. Dies macht es schwierig, ein PEAR-Paket in einer anderen Anwendung mit einem eigenen include_path zu bündeln, eine einzelne Datei mit den erforderlichen Klassen zu erstellen und ein PEAR-Paket ohne umfangreiche Änderungen des Quellcodes in ein Phar-Archiv zu verschieben.
  • Wenn require_once der obersten Ebene mit bedingtem require_once gemischt wird, kann dies zu Code führen, der von Opcode-Caches wie APC, die mit PHP 6 gebündelt werden, nicht zwischengespeichert werden kann.
  • Für relative require_once muss include_path bereits auf den richtigen Wert eingestellt sein, sodass es unmöglich ist, ein Paket ohne den richtigen include_path zu verwenden
Steve Clay
quelle
5

Die *_once()Funktionen stat jedes übergeordnete Verzeichnis, um sicherzustellen, dass die Datei, die Sie einschließen, nicht mit der bereits enthaltenen übereinstimmt. Das ist ein Teil des Grundes für die Verlangsamung.

Ich empfehle die Verwendung eines Tools wie Siege für das Benchmarking. Sie können alle vorgeschlagenen Methoden ausprobieren und die Antwortzeiten vergleichen.

Mehr require_once()dazu bei Tech Your Universe .

Annika Backstrom
quelle
Danke für den Hinweis auf den Artikel. require_once () ist ein guter Sicherheitsgurt für Dateien mit doppeltem Einschluss, und wir werden ihn weiterhin verwenden, aber es ist schön, ihn sauber zu machen.
Andy Lester
2

Selbst wenn require_onceund include_once sind langsamer als requireund include(oder was auch immer Alternativen existieren könnten), sind wir über die kleinste Ebene der Mikro-Optimierung hier sprechen. Ihre Zeit wird viel besser damit verbracht, diese schlecht geschriebene Schleifen- oder Datenbankabfrage zu optimieren, als sich um so etwas zu kümmern require_once.

Nun könnte man ein Argument vorbringen, das require_onceschlechte Codierungspraktiken zulässt, weil Sie nicht darauf achten müssen, Ihre Includes sauber und organisiert zu halten, aber das hat nichts mit der Funktion selbst und insbesondere nicht mit ihrer Geschwindigkeit zu tun .

Natürlich ist das automatische Laden aus Gründen der Code-Sauberkeit und der Wartungsfreundlichkeit besser, aber ich möchte klarstellen, dass dies nichts mit Geschwindigkeit zu tun hat .

NeuroXc
quelle
0

Sie testen mit include die Alternative von oli und __autoload (); und testen Sie es mit etwas wie APC installiert.

Ich bezweifle, dass die Verwendung von Konstanten die Dinge beschleunigen wird.

Dinoboff
quelle
0

Ja, es ist etwas teurer als einfach erforderlich (). Ich denke, der Punkt ist, wenn Sie Ihren Code so organisiert halten können, dass keine Includes dupliziert werden, verwenden Sie nicht die Funktionen * _once (), da Sie dadurch einige Zyklen sparen.

Die Verwendung der Funktionen _once () wird Ihre Anwendung jedoch nicht beenden. Verwenden Sie es im Grunde genommen nicht als Ausrede, um Ihre Includes nicht organisieren zu müssen . In einigen Fällen ist die Verwendung immer noch unvermeidlich und keine große Sache.

Lucas Oman
quelle
-2

Ich denke, in der PEAR-Dokumentation gibt es eine Empfehlung für require, require_once, include und include_once. Ich folge dieser Richtlinie. Ihre Bewerbung wäre klarer.

Ekkmanz
quelle
Einige Referenzen wären in Ordnung.
Peter Mortensen
-3

Es hat nichts mit Geschwindigkeit zu tun. Es geht darum, anmutig zu scheitern.

Wenn require_once () fehlschlägt, ist Ihr Skript fertig. Sonst wird nichts verarbeitet. Wenn Sie include_once () verwenden, versucht der Rest Ihres Skripts, das Rendern fortzusetzen, sodass Ihre Benutzer möglicherweise nicht wissen, was in Ihrem Skript fehlgeschlagen ist.

Ashchristopher
quelle
1
Nicht unbedingt. Sie können tatsächlich einen Fehlerhandler oder einen Shutdown-Handler einbinden, um dem Benutzer eine nette Fehlerseite zu geben (obwohl dies selten der Fall ist). Als Entwickler würde ich viel lieber sofort Fehler machen.
Edward Z. Yang
1
Oder, wie es der Fall sein kann, nicht versagt anmutig - wenn einige wichtige Datei benötigen nicht () 'd richtig, es ist eine gute Idee , nur aufgeben und Halt. Aber das ist require vs include, während ich denke, dass sich die Frage mehr auf require vs require_once konzentriert.
HoboBen
-4

Meine persönliche Meinung ist, dass die Verwendung von require_once (oder include_once) eine schlechte Praxis ist, da require_once für Sie prüft, ob Sie diese Datei bereits aufgenommen haben, und Fehler von doppelt eingeschlossenen Dateien unterdrückt, die zu schwerwiegenden Fehlern führen (wie doppelte Deklaration von Funktionen / Klassen / etc.) .

Sie sollten wissen, ob Sie eine Datei einfügen müssen.

Joe Scylla
quelle