Optimisation des performances des applications PHP
Le plus grand avantage de la programmation en PHP est la facilité avec laquelle il est possible d’apprendre ce langage de programmation et ses riches bibliothèques. Même si nous ne savons pas grand-chose sur les fonctions que nous devons utiliser, nous pouvons deviner comment accomplir une tâche spécifique.
Bien que PHP soit très simple et facile à apprendre, nous devons encore passer un peu de temps à apprendre certaines compétences en programmation PHP, notamment celles liées aux performances et à l’utilisation de la mémoire. En PHP, il existe de nombreuses astuces qui nous permettent de réduire l’utilisation de la mémoire et d’améliorer les performances des applications. Dans cet article, nous présenterons brièvement l'analyse des applications PHP, comment modifier le code du script et comparerons diverses valeurs de paramètres avant et après l'optimisation.
En définissant des procédures de synchronisation dans le programme et en exécutant ces codes à plusieurs reprises, nous pouvons obtenir un ensemble de données sur la vitesse d'exécution du programme. Ces données peuvent être utilisées pour découvrir les goulots d'étranglement dans le programme et comment l'optimiser pour améliorer les performances du programme. application.
Peut-être que les lecteurs ont entendu parler de la bibliothèque PEAR. Nous utiliserons la bibliothèque PEAR pour créer des exemples que nous devons utiliser lors de l'analyse. C'est également le moyen le plus simple d'analyser le code existant. Cela nous permet d'analyser le code sans utiliser de produits commerciaux.
Le nom de la bibliothèque que nous allons utiliser est PEAR::Benchmark et elle est très utile pour le profilage et les tests de performances du code. Cette bibliothèque fournit une classe nommée Benchmark_Timer(), qui peut enregistrer le temps entre un appel de fonction et le prochain appel de fonction. Lors du test des performances du code, nous pouvons obtenir un résultat détaillé de l’exécution du script, qui est très simple, comme suit :
include_once("Benchmark/Timer.php");
$bench = nouveau Benchmark_Timer ;
$banc->start();
$bench-> setMarker('Début du script');
// Maintenant en état de veille pendant quelques minutes
dormir(5);
$banc->stop();
// Récupère les informations d'analyse du minuteur
print_r($bench->getProfiling());
?>
Le résultat après exécution du code ci-dessus est le suivant :
Tableau
(
[0] => Tableau
(
[nom] => Démarrer
[heure] => 1013214253.05751200
[diff] => -
[total] => 0
)
[1] => Tableau
(
[nom] => Début du script
[heure] => 1013214253.05761100
[diff] => 9.8943710327148E-05
[total] => 9.8943710327148E-05
)
[2] => Tableau
(
[nom] => Arrêter
[heure] => 1013214258.04920700
[diff] => 4.9915959835052
[total] => 4,9916949272156
)
)
Les nombres ci-dessus peuvent ressembler à un ensemble de nombres disjoints, mais si la taille du programme est plus grande, ces nombres peuvent être très utiles.
Peut-être que la majorité des lecteurs peuvent également deviner que la première entrée du tableau est la méthode réelle d'appel de la classe Benchmark_Timer(), par exemple
$bench->start(), $bench->setMarker() et $bench->stop() Les nombres associés à ces entrées sont assez simples. Examinons maintenant de plus près ces nombres :
[0] => Tableau
(
[nom] => Démarrer
[heure] => 1013214253.05751200
[diff] => -
[total] => 0
)
L'entrée de temps fait référence à l'horodatage UNIX lorsque la méthode start() de Benchmark_Timer() est appelée. L'entrée diff indique l'intervalle de temps entre cet appel et le dernier appel. Puisqu'il n'y a pas d'appel précédent ici, un tiret, l'entrée totale. fait référence à la durée totale d'exécution du code depuis le début du test jusqu'à cet appel particulier. Jetons un coup d'œil à la sortie du tableau suivant :
[1] => Tableau
(
[nom] => Début du script
[heure] => 1013214253.05761100
[diff] => 9.8943710327148E-05
[total] => 9.8943710327148E-05
)
D'après les chiffres ci-dessus, nous pouvons voir qu'après avoir appelé $bench->start(), le programme s'exécute pendant 9,8943710327148E-05 secondes (soit 0,0000989 secondes) avant d'appeler $bench->setMarker(….).
Une véritable expérience de test de performances
Bien que l'exemple ci-dessus soit bon, ce n'est vraiment pas un bon exemple pour décider comment optimiser la conception du code de votre site. Ci-dessous, j'utiliserai ma propre expérience personnelle en tant que technicien de site Web pour illustrer comment résoudre les problèmes de performances.
Je ne comprends pas vraiment le code utilisé par le site Web, car il a été développé sur de nombreuses années en fonction de besoins spécifiques : un module contient le code de conversion du site Web, un autre module enregistre l'utilisation du site Web et les autres modules ont leur propre code. rôle de chacun. Le développeur principal du site Web et moi-même avons réalisé que le code du site Web devait être optimisé, mais nous ne savions pas quel était le problème.
Afin de terminer la tâche le plus rapidement possible, j'ai commencé à étudier le code de script principal du site Web, et j'ai ajouté quelques commandes $bench->setMarker() à tous les codes de script et leurs fichiers inclus, puis j'ai analysé la sortie de $bench ->getProfiling(), et j'ai été surpris par les résultats. Il s'est avéré que le problème résidait dans un appel de fonction lié au code de conversion pour obtenir un nom de langue spécifique (comme en pour l'anglais), qui a été utilisé des centaines de fois. sur chaque page. Chaque fois que cette fonction est appelée, le code du script interroge une base de données MySQL pour obtenir le nom réel de la langue à partir d'une table de base de données.
Nous créons donc un système tampon pour ce type d’informations. Après seulement 2 jours de travail, nous avons considérablement amélioré les performances du système et le nombre de pages vues a augmenté de 40 % au cours de la première semaine. Bien entendu, ce n’est là qu’un exemple de la manière dont l’analyse du code peut améliorer les performances d’une application Internet ou d’un site Web Internet.
Appel de fonction de test de performances
Bien que Benchmark_Timer() soit particulièrement utile lors de l'analyse d'un script ou d'une page Web (et des fichiers qu'il contient), ce n'est pas scientifique car il faut charger le script plusieurs fois pour obtenir les données analysées, et ce n'est pas spécifique à une certaine classe ou fonction. . appelé.
Une autre classe de la bibliothèque PEAR::Benchmark appelée Benchmark_Iterator peut très bien résoudre ce problème. Elle peut afficher des informations d'analyse pour une fonction ou une méthode de classe spécifique. Son objectif est de pouvoir obtenir des résultats cohérents à partir des tests, car nous savons que si nous exécutons un script une fois et que son exécution prend 10 secondes, cela ne signifie pas qu'il faudra toujours 10 secondes pour s'exécuter à chaque fois.
Dans tous les cas, voyons quelques exemples :
// Code pour se connecter à la base de données
include_once("DB.php");
$dsn = tableau(
'phptype' => 'mysql',
'hostspec' => 'localhost',
'base de données' => 'nom_base de données',
'nom d'utilisateur' => 'nom_utilisateur',
'mot de passe' => 'mot de passe'
);
$dbh = DB::connect($dsn);
fonction getCreatedDate($id)
{
global $dbh ;
> $stmt = "SELECT create_date FROM utilisateurs WHERE id=$id";
// Utilisez PEAR::DB ici
$created_date = $dbh-> getOne($stmt);
if ((PEAR::isError($created_date)) ||
(vide ($ date_créée))) {
renvoie faux ;
} autre {
renvoie $created_date ;
}
}
include_once 'Benchmark/Iterate.php';
$bench = nouveau Benchmark_Iterate ;
//Exécutez la fonction getDate 10 fois
$bench-> run(10, 'getCreatedDate', 1);
//Imprimer les informations d'analyse
print_r($bench->get());
?>
L'exécution du code ci-dessus produit des résultats similaires aux suivants :
Tableau
(
[1] => 0,055413007736206
[2] => 0,0012860298156738
[3] => 0,0010279417037964
[4] => 0,00093603134155273
[5] => 0,00094103813171387
[6] => 0,00092899799346924
[7] => 0,0010659694671631
[8] => 0,00096404552459717
[9] => 0,0010690689086914
[10] => 0,00093603134155273
[moyenne] => 0,0064568161964417
[itérations] => 10
)
Les nombres ci-dessus sont faciles à comprendre. L'entrée moyenne représente la durée moyenne de 10 exécutions de la fonction getCreatedDate(). Lors de tests réels, vous devez l'exécuter au moins 1 000 fois, mais les résultats de cet exemple suffisent à illustrer le problème.