Une petite classe qui permet de comparer le temps d'exécution de plusieurs fonctions... je m'en sert pour tout ce que je fais, pour optimiser le code.
Elle n'est pas vraiment compliquée, mais super pratique !
Source / Exemple :
<?php
class Bench {
/** Tableaux ayant pour clés les noms de fonctions, et pour valeurs les temps, initialisées à 0 */
private $fcts;
/** Arguments à passer aux fonctions */
private $args;
/**
- Constructeur, initialise les tableaux.
- /
function __construct() {
$this->fcts = array();
$this->args = array();
}
/**
- Charge les fonctions passées en argument
- @return l'objet ($this)
- /
function load() {
foreach(func_get_args() as $cfct)
$this->fcts[$cfct] = 0;
return $this;
}
/**
- Enregistre les arguments des fonctions
- /
function args() {
$this->args = func_get_args();
return $this;
}
/**
- Commence un benchmark.
- @arg $max : nombre de récursions
- @arg $print : affiche le résultat, par défaut à true
- @arg $autocompare : compare automatiquement les résultats des fonctions, par défaut à true
- @return l'objet ($this)
- /
function start($max, $print = true, $autocompare = true) {
if($autocompare)
$this->compare($print);
foreach($this->fcts as $fct => $t) {
$n = $max;
$time = &$this->fcts[$fct];
$start = microtime(true);
while($n-- > 0) call_user_func_array($fct, $this->args);
$time = microtime(true) - $start;
if($print) {
echo $fct.' : '.$time.'s<br />';
flush();
}
}
return $this;
}
/**
- Compare les résultats des fonctions avec la première.
- @arg $print : affiche un message d'avertissement si ce n'est pas les mêmes valeurs, par défaut à true
- @return le nom de la fonction qui ne retourne pas la même chose, sinon null
- /
function compare($print = true) {
$first = true;
reset($this->fcts);
foreach($this->fcts as $fct => $t) {
$nout = call_user_func_array($fct, $this->args);
if($first) {
$out = $nout;
$first = false;
}
else if( $out !== $nout ) {
if($print) {
echo 'Attention, différence entre les valeurs de retours des deux fonctions.<br />Valeur de retour de la fonction '.key($this->fcts).' : <pre>';
var_dump($out);
echo '</pre>Valeur de retour de la fonction '.$fct.' : <pre>';
var_dump($nout);
echo '</pre>';
flush();
}
return $fct;
}
}
return null;
}
/**
- Retourne le temps mit par une fonction. Si aucun argument n'est spécifié, il retournera le temps mit par la première fonction, puis la suivante, etc...
- @arg $n : nom de la fonction
- @return le temps mis par une fonction, false si il n'y a plus de fonction ou si la fonction n'est pas trouvée.
- /
function getTime($n = NULL) {
if($n === NULL) {
$t = current($this->fcts);
if($t !== false) next($this->fcts);
}
else {
if(!isset($this->fcts[$n])) $t = false;
else $t = $this->fcts[$n];
}
return $t;
}
}
/*********
Exemple d'utilisation :
Comparaison entre deux fonction qui test si une chaîne ne contient que des caractères minuscules/majuscules, et les caractères ' ', '_', '.', '-'
L'une utilise une méthode un peu 'naïve' en testant la valeur ascii de chaque caractères, l'autre utilisera une expression rationnelle
/* première fonction */
function bmtest($s) {
$res = true;
$j = 0;
while($res && $j < strlen($s)) {
$tmp = ord($s[$j]);
$res = ($tmp > 44 && $tmp < 58 && $tmp != 47)
|| ($tmp > 64 && $tmp < 91)
|| ($tmp > 94 && $tmp < 123 && $tmp != 96)
|| ($tmp == 32);
$j++;
}
return $res;
}
/* deuxième fonction */
function bmtestpreg($str) {
return preg_match('`[^-.0-9A-Za-z_ ]`', $str) == 0;
}
$t = new Bench();
$t->load('bmtest', 'bmtestpreg');
echo 'Benchmark avec une chaîne qui concorde<br />';
$t->args('azeazepfsdpog')->start(10000);
echo 'Benchmark avec une chaîne qui ne concorde pas<br />';
$t->args('plsdfé"sdf')->start(10000);
/*
Affiche :
Benchmark avec une chaîne qui concorde
bmtest : 0.381120920181s
bmtestpreg : 0.0587420463562s
Benchmark avec une chaîne qui ne concorde pas
bmtest : 0.196413040161s
bmtestpreg : 0.0624430179596s
On aurait aussi pu afficher le résultat comme cela :
echo $t->getTime().'<br />'.$t->getTime();
ou bien :
echo $t->getTime('bmtest').'<br />'.$t->getTime('bmtestpreg');
?>
Conclusion :
La classe est pas mal commentée avec des exemples, je pense que vous vous y retrouverez !
Si il y a des questions, n'hésitez pas, je serais heureux d'y répondre...
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.