PHP : le mal, le bien et le mieux.

Statut
N'est pas ouverte pour d'autres réponses.

ozilrit

Elite
Quelques conventions : Zend Framework coding standards.

L'impression (performance) :

  • les doubles guillemets imposent à php de parser toute la chaîne,
  • la concaténation à un coût.
  • Code:
    Mal : 
    <?php echo "Je me prénomme $firstname."; ?>
    
    Bien :
    <?php echo 'Je me prénomme ' . $firstname . '.'; ?>
    
    Mieux :
    <?php echo 'Je me prénomme ', $firstname, '.'; ?>

La boucle for (performance) :

  • le mal recalculera le nombre d'éléments du tableau à chaque itération,
  • le bien calculera ce nombre avant,
  • le mieux n'étendra pas le nombre d'appels à effectuer.
  • Code:
    Mal : 
    <?php for($i = 0; $i < count ( $array ); $i ++) {
      $array [$i] = 'Enregistrement n°'.$i;
    } ?>
    
    Bien :
    <?php $count = count ( $array );
    for($i = 0; $i < $count; $i ++) {
      $array [$i] = 'Enregistrement n°'.$i;
    } ?>
    
    Mieux :
    <?php for($i = 0, $count = count ( $array ); $i < $count; $array [$i ++] = 'Enregistrement n°'.$i); ?>


Parcourir le nième niveau d'un tableau (performance) :
  • Le mal devra parcourir chaque niveau du tableau avant d'imprimer,
  • le bien exploitera une référence directe à ce niveau.
  • Code:
    Mal :
    <?php
    for($i = 0, $count = count ( $array ['key'] ['key'] ['key'] ['key'] ); $i < $count; $i ++) {
      echo $array ['key'] ['key'] ['key'] ['key'] [$i];
    }
    ?>
    
    Bien :
    <?php
    $ref &= $array ['key'] ['key'] ['key'] ['key'];
    for($i = 0, $count = count ( $ref ); $i < $count; $i ++) {
      echo $ref [$i];
    }
    ?>

Comparaison des n premiers caractères d'une chaine (performance) :
  • Code:
    Mal :
    <?php if (substr ( 'Coucou' , 0 , 3 ) === 'Cou') /* Pompompom */ ?>
    
    Bien :
    <?php if (! strncmp ( 'Coucou' , 'Cou' , 3 )) /* Pompompom */ ?>


S'assurer qu'une chaîne n'est pas vide (piège) :

  • Le mal répondra vrai si la chaîne est '' ou 0, ou encore false (ce qui est en fait parfaitement logique),
  • le mieux vérifiera qu'un premier char est défini.
  • Code:
    Mal :
    <?php if (isset ($string)) /* pompompom */ ?>
    
    Bien :
    <?php if (isset ($string) && (! empty ($string))) /* pompompom */ ?>
    
    Mieux :
    <?php if (isset ($string{0})) /* pompompom */ ?>


S'assurer qu'une chaîne ne dépasse pas 32 caractères (performance) :

  • Le mieux vérifiera la présence d'un 33ème char.
  • Code:
    Bien :
    <?php if (strlen ($string) < 33) /* pompompom */ ?>
    
    Mieux :
    <?php if (! isset ($string{32})) /* pompompom */ ?>


L'opérateur ternaire (performance) :
  • Cet opérateur est illisible, limitez-vous donc à des conditions simples d'un niveau.
  • Code:
    Bien :
    <?php if (true === true) { echo 'Vrai'; } else { echo 'Faux'; } ?>
    
    Un peu mieux :
    <?php echo true === true ? 'Vrai' : 'Faux'; ?>


Inclure un fichier (performance) :
  • Définissez des chemins absolus,
  • évitez les fonctions _once.
  • Code:
    Mal :
    <?php require_once ('/pompompom/'.$class.'.php'); ?>
    
    Bien :
    <?php if (! class_exists ($class)) require ('/pompompom/'.$class.'.php'); ?>


Quelques petits trucs :
  • Evitez l'opérateur de suppression d'erreur @,
  • regex : utilisez ?: afin d'éviter la capture de parenthèses inutiles ou définissez des classes,
  • utilisez des constantes de class plutôt que globales,
  • utilisez le bitwise,
  • utilisez un profiler (zend, apd, xdebug).


D'autres petits trucs que j'approfondirai si vous le souhaitez :
  • Utilisez un cache d'opcode,
  • forcez le type de certains arguments (nécessite de modifier les sources),
  • définissez un entrepôt de données unique mais multisources (stock, bdd, xml, mémoire),
  • stockez les variables persistantes en mémoire,
  • stockez les sessions sur bdd ou en mémoire,
  • gzipez le contenu,
  • limitez vos paquets à 4ko,
  • définissez la période de mise en cache côté client,
  • définissez une texture plutôt que 10 images différentes,
  • vérifiez qu'une modification peut se faire avant de la tenter,
  • quittez Apache. =]
N'hésitez pas à proposer un truc ! =]

En espérant que ceci soit utile.
 

null

ose();
C'est bon à savoir, surtout pour l'histoire de vérifier la taille d'une chaîne =]
 
1er
OP
O

ozilrit

Elite
J'oubliais : lors du développement, créez une architecture sobre et utile de l'application où chaque fichier est clair et documenté.

- votre-application
- - app
- - - app1
- - - - etc
- - - - model
- - - - view
- - - - controller
- - - - webroot
- - - app2
- - - - etc
- - - - model
- - - - view
- - - - controller
- - - - webroot
- - lib
- - - database
- - - - mysql
- - - - oracle
- - - - firebird
- - - cache
- - - - apc
- - - - memcache

Puis, le coût des inclusions étant ce qu'il est : tentez de créer un fichier global (sans commentaires, ni espaces, ni tabs, ni sauts de lignes) rassemblant toutes les classes et interfaces nécessaires à l'existence basique de l'application, le coeur. =]
 

Bartdude

Touriste
ozilrit a dit:
Puis, le coût des inclusions étant ce qu'il est : tentez de créer un fichier global (sans commentaires, ni espaces, ni tabs, ni sauts de lignes) rassemblant toutes les classes et interfaces nécessaires à l'existence basique de l'application, le coeur. =]
OK l'inclusion ca coute, mais bon... aucun commentaire ni rien dans le "coeur" d'une application ? Ca serait pas plus rationnel de "splitter" le code bien documenté et d'inclure uniquement ce dont on a besoin ?

Sinon, chouette article ! J'ai juste une rétiscence sur le "mieux" pour la boucle for. L'exemple ne pourrait pas être plus basique et pourtant je le trouve déjà très peu lisible.

Pour la performance, je te fais confiance... mais très honnêtement ca doit quand-même être chaud de repasser dans ton code après, non ?
 
1er
OP
O

ozilrit

Elite
Il ne sera jamais question d'intervenir sur le fichier coeur. Celui-çi n'est que l'agglomération optimisée d'autres fichiers clairs et documentés (sur lesquels nous travaillons).

Je suis d'accord avec toi, l'accessibilité prime sur les performances.
 

zoheir

cvm.mangaleet()
ozilrit a dit:
J'oubliais : lors du développement, créez une architecture sobre et utile de l'application où chaque fichier est clair et documenté.

- votre-application
- - app
- - - app1
- - - - etc
- - - - model
- - - - view
- - - - controller
- - - - webroot
- - - app2
- - - - etc
- - - - model
- - - - view
- - - - controller
- - - - webroot
- - lib
- - - database
- - - - mysql
- - - - oracle
- - - - firebird
- - - cache
- - - - apc
- - - - memcache
Autant faire du ruby on rails ;-D
 

Ahava

Revenant
quittez Apache. => pour utiliser quoi à la place ?
 
1er
OP
O

ozilrit

Elite
Nginx tiens. =]

N'hésite pas si tu as des questions. :)
 

Ahava

Revenant
ozilrit a dit:
Nginx tiens. =]

N'hésite pas si tu as des questions. :)
Pourrais-tu faire un post là-dessus ? Les avantages par rapport à Apache, la configuration sur serveur web linux, les + de ce serveur web http, configurer php là-dessus, etc. ?
 

Tifox

ou pas
Sympa ce petit rappel, je connaissais pas le truc de la virgule dans le echo ou le for.

Quittez Apache -> Pourquoi ?
 
1er
OP
O

ozilrit

Elite
Ahava : ok. =]

Tifox : voici une raison intéressante :

PHP 5.2.5, quatre requêtes SQL sur Oracle 11g, les sessions sur Memcache, Apc pour précompiler le tout et 15000 requêtes par paquets de 15 via http_load (sur le même réseau).

Moyennes sur dix lancés :
Apache 1.3 et mod_php : 667 requêtes par secondes.
Nginx 0.6 et php-fpm : 3742 requêtes par secondes.​
 

Ahava

Revenant
Merci, je l'attend donc avec impatience :)
 

Tifox

ou pas
ozilrit a dit:
Ahava : ok. =]

Tifox : voici une raison intéressante :

PHP 5.2.5, quatre requêtes SQL sur Oracle 11g, les sessions sur Memcache, Apc pour précompiler le tout et 15000 requêtes par paquets de 15 via http_load (sur le même réseau).

Moyennes sur dix lancés :
Apache 1.3 et mod_php : 667 requêtes par secondes.
Nginx 0.6 et php-fpm : 3742 requêtes par secondes.​
Ah oui, effectivement. Je vais jeter de ce pas un oeil sur ton autre post a ce sujet.

Ceci dit, virer apache, on a pas toujours le choix du serveur :-(
 
1er
OP
O

ozilrit

Elite
La révolution est en marche, notamment parmi quelques grands comptes. =]
 
J'ai bien ri ... Mais avec ton mieux, tu gagnes quoi en réalité dans une situation vraiment réelle ? Je ne te parle pas de "benchmark" à 2 francs sur un million d'itération (ou environ).
 
1er
OP
O

ozilrit

Elite
Rigoler t'empêche sans doute de démontrer.

Je suis ouvert à la critique et au dialogue, fussent-ils utiles et argumentés. Je ne suis pas là pour convaincre les hérétiques.
 

Tifox

ou pas
Même si tu ne gagne pas grand chose, tu gagnes quand même. Et vu que ce qui est proposé n'est pas plus long a coder, autant l'adopter tout de suite.
 

Bartdude

Touriste
Tifox a dit:
Même si tu ne gagne pas grand chose, tu gagnes quand même. Et vu que ce qui est proposé n'est pas plus long a coder, autant l'adopter tout de suite.
N'est pas plus long à coder, comme je disais ca dépend pour quels exemples... Repasser dans son code après un ptit bout de temps, c'est déjà parfois coton, alors dans un code raccourci ainsi au minimum (et parfois de toute facon inapplicable dans une situation concrète), ca doit être beau ! Et le temps de développement coûte quand-même assez cher lui aussi...
 
ozilrit a dit:
Rigoler t'empêche sans doute de démontrer.

Je suis ouvert à la critique et au dialogue, fussent-ils utiles et argumentés. Je ne suis pas là pour convaincre les hérétiques.
Je le prends comme une insulte ou pas ?
Le démontrer ? Euh ... Je te rappelle également que c'est toi qui arrive avec une superbe technique qui va améliorer les temps de réponses.
Pour ma part, en tant qu'hérétique, j'ai déjà lu des benchmarks pour PHP. Et je confirme bien que je rigole ;) On remarque une différence sur un million voire dix millions d'itérations d'une parfois deux secondes. C'est certain que tu codes comme ça. Si oui, l'hérétique, ce n'est pas moi.

Tifox, ce que tu vas "gagner", tu ne le verras pour la plupart du cas jamais. Si tu gagnes un quart de secondes, c'est déjà beaucoup mais tu dois vachement coder comme un pied.

Enfin, bon. L'hérétique vous laisse entre vous.
 

THiBOo

Elite
Certains trucs sont effectivement intéressant, mais il y a un point qui est négligé, c'est la lisibilité du code.
Genre la boucle for là. Ca rend une instruction lisible facilement, totalement illisible. Pour un gain effectivement léger.

La perf c'est bien, mais il ne faut pas négliger l'aspect "maintenance".
 
Statut
N'est pas ouverte pour d'autres réponses.
Haut