Calculer le temps d'exécution en C++

Une solution portable pour calculer le temps d'exécution

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;
}