/*---------------------------------------------------------------*/
|
/*
|
Titre : Calcul le temps d'exécution d'un script PHP
|
|
URL : https://phpsources.net/code_s.php?id=139
|
Auteur : Eric Potvin
|
Date édition : 23 Sept 2005
|
Date mise a jour : 24 Aout 2019
|
|
Rapport de la maj:
|
- fonctionnement du code vérifié
|
Date mise a jour : 15 Fev 2026
|
|
Rapport de la maj:
|
- refactoring du code en PHP 8
|
*/
|
/*---------------------------------------------------------------*/
|
|
declare(strict_types=1);
|
|
/**
|
* Classe moderne pour mesurer le temps d'exécution en PHP 8.3+
|
*
|
* Améliorations par rapport à l'ancienne méthode :
|
* - Utilisation de hrtime() (nanoseconde) au lieu de microtime()
|
* - Typed properties et return types
|
* - Support de multiples timers simultanés
|
* - Format de sortie flexible
|
* - Precision configurable
|
*/
|
class ExecutionTimer
|
{
|
private array $timers = [];
|
private array $results = [];
|
|
/**
|
* Démarre un timer
|
*/
|
public function start(string $name = 'default'): void
|
{
|
$this->timers[$name] = hrtime(true);
|
}
|
|
/**
|
* Arrête un timer et retourne le temps écoulé
|
*
|
* @return float Temps en secondes
|
*/
|
public function stop(string $name = 'default'): float
|
{
|
if (!isset($this->timers[$name])) {
|
throw new RuntimeException("Timer '$name' n'a pas été démarré");
|
}
|
|
$elapsed = (hrtime(true) - $this->timers[$name]) / 1_000_000_000;
|
$this->results[$name] = $elapsed;
|
unset($this->timers[$name]);
|
|
return $elapsed;
|
}
|
|
/**
|
* Obtient le temps écoulé sans arrêter le timer
|
*/
|
public function elapsed(string $name = 'default'): float
|
{
|
if (!isset($this->timers[$name])) {
|
throw new RuntimeException("Timer '$name' n'a pas été démarré");
|
}
|
|
return (hrtime(true) - $this->timers[$name]) / 1_000_000_000;
|
}
|
|
/**
|
* Formate le temps en unité appropriée
|
*/
|
public function format(float $seconds, int $precision = 4): string
|
{
|
return match (true) {
|
$seconds < 0.000001 => round($seconds * 1_000_000_000, $precision) .
|
' ns',
|
$seconds < 0.001 => round($seconds * 1_000_000, $precision) . ' ?s',
|
$seconds < 1 => round($seconds * 1000, $precision) . ' ms',
|
$seconds < 60 => round($seconds, $precision) . ' s',
|
default => sprintf('%d min %0.2f s', floor($seconds / 60), $seconds
|
% 60)
|
};
|
}
|
|
/**
|
* Obtient tous les résultats enregistrés
|
*/
|
public function getResults(): array
|
{
|
return $this->results;
|
}
|
|
/**
|
* Affiche un résumé formaté
|
*/
|
public function displaySummary(): void
|
{
|
echo "\n" . str_repeat('=', 60) . "\n";
|
echo "RÉSUMÉ DES TEMPS D'EXÉCUTION\n";
|
echo str_repeat('=', 60) . "\n";
|
|
foreach ($this->results as $name => $time) {
|
printf("%-30s : %s\n", $name, $this->format($time));
|
}
|
|
echo str_repeat('=', 60) . "\n\n";
|
}
|
}
|
|
// ============================================
|
// EXEMPLES D'UTILISATION
|
// ============================================
|
|
// Exemple 1 : Usage basique (ancien vs nouveau)
|
echo "=== EXEMPLE 1 : Usage Basique ===\n\n";
|
|
// ? ANCIEN CODE (microtime)
|
echo "Ancienne méthode (microtime) :\n";
|
$start_old = microtime(true);
|
sleep(1);
|
$end_old = microtime(true);
|
$execution_time_old = $end_old - $start_old;
|
echo "Temps : " . round($execution_time_old, 4) . " secondes\n\n";
|
|
// ? NOUVEAU CODE (hrtime)
|
echo "Nouvelle méthode (hrtime) :\n";
|
$timer = new ExecutionTimer();
|
$timer->start();
|
sleep(1);
|
$time = $timer->stop();
|
echo "Temps : " . $timer->format($time) . "\n\n";
|
|
|
// Exemple 2 : Multiples timers simultanés
|
echo "=== EXEMPLE 2 : Multiples Timers ===\n\n";
|
|
$timer = new ExecutionTimer();
|
|
$timer->start('boucle_1');
|
for ($i = 0; $i < 1000000; $i++) {
|
// Opération simple
|
}
|
$timer->stop('boucle_1');
|
|
$timer->start('boucle_2');
|
for ($i = 0; $i < 1000000; $i++) {
|
$x = $i * 2;
|
}
|
$timer->stop('boucle_2');
|
|
$timer->start('base_donnees_simulation');
|
usleep(5000); // Simule une requête DB
|
$timer->stop('base_donnees_simulation');
|
|
$timer->displaySummary();
|
|
|
// Exemple 3 : Mesure pendant l'exécution
|
echo "=== EXEMPLE 3 : Mesure en Temps Réel ===\n\n";
|
|
$timer = new ExecutionTimer();
|
$timer->start('longue_tache');
|
|
for ($i = 1; $i <= 5; $i++) {
|
usleep(200000); // 200ms
|
echo "Étape $i/5 - Temps écoulé : " . $timer->format($timer->elapsed(
|
'longue_tache')) . "\n";
|
}
|
|
$timer->stop('longue_tache');
|
echo "\n";
|
|
|
// Exemple 4 : Fonction helper simple
|
echo "=== EXEMPLE 4 : Fonction Helper ===\n\n";
|
|
/**
|
* Fonction helper pour mesurer rapidement une fonction
|
*/
|
function mesurer_execution(callable $fonction, string $nom = 'fonction'): float
|
|
{
|
$start = hrtime(true);
|
$fonction();
|
$elapsed = (hrtime(true) - $start) / 1_000_000_000;
|
|
$timer = new ExecutionTimer();
|
echo "$nom : " . $timer->format($elapsed) . "\n";
|
|
return $elapsed;
|
}
|
|
mesurer_execution(function() {
|
for ($i = 0; $i < 500000; $i++) {
|
$x = sqrt($i);
|
}
|
}, 'Calcul racine carrée');
|
|
|
// Exemple 5 : Comparaison de performances
|
echo "\n=== EXEMPLE 5 : Comparaison d'Algorithmes ===\n\n";
|
|
function bubble_sort(array $arr): array {
|
$n = count($arr);
|
for ($i = 0; $i < $n - 1; $i++) {
|
for ($j = 0; $j < $n - $i - 1; $j++) {
|
if ($arr[$j] > $arr[$j + 1]) {
|
[$arr[$j], $arr[$j + 1]] = [$arr[$j + 1], $arr[$j]];
|
}
|
}
|
}
|
return $arr;
|
}
|
|
$data = range(1, 100);
|
shuffle($data);
|
|
$timer = new ExecutionTimer();
|
|
// Test 1 : Bubble sort
|
$data_copy = $data;
|
$timer->start('bubble_sort');
|
bubble_sort($data_copy);
|
$timer->stop('bubble_sort');
|
|
// Test 2 : sort() natif
|
$data_copy = $data;
|
$timer->start('sort_natif');
|
sort($data_copy);
|
$timer->stop('sort_natif');
|
|
$timer->displaySummary();
|
|
// Calcul du gain
|
$bubble_time = $timer->getResults()['bubble_sort'];
|
$native_time = $timer->getResults()['sort_natif'];
|
$gain = ($bubble_time / $native_time);
|
echo "Le sort() natif est " . round($gain, 1) . "x plus rapide !\n\n";
|
|
|
// Exemple 6 : Classe avec auto-timer (pattern decorator)
|
echo "=== EXEMPLE 6 : Auto-Timer (Avancé) ===\n\n";
|
|
/**
|
* Trait pour ajouter automatiquement un timer à n'importe quelle méthode
|
*/
|
trait TimedExecution
|
{
|
private static ExecutionTimer $globalTimer;
|
|
public static function initTimer(): void
|
{
|
self::$globalTimer = new ExecutionTimer();
|
}
|
|
protected function timed(string $name, callable $callback): mixed
|
{
|
if (!isset(self::$globalTimer)) {
|
self::initTimer();
|
}
|
|
self::$globalTimer->start($name);
|
$result = $callback();
|
$time = self::$globalTimer->stop($name);
|
|
echo "?? $name : " . self::$globalTimer->format($time) . "\n";
|
|
return $result;
|
}
|
}
|
|
class DataProcessor
|
{
|
use TimedExecution;
|
|
public function process(array $data): array
|
{
|
return $this->timed('Traitement des données', function() use ($data) {
|
// Simulation traitement
|
usleep(100000);
|
return array_map(fn($x) => $x * 2, $data);
|
});
|
}
|
|
public function validate(array $data): bool
|
{
|
return $this->timed('Validation', function() use ($data) {
|
usleep(50000);
|
return count($data) > 0;
|
});
|
}
|
}
|
|
$processor = new DataProcessor();
|
$result = $processor->process([1, 2, 3, 4, 5]);
|
$valid = $processor->validate($result);
|
|
echo "\n";
|
|
| ?> |
Fabien
31 Déc 2005 à 12:16Ce script est simple mais efficace.
Merci à l'auteur, je vais l'utilisé pour mon TPE.
Je n'oublie pas de le cité bien sure.