wake-up-neo.net

Warum sollte in Composer ein Autoload mit PSR-0 oder PSR-4 verwendet werden, wenn die Klassenzuordnung tatsächlich schneller ist?

Ich verstehe, dass Sie entweder einen PSR-Standard zum Suchen von Dateien verwenden können oder Composer ein Verzeichnis mitteilen können, das nach Klassen durchsucht werden soll. Die Dokumentation empfiehlt die Verwendung des Standards PSR-4 . Es gibt auch eine Option für Composer, um einen optimierten Autoloader zu erstellen, der im Wesentlichen eine vollständige Classmap generiert. Warum sollte man also überhaupt PSR-4 verwenden, wenn man am besten mit einer Classmap lädt?

Es ist für mich sinnvoll, die Verzeichnisstruktur beizubehalten, da sich dies auf jeden Fall gut organisieren lässt. Es scheint jedoch die logische Option zu sein, PSR-4 auf Entwicklungsmaschinen zu laden, und dann Classmap für die Produktionsumgebung. Auf diese Weise müssen Sie Ihre Classmap nicht jedes Mal neu erstellen, wenn Sie eine neue Klasse erstellen. Die Produktionsumgebung erstellt jedoch eine vollständige Umgebung als Teil des Bereitstellungsprozesses, ohne dass ein zusätzlicher Aufruf erfolgt 

./composer.phar dump-autoload -o
29
Bryan Agee

Warum sollte in Composer ein Autoload mit PSR-0 oder PSR-4 verwendet werden, wenn die Klassenzuordnung tatsächlich schneller ist?

Weil es praktischer ist.

In der Produktion können Sie eine Classmap (mit composer dumpautoload -o) verwenden, da Sie keine neue Klasse hinzufügen. In der Dev-Umgebung ist es jedoch interessant, über die Flexibilität von PSR-0 oder PSR-4 zu verfügen (dh beim Hinzufügen neuer Klassen nichts zu tun) ).

Update: Sie können auch composer install -o verwenden, es ist einfacher.

32
Matthieu Napoli

Das Problem ist, dass die Classmap NICHT in jedem Fall wirklich schneller ist!

Die Geschwindigkeit der Classmap ist darauf zurückzuführen, dass Sie das Dateisystem nicht überprüfen müssen, ob eine Datei vorhanden ist, bevor Sie die immer erforderliche Arbeit erledigen, indem Sie sie laden, analysieren (Opcode-Caches helfen hier) und dann ausführen.

Der Nachteil der Classmap besteht jedoch darin, dass Sie möglicherweise für jede einzelne Klasse, Schnittstelle und Eigenschaft, die in den verwendeten Bibliotheken enthalten ist, eine riesige Datenmenge generieren können, ohne dass Sie sie tatsächlich in Ihrem Produktionscode verwenden. Das Laden riesiger Arrays ist nicht kostenlos - während der Code nicht immer wieder analysiert werden muss (Opcode-Cache), muss er noch ausgeführt werden, die Array-Datenstruktur muss in den Speicher gestellt, mit vielen Zeichenfolgen gefüllt werden und dann verbraucht etwas Speicher, der möglicherweise für etwas anderes verwendet werden konnte.

Ich habe zwei Ressourcen gefunden, die sich mit diesem Thema befassen: Erstens gibt es github Ausgabe # 1529 , in dem weitere Verbesserungen für den Autoloader des Komponisten vorgeschlagen werden, die eine Reihe von Symlinks verwenden, um das Durchsuchen mehrerer Verzeichnisse zu vermeiden.

Die Diskussion dort zeigt auch, dass Sie tatsächlich versuchen sollten, das bestmögliche Namespace- oder Klassennamen-Präfix in der PSR-0-Autoload-Deklaration zu verwenden, d. H. Das längste mögliche. Sie können auch mehrere Präfixe in der Deklaration verwenden.

Dann gibt es einen Blogeintrag, der in dieser Ausgabe verlinkt ist der einige Xhprof-Benchmarks anhand eines Standard-EZPublish 5 dokumentiert und mit den Einstellungen spielt, einschließlich APC-Caching und Classmap-Dumping.

Geldzitat:

Mit diesem Befehl wurde eine 662KiB Vendor/composer/autoload_classmap.php -Datei erstellt, die ein Array enthält, das ein Hash ist, das aus dem Klassennamen als Index und dem Pfad zu der Datei mit der Klassendefinition als Wert besteht. Zum Zeitpunkt, als ich diesen Beitrag schreibe, besteht dieses Array aus 4168 Einträgen . [...] Obwohl es uns den effizientesten Autoloading-Mechanismus geben sollte, verlangsamt es sich tatsächlich (von 254.53 reqs/Sekunde auf 197,95). Der Grund ist, dass selbst wenn die Datei von APC zwischengespeichert wird, das PHP - Array, das die Map mit mehr als 4100 Einträgen enthält, bei jeder einzelnen Anforderung neu erstellt werden muss. 

Wird eine Klassenübersicht schnell sein? Bestimmt. In jedem Fall am schnellsten? Natürlich nicht - es hängt vom verwendeten Verhältnis zu den nicht verwendeten Klassen pro Anfrage ab. Selbst wenn im Durchschnitt in Ihrer Anwendung tatsächlich ALLE Klassen in der Map verwendet werden, ist eine Classmap möglicherweise noch langsamer, wenn Sie nur etwa 10% der Klassen pro Anforderung verwenden, und Sie sollten die Autoload-Deklarationen der verwendeten Bibliotheken besser optimieren . Tatsächlich sollte jedes Klassennamenpräfix immer nur auf genau ein Verzeichnis verweisen.

Beachten Sie, dass der Leistungsgewinn, den Sie nur im Bereich von etwa einstelligen einstelligen Millisekunden pro Anfrage erzielen würden, liegt. Ihre Anwendung ist sicherlich großartig, wenn diese Zahl eine signifikante Leistungssteigerung im Bereich von 5 bis 10% bedeutet. Wenn Sie sich jedoch wirklich in diesem Leistungsbereich befinden, verschwendet der blinde Glaube, dass eine Classmap IMMER schneller ist, eine Menge unnötiger CPU-Zyklen.

Wenn Sie etwas optimieren: Messen Sie es! Wie würden Sie wissen, ob es tatsächlich besser wird, wenn Sie es nicht messen können?

45
Sven

wenn Sie Klassen hinzugefügt/geändert haben, müssen Sie Folgendes tun:

  • classmap: composer dumpautoload (eventuell auch composer.json mit einem neuen classmap-Eintrag aktualisieren)
  • psr-0: nichts
  • psr-4: nichts

im Grunde können Sie also mit psr-4 und psr-0 wild gehen, ohne sich Sorgen zu machen, ob Ihre neu erstellte Klasse im Autoloader richtig ist. Außerdem erhalten Sie eine free - korrekte Verzeichnisstruktur Ihrer Bibliothek, die Ihren Namespace darstellt.

autoloader-Dateien:

  • classmap: vendor/composer/autoload_classmap.php
  • psr-0: vendor/composer/autoload_namespaces.php
  • psr-4: vendor/composer/autoload_psr4.php
9
zwacky

Ein wichtiges Argument ist hier, dass die Verwendung von psr-4 oder psr-0 in composer.json zwingt you, Ihre Klassendateien nach einem strengen Standard zu organisieren. Dies ermöglicht anderen (oder sich selbst in 2 Jahren), die auf composer.json schauen, sofort zu wissen, wo sich Ihre Klassen befinden.

Wenn Sie dies falsch machen, z. Wenn Sie einen Namespace falsch schreiben, werden Sie wahrscheinlich während der Entwicklung oder in Ihren Komponententests aufgrund einer "Klasse nicht gefunden" erfahren. Das ist gut, weil es Sie zwingt, dies zu beheben.

Die Klassenzuordnung ist viel verzeihender und erlaubt jede willkürliche Organisation von Klassendateien, wodurch der Leser im Dunkeln bleibt.

Wie andere bereits gesagt haben: Verwenden Sie psr-4 oder psr-0 in composer.json, arbeiten Sie damit während der Entwicklung und erwägen Sie dann die Option -o für die Produktion. Aber messen Sie, ob dies wirklich einen Leistungsvorteil bringt!

2
donquixote

Das Problem mit PSR-0 und PSR-4 (und der Klassenzuordnung) seiner Implementierung berücksichtigt die Optimierung nicht. Die Umsetzung fehlt bestenfalls.

Die Idee hinter der Klassenkarte funktioniert jedoch.

Ich habe eine Bibliothek erstellt, die eine Klassenkarte generiert. Diese Klassenzuordnung ist jedoch viel einfacher und dennoch optimiert.

https://github.com/eftec/autoloadone

Die Map wird auch für ein großes Projekt verkleinert. Sie gruppiert dieselben Klassen desselben Namespaces, wenn sie im selben Ordner enthalten sind. Wenn nicht, dann ist es kein Problem, dass sie auch enthalten sind. Wenn die Klasse keinen Namespace hat, befinden sich zwei Klassen in einer Datei. Die Datei befindet sich außerhalb des Gültigkeitsbereichs. Dies ist kein Problem, sie verfolgt alle. Sie könnten sogar einige Ordner oder Namespaces ausschließen. 

Zum Beispiel in einem großen Projekt

Number of Classes: 898
Number of Namespaces: 62
Number of Maps: 117
Number of PHP Files: 1693
Number of PHP Autorun: 0
Number of conflict: 1
Ratio map: 6.91% (less is better. 100% means one map/one file)
Map size: 12.9 kbytes (less is better, it's an estimate of the memory used by the map)

Für ein Projekt mit 898 Klassen benötigt die Karte also nur 12,9 KB. 

Und was ist der Unterschied in der Leistung:

  • es muss kein Ordner gescannt werden (zum Beispiel, wenn die Datei nicht existiert).
  • es wird nicht überprüft, ob die Datei nicht vorhanden ist. 
  • es ist nur eine einzige Datei. Der Overhead ist also ein einzelnes Include, nicht 3 für 

Autoload des Composers enthält (für jeden Aufruf) die nächsten Dateien: 

  • autoload.php
  • composer/ClassLoader.php (hängt von der Konfiguration ab)
  • composer/autoload_real.php
  • composer/autoload_namespaces.php
  • composer/autoload_psr4.php
  • komponist/autoload_classmap.php (89kb)

oder es führt die Dateien aus:

  • autoload.php
  • composer/ClassLoader.php (hängt von der Konfiguration ab)
  • komponist/autoload_static.php (107kb)

Zwar wundert sich Opcache, aber wir enthalten immer noch mindestens zwei (statt eines), und einer davon ist riesig und es ist immer noch ein Overhead, und es ist immer noch ein Anruf.

Also das ist schneller. Es hängt vom Projekt ab, aber ich habe überprüft, dass normalerweise PSR-0 schneller ist. Der Unterschied ist jedoch schwach, beide sind langsam. :-P

0
magallanes