Aller au contenu

Benchmarking PHP – Partie 3

Voici la suite du premier et du deuxième article de cette série sur les performances de PHP.

PHP est un langage particulièrement permissif et tolérant, qui continue notamment de fonctionner correctement même si une variable n’a pas été définie (à l’exception des propriétés d’objet).
En effet, PHP n’émet qu’un simple avertissement (de type E_NOTICE) dans ces cas-là et continue son exécution normalement.

Le code suivant :

$b = 1 + $a;

produira simplement le message :

Notice: Undefined variable: a in test.php on line 2

La grande tolérance à ce genre d’erreurs de PHP et de mauvaises habitudes de programmation ont entraîné la banalisation de ces messages et il est généralement admis de ne pas en tenir compte. PHP propose en effet de filtrer les messages d’erreur par type. Ainsi, la commande suivante est préconisée par de nombreuses distributions de PHP :

error_reporting(E_ALL ^ E_NOTICE);

Comme son nom l’indique vaguement, cette commande indique à PHP de rapporter toutes les erreurs, à l’exception du type E_NOTICE.

Mais le fait de ne pas rapporter ces erreurs n’a-t-il aucune autre conséquence sur l’exécution de PHP elle-même ?

Etat des lieux

Lorsqu’une erreur est déclenchée dans le code PHP, quel que soit son niveau (et donc y compris pour les erreurs de type E_NOTICE), un appel à la fonction native trigger_error() est exécuté.
Il est de notoriété publique que l’exécution de cette fonction soit lente.

Ne pas rapporter les erreurs concernées entraîne-t-il un gain de temps au niveau de l’exécution ?

Le protocole de test

Pour ce test, j’ai choisi d’exécuter les cas suivants :

  1. ajouter 10 millions de fois la valeur d’une variable non définie,
  2. exécuter la même addition sans rapporter les erreurs au journal global des erreurs de PHP,
  3. exécuter la même addition mais en testant à chaque itération l’existence de la variable,
  4. exécuter l’addition avec une variable définie

Tous les cas ont été exécutés avec la commande :

error_reporting(E_ALL ^ E_NOTICE);

Résultats

Les résultats sont édifiants :

Variable non définie + log des erreurs : 7.55 s
Variable non définie + pas de log des erreurs : 7.29 s
Variable non définie mais testée : 1.08 s
Variable définie : 1.09 s

La conclusion est simple. Les déclenchements de la fonction trigger_error() dans les cas de variables non définies prennent beaucoup de temps. Le code source s’exécute ici 7 fois plus lentement qu’avec une variable dument définie.

PHP incite-t-il au laxisme ?

Mon avis sur la question est tranché : Oui.

En effet, l’autre inconvénient de ne pas rapporter les erreurs de type E_NOTICE est de laisser passer des erreurs parfois dommageables.

L’exemple ci-dessous ne crée aucune erreur "visible" et pourtant n’apporte pas la solution attendue :

error_reporting(E_ALL ^ E_NOTICE);

function valide_si_conforme($txt) {
    return (empty($texte) || preg_match('/^[a-z]+$/', $txt));
}
echo valide_si_conforme('123456789');

En effet, la fonction valide_si_conforme() devrait renvoyer un résultat positif uniquement si le paramètre $txt est vide ou ne contient que des lettres minuscules.

L’appel :

valide_si_conforme('123456789')

devrait renvoyer 0 ou false.

Il n’en est rien et le script renvoie 1 ou true. L’erreur qui inscrit le paramètre $texte en lieu et place de $txt dans l’appel à empty() déclenche une erreur fonctionnelle mais PHP n’en tient pas compte et la détection de ce problème est alors laissée à l’appréciation du développeur. Et si celui-ci n’a pas la discipline ou l’expérience suffisante pour savoir où il faut et où il ne faut pas tester une valeur, de nombreuses erreurs sont susceptibles d’apparaître.

Mais alors que faire ?

La logique voudrait que toutes les erreurs soient rapportées et que les variables soient testées, tant sur leur valeur que sur leur existence.
Cette démarche m’a personnellement évité beaucoup de problèmes par le passé ou permis de corriger bon nombre de bugs dans des codes sources tiers.

Code du test

<?php
    error_reporting(E_ALL ^ E_NOTICE);
    header("Content-Type: text/plain; charset=UTF-8");

    printf("Variable non définie + log des erreurs : ");
    $start = microtime(true);
    $b = 0;
    for ($i = 0; $i < 10000000; $i++)
        $b += $a;
    $elapsed = microtime(true) - $start;
    printf("%0.2f s\n", $elapsed);

    printf("Variable non définie + pas de log des erreurs : ");
    ini_set('log_errors', 0);
    $start = microtime(true);
    $b = 0;
    for ($i = 0; $i < 10000000; $i++)
        $b += $a;
    $elapsed = microtime(true) - $start;
    printf("%0.2f s\n", $elapsed);

    printf("Variable non définie mais testée : ");
    $start = microtime(true);
    $b = 0;
    for ($i = 0; $i < 10000000; $i++) {
        if (isset($a))
            $b += $a;
    }
    $elapsed = microtime(true) - $start;
    printf("%0.2f s\n", $elapsed);

    printf("Variable définie : ");
    $start = microtime(true);
    $b = 0;
    $a = 1;
    for ($i = 0; $i < 10000000; $i++)
        $b += $a;
    $elapsed = microtime(true) - $start;
    printf("%0.2f s\n", $elapsed);
?>

Gratte-ciel – Le Havre, France – Juin 2012

Canon EOS 450D – EFS 55-250 mm – Focale 194 mm – f 29 – 1/30 s – ISO 100

Déferlante – Le Havre, France – Juillet 2012

Canon EOS 450D – EFS 55-250 mm – Focale 250 mm – f 5,6 – 1/800 s – ISO 100

Blanche-Neige et le Chasseur

20120617-230347.jpg

Après l’année 2011 et ses deux Guerres des Boutons, nous avons droit en 2012 à deux nouvelles interprétations du conte de Blanche-Neige. Si beaucoup s’accordent pour dire que le premier menė par Julia Roberts ne marquera pas les esprits, qu’en est-il pour ce Blanche-Neige et le Chasseur un peu plus éloigné de la version originale ?

75 ans après la version animée de Walt Disney parue en 1937, le réalisateur Rupert Sanders signe pour son premier film une version beaucoup plus sombre et épique que l’original, remplie de magie noire et de bons sentiments. Ce mélange à mi-chemin entre Harry Potter et le Prisonnier d’Azkaban et le Seigneur des Anneaux peine cependant à convaincre, tant il a déjà été vu et revu de toutes les bonnes et les mauvaises façons. Et ce n’est pas la principale contradiction du film, bien qu’elle soit une pure question de goût, qui contrebalancera ce fait.

En effet, Blanche-Neige n’est-elle pas censée être "la plus belle entre toutes" ? Mais Kristen Stewart qui joue la jeune princesse ne tient malheureusement pas la comparaison face à Charlize Theron, reine de beauté, qui incarne avec un charisme impressionnant la méchante sorcière. Voilà d’ailleurs la principale qualité et le principal défaut de ce film.

Autour de la prestation de Charlize Theron, le reste de ce long métrage semble bien fade et se cantonne à un classicisme fonctionnel. Kristen Stewart joue à nouveau une adolescente ingénue et impétueuse dont la beauté éclipse la potentielle intelligence. Chris "Thor" Hemsworth se retrouve cantonné quant à lui à son rôle de héros vengeur et pathétique dans lequel on le connaît déjà. Les décors sont certes de qualité mais manquent d’originalité, y compris dans le sanctuaire où les esprits attentifs auront reconnu une forte inspiration du célèbre Princesse Mononoke d’Hayao Miyazaki.

À la question "s’agit-il d’un bon film ?", je répondrai probablement qu’il vaut au moins d’être vu une fois pour la curiosité, mais une projection chez soi en location en vidéo à la demande remplira tout aussi bien son office.

Firefox 13 & SPDY : Quelques Problèmes

La fondation Mozilla a mis en ligne hier, mardi 5 juin 2012, la version 13 de Firefox. Au rang des nouveautés, la prise en charge du protocole SPDY, chargé d’accélérer le chargement des pages.

Malheureusement, sur mon ordinateur, avec certains sites comme la version américaine du moteur de recherche Google (pourtant à l’origine du protocole), le chargement des pages est considérablement ralentie, voire impossible. Bien évidemment, avec la prise en charge du protocole désactivée, la navigation revient à la normale.

Ci-dessous, retrouvez la procédure pour désactiver le protocole SPDY :

  • Rendez-vous dans Firefox, dans une nouvelle fenêtre ou un nouvel onglet, à l’adresse about:config
  • Si un avertissement de sécurité s’affiche, prenez en connaissance et validez
  • Recherchez la clé network.http.spdy.enabled
  • Si sa valeur est à true, double-cliquez dessus pour la faire passer à false

Voilà, votre navigation devrait être à nouveau fluide comme à son habitude.

AirPrint sans imprimante compatible

Lors de la publication d’iOS 4.2, Apple a ajouté à son système d’exploitation mobile la fonctionnalité AirPrint permettant d’imprimer des documents directement depuis son iPhone, son iPod ou son iPad.

Malheureusement, l’écosystème Apple étant ce qu’il est, cette fonctionnalité fut bridée à la dernière minute à une poignée d’imprimantes compatibles, initialement chez HP, puis désormais chez Epson, Canon, Lexmark et Brother (voir liste des imprimantes compatibles). Il était donc initialement impossible d’imprimer sur sa basique petite imprimante, bien que partagée sur le réseau au travers d’un Mac.

Jusqu’à ce que de gentils développeurs mettent en place des méthodes de contournement et activent AirPlay non pas sur les imprimantes mais directement sur nos Mac, qui permettent donc désormais d’utiliser les imprimantes qui leur sont connectées.

J’utilise pour ma part AirPrint Activator 2 qui fonctionne très bien sous OS X Lion, bien qu’en bêta.

Le Chemin des Philosophes – Kyoto, Japon – Octobre 2009

Canon EOS 450D – EFS 18-55 mm – Focale 39 mm – f 5,6 – 1/30 s – ISO 100

Termites – Le Boucanet, France – Mars 2012

Canon EOS 450D – EFS 18-55 mm – Focale 55 mm – f 5,6 – 1/125 s – ISO 100

Berges de la Garonne – Toulouse, France – Septembre 2009

Canon EOS 450D – EFS 18-55 mm – Focale 55 mm – f 5,6 – 1/250 s – ISO 200

Fontaine de purification – Takayama (高山), Japon – Octobre 2009

Canon EOS 450D – EFS 18-55 mm – Focale 41 mm – f 5,6 – 1/100 s – ISO 400

Suivre

Recevez les nouvelles publications par mail.

Joignez-vous à 184 followers