C++ : time.h

De Wiki de Calcul Québec
Aller à : Navigation, rechercher
Autres langues :anglais 100% • ‎français 100%

C++ : un outil d'analyse de performance basé sur time.h

On peut se servir des fonctions définies dans le fichier d'entête standard <time.h> pour construire un outil d'analyse de performance simple et convivial. Le « chronomètre » défini ci-dessous peut être très utile à qui veut optimiser son programme. Il permet de mesurer le temps passé dans des sections de code choisies.


Fichier : chronometer.cpp
#include <list>
#include <string>
#include <iostream>
#include <time.h>
 
using namespace std;
 
class Chronometer
{
public:
    // ----------------------------------
    // instance methods
    // ----------------------------------
 
    // constructor
    Chronometer(const string& name);
 
    // destructor
    ~Chronometer();
 
    // start measuring time
    inline void Start();
 
    // stop measuring time
    inline void Stop();
 
    // get elapsed time (in seconds)
    double ElapsedTime() const;
 
 
    // ----------------------------------
    // class methods
    // ----------------------------------
 
    // total elapsed time (in seconds) for all chronometers
    static double TotalElapsedTime();
 
    // write report on standard output
    static void Report();
 
private:
    // private data
    clock_t     begin;
    clock_t     total;
    string      name;
    static list<Chronometer*> chronometerList;
};
 
 
// ----------------------------------
// static member initialization
// ----------------------------------
 
list<Chronometer*> Chronometer::chronometerList;
 
 
// ----------------------------------
// method implementations
// ----------------------------------
 
Chronometer::Chronometer(const string& name) : total(0), name(name)
{
    chronometerList.push_back(this);
}
 
Chronometer::~Chronometer()
{
    chronometerList.remove(this);
}
 
void Chronometer::Start()
{
    begin = clock();
}
 
void Chronometer::Stop()
{
    total += clock() - begin;
}
 
double Chronometer::ElapsedTime() const
{
    return (double) total / CLOCKS_PER_SEC;
}
 
double Chronometer::TotalElapsedTime()
{
    double total = 0;
 
    for (list<Chronometer*>::const_iterator i = chronometerList.begin();
         i != chronometerList.end(); ++i)
    {
        total += (*i)->total;
    }
 
    return (double) total / CLOCKS_PER_SEC;
}
 
void Chronometer::Report()
{
    cout << "--------------------------------" << endl;
 
    for (list<Chronometer*>::const_iterator i = chronometerList.begin();
         i != chronometerList.end(); ++i)
    {
        cout << "chronometer " << (*i)->name << ": "
             << (*i)->ElapsedTime()
             << " seconds" << endl;
    }
 
    cout << "--------------------------------" << endl
         << "total = " << TotalElapsedTime()   << endl
         << "--------------------------------" << endl;
}


Les macros ci-dessous permettent d'activer l'analyse de performance seulement lorsque la directive ACTIVATE_CHRONOMETER est définie (il suffit d'ajouter l'option -DACTIVATE_CHRONOMETER dans la ligne de compilation).


Fichier : chronometer.h
#ifdef ACTIVATE_CHRONOMETER
 
#define START_CHRONOMETER(name) static Chronometer name(#name); name.Start();
#define STOP_CHRONOMETER(name) name.Stop();
#define CHRONOMETER_REPORT() Chronometer::Report();
 
#else
 
#define START_CHRONOMETER(name)
#define STOP_CHRONOMETER(name)
#define CHRONOMETER_REPORT()
 
#endif


Voici un exemple d'utilisation :


Fichier : exemple_chronometer.cpp
void function1()
{
    START_CHRONOMETER(function1)
    ...
    STOP_CHRONOMETER(function1)
}
 
void function2()
{
    START_CHRONOMETER(function2)
    ...
    STOP_CHRONOMETER(function2)
}
 
void function3()
{
    START_CHRONOMETER(function3_outer)
    ...
    START_CHRONOMETER(function3_inner)
    ...
    STOP_CHRONOMETER(function3_inner)
    ...
    STOP_CHRONOMETER(function3_outer)
}
 
int main()
{
    for (int i = 1; i < 1000000; ++i)
    {
        function1();
        function2();
        function3();
    }
    CHRONOMETER_REPORT()
}


Sortie :

--------------------------------
chronometer function1: 0.62 seconds
chronometer function2: 0.67 seconds
chronometer function3_outer: 2.06 seconds
chronometer function3_inner: 0.66 seconds
--------------------------------
total = 4.01
--------------------------------

Notez qu'à cause de la déclaration statique des objets Chronometer, cet outil n'est pas fait pour être utilisé dans des fonctions récursives ou sujettes à être appelées par plusieurs fils d'exécution à la fois. Cette stratégie est cependant très performante car on évite de créer un nouveau Chronometer sur la pile chaque fois que le bloc de code en examen est exécuté.

Il faut garder à l'esprit que la mesure du temps prend elle-même du temps. Les résultats seront plus fiables si le bloc d'instructions visé par un chronomètre est très long par rapport à l'opération de mesure.

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager