Calculer le temps d’exécution
Très souvent, on est amené à calculer le temps mis par une fonction ou un morceau de code. De nombreuses méthodes différentes existent pour arriver à ce but, mais toutes ne sont pas fiables ou précises.
Linux
Sous Linux, il est généralement conseillé d’utiliser gettimeofday (précision à la microseconde). Il existe aussi clock(), mais celle-ci est peu précise (précision à la milliseconde).
Windows
Sous Windows, il est généralement conseillé d’utiliser QueryPerformanceCounter précision à la microseconde). Il existe aussi GetTickCount(), mais celle-ci est peu précise (précision à la milliseconde).
Une classe multiplateforme
Je vous propose une classe qui fonctionne aussi bien sous Linux que sous Windows. Celle-ci est facilement utilisable et se sert de la notion de scope pour effectuer automatiquement le calcul.
ElapsedTime.hh:
#ifndef ELAPSEDTIME_HH_
# define ELAPSEDTIME_HH_
# ifdef WIN32
# include <windows.h>
# else
# include <ctime>
# include <sys/time.h>
# endif
class ElapsedTime
{
public:
ElapsedTime()
{
}
~ElapsedTime()
{
}
void start()
{
# ifdef WIN32
QueryPerformanceFrequency(&_procFreq);
QueryPerformanceCounter(&_begin);
# else
gettimeofday(&_begin, &_tz);
# endif
}
void stop()
{
# ifdef WIN32
QueryPerformanceCounter(&_end);
_time = double(_end.QuadPart - _begin.QuadPart) / (_procFreq.QuadPart / 1000000.0);
# else
gettimeofday(&_end, &_tz);
_time = (_end.tv_sec - _begin.tv_sec) *
1000000L + (_end.tv_usec - _begin.tv_usec);
# endif
}
long getElapsedTime() const
{
return _time;
}
private:
long _time;
# ifdef WIN32
LARGE_INTEGER _begin, _end;
LARGE_INTEGER _procFreq;
# else
struct timeval _begin, _end;
struct timezone _tz;
# endif
};
#endif /* !ELAPSEDTIME_HH_ */
ScopeElapsedTime.hh:
#ifndef SCOPEELAPSEDTIME_HH_
# define SCOPEELAPSEDTIME_HH_
# include <iostream>
# include <sstream>
# include "ElapsedTime.hh"
class ScopeElapsedTime
{
public:
ScopeElapsedTime()
: _origin("")
{
_elapsedTime.start();
}
ScopeElapsedTime(const std::string& origin)
: _origin(origin)
{
_elapsedTime.start();
}
~ScopeElapsedTime()
{
_elapsedTime.stop();
std::ostringstream buff;
if (!_origin.empty())
buff << "[" << _origin << "]";
buff << "Elapsed time: " << _elapsedTime.getElapsedTime()
<< " us" << std::endl;
std::cout << buff.str();
}
private:
std::string _origin;
ElapsedTime _elapsedTime;
};
#endif /* !SCOPEELAPSEDTIME_HH_ */
Et voici un exemple d’utilisation.
main.cc:
#include <iostream>
#include "ScopeElapsedTime.hh"
namespace Toto
{
void fonction()
{
ScopeElapsedTime timer("Fonction");
}
void autreFonction()
{
ScopeElapsedTime timer("AutreFonction");
}
void test()
{
ScopeElapsedTime timer("Application");
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
{
ScopeElapsedTime timer2("Les Deux");
fonction();
autreFonction();
}
fonction();
}
}
int main()
{
test();
#ifdef WIN32
system("pause");
#endif
return 0;
}