web-dev-qa-db-fra.com

Pourquoi utiliser un chargement automatique PSR-0 ou PSR-4 dans Composer si classmap est réellement plus rapide?

Je comprends que vous pouvez utiliser une norme PSR pour localiser les fichiers ou indiquer au compositeur un répertoire dans lequel rechercher des classes. La documentation recommande d'utiliser le standard PSR-4 . Il existe également une option permettant au composeur de créer un autochargeur optimisé, qui génère fondamentalement un classmap complet . Alors, pourquoi utiliser le PSR-4 si la meilleure façon de charger est d'utiliser un classmap?

Il est logique pour moi de conserver la structure de répertoires, car c’est un bon moyen d’organiser de toute façon. Cependant, il semble que l'option logique serait d'utiliser le chargement du PSR-4 sur les machines de développement, puis de classmap pour l'environnement de production. Ainsi, vous n’avez pas à reconstruire votre classmap à chaque fois que vous créez une classe, mais l’environnement de production en crée une complète dans le cadre du processus de déploiement, sans appel supplémentaire à 

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

Pourquoi utiliser un chargement automatique PSR-0 ou PSR-4 dans Composer si classmap est réellement plus rapide?

Parce que c'est plus pratique.

En production, vous pouvez utiliser une classmap (avec composer dumpautoload -o) car vous n'ajouterez pas de nouvelle classe, mais dans un environnement de développement, il est intéressant de disposer de la flexibilité offerte par PSR-0 ou PSR-4 (autrement dit, rien à faire lors de l'ajout de nouvelles classes ).

Mise à jour: vous pouvez également utiliser composer install -o, c'est plus simple.

32
Matthieu Napoli

Le problème est que la classmap n'est PAS réellement plus rapide dans tous les cas!

La vitesse de la classmap provient du fait qu'il n'est pas nécessaire de vérifier le système de fichiers si un fichier existe avant de procéder au travail toujours nécessaire de le charger, de l'analyser (les caches d'opcode aideront ici), puis de l'exécuter.

Mais l'inconvénient de la classmap est que vous générez probablement une quantité énorme de données pour chaque classe, interface et trait inclus dans les bibliothèques que vous utilisez, sans que vous l'utilisiez réellement dans votre code de production. Le chargement de grands tableaux ne se fait pas gratuitement - bien que le code ne soit pas analysé encore et encore (cache opcode), il doit encore être exécuté, la structure de données du tableau doit être mise en mémoire, remplie de nombreuses chaînes, puis mange une certaine quantité de mémoire qui aurait pu être utilisée pour autre chose.

J'ai trouvé deux ressources traitant de ce sujet: Tout d'abord, il y a le problème github n ° 1529 qui suggère des améliorations supplémentaires pour l'autochargeur du composeur en utilisant un groupe de liens symboliques pour éviter de numériser plusieurs répertoires.

La discussion à cet endroit révèle également que vous devez réellement essayer d’utiliser le meilleur préfixe d’espace de nom ou de nom de classe dans la déclaration de chargement automatique du PSR-0, c’est-à-dire la plus longue possible. Vous pouvez également utiliser plusieurs préfixes dans la déclaration.

Ensuite, il y a un article de blog lié à ce numéro qui documente certains tests de performance xhprof en utilisant un stock EZPublish 5 et en bidouillant les paramètres, notamment APC Caching et classmap dumping.

Devis d'argent:

Cette commande a créé un fichier fournisseur/composer/autoload_classmap.php de 662 Ko contenant un tableau qui est un hachage composé du nom de la classe en tant qu'index et du chemin d'accès au fichier contenant la définition de la classe en tant que valeur. Au moment où j'écris ce post, ce tableau est composé de 4168 entrées . [...] Bien que cela devrait nous fournir le mécanisme de chargement automatique le plus efficace, il ralentit les choses (de 254,53 reqs/seconde à 197,95). La raison en est que même si le fichier est mis en cache par APC, le tableau PHP contenant la carte avec plus de 4 100 entrées doit être recréé à chaque demande. 

Un classmap sera-t-il rapide? Certainement. Le plus rapide dans tous les cas? Bien sûr que non - cela dépend du rapport utilisé par rapport aux classes non utilisées par demande. Ainsi, même si en moyenne votre application utilise TOUTES les classes de la carte, une classe peut être encore plus lente si vous n'utilisez que 10% environ des classes par requête et il serait préférable d'optimiser les déclarations de chargement automatique des bibliothèques que vous utilisez. . En fait, chaque préfixe de nom de classe ne doit pointer que vers un seul répertoire.

Notez que le gain de performances que vous obtiendriez uniquement est d'environ quelques millisecondes à un chiffre par requête. Votre application est sûrement géniale si ce chiffre représente une amélioration significative des performances de l'ordre de 5 à 10%. Mais si vous êtes vraiment dans cette gamme de performances, croire aveuglément qu’une classmap est TOUJOURS plus rapide gaspille probablement beaucoup de cycles de calcul inutiles.

Si vous optimisez quelque chose: mesurez-le! Comment sauriez-vous si cela devient réellement meilleur si vous ne pouvez pas le mesurer?

45
Sven

voici ce que vous devez faire si vous ajoutez/changez de classe:

  • classmap: composer dumpautoload (peut-être aussi mettre à jour composer.json avec une nouvelle entrée de classmap)
  • psr-0: rien
  • psr-4: rien

donc, fondamentalement, vous pouvez vous déchaîner avec psr-4 et psr-0 sans vous inquiéter de savoir si votre classe nouvellement créée est correctement dans l'autoloader. De plus, vous obtenez une structure de répertoires appropriée pour votre bibliothèque free, qui représente votre espace de noms.

fichiers autochargeur:

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

Un argument important ici est que l’utilisation de psr-4 ou psr-0 dans composer.json force vous pour organiser vos fichiers de classe selon un standard strict. Cela permet aux autres (ou à vous-même dans 2 ans) qui regardent le composer.json de savoir immédiatement où sont vos cours.

Si vous ne le faites pas correctement, par exemple Si vous mal orthographiez un espace de noms, vous le saurez probablement pendant le développement ou dans vos tests unitaires en raison d'une "classe non trouvée". C'est bien, car cela vous oblige à résoudre ce problème.

La classmap est beaucoup plus clémente et permettra toute organisation arbitraire de fichiers de classe, laissant le lecteur dans le noir.

Ainsi, comme d’autres l’ont déjà dit: utilisez psr-4 ou psr-0 dans composer.json, utilisez-le pendant le développement, puis considérez l’option -o pour la production. Mais mesurer si cela apporte vraiment un avantage de performance!

2
donquixote

Le problème avec PSR-0 et PSR-4 (et le class-map) de son implémentation ne prend pas en compte l'optimisation. La mise en œuvre fait défaut au mieux.

Cependant, l'idée derrière la carte de classes fonctionne.

J'ai créé une bibliothèque qui fonctionne en générant une carte de classes. Cependant, cette carte de classes est beaucoup plus simple mais optimisée.

https://github.com/eftec/autoloadone

La carte est réduite même pour un grand projet, elle regroupe les mêmes classes du même espace de noms si elles sont contenues dans le même dossier. Si non, alors ce n'est pas un problème, ils sont également inclus. En outre, si la classe manque d'espace de nom, deux classes dans un fichier, le fichier est en dehors de la portée, ce n'est pas un problème, il les suit toutes. Vous pouvez même exclure certains dossiers ou espaces de noms. 

Par exemple, dans un grand projet

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)

Ainsi, pour un projet de 898 classes, la carte n’utilise que 12,9 Ko. 

Et quelle est la différence de performance:

  • il n'est pas nécessaire d'analyser un dossier (par exemple, si le fichier n'existe pas).
  • il ne vérifie pas si le fichier n'existe pas. 
  • ce n'est qu'un seul fichier. Donc, les frais généraux correspondent à un simple include, pas 3 pour 

Le chargement automatique du compositeur inclut (pour chaque appel) les fichiers suivants: 

  • autoload.php
  • composer/ClassLoader.php (cela dépend de la configuration)
  • composer/autoload_real.php
  • composer/autoload_namespaces.php
  • composer/autoload_psr4.php
  • composer/autoload_classmap.php (89kb)

ou il exécute les fichiers:

  • autoload.php
  • composer/ClassLoader.php (cela dépend de la configuration)
  • composer/autoload_static.php (107kb)

Bien qu'Opcache s’émerveille, mais nous incluons toujours au moins deux inclusions (au lieu d’un), plus l’un d’eux est énorme et c’est toujours un temps système, et cela reste à chaque appel.

Donc, ce qui est plus rapide. Cela dépend du projet, mais j'ai vérifié qu'habituellement, le PSR-0 est plus rapide. Cependant, la différence est faible, les deux sont lents. :-P

0
magallanes