Learn-to-Compress / headers / ztimer.h
ztimer.h
Raw
/**
 * This code is released under the
 * Apache License Version 2.0 http://www.apache.org/licenses/.
 */

#ifndef ZTIMER
#define ZTIMER

#include "common.h"

namespace FastPForLib {

//
// VS2012 bug: high_precision_clock is defined as system_clock and precision is
// about 15 MS!!
// See: https://connect.microsoft.com/VisualStudio/feedback/details/719443
//
// Implementation has been taken from a post on stackoverflow and adapted here
// http://stackoverflow.com/questions/13263277/difference-between-stdsystem-clock-and-stdsteady-clock
//
#ifdef _WIN32
#define NOMINMAX
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>

struct qpc_clock {
  typedef std::chrono::nanoseconds duration;
  typedef duration::rep rep;
  typedef duration::period period;
  typedef std::chrono::time_point<qpc_clock, duration> time_point;
  static time_point now() {
    static bool isInited = false;
    static LARGE_INTEGER frequency = {0, 0};
    if (!isInited) {
      if (QueryPerformanceFrequency(&frequency) == 0) {
        throw std::logic_error("QueryPerformanceCounter not supported: " +
                               std::to_string(GetLastError()));
      }
      isInited = true;
    }
    LARGE_INTEGER counter;
    QueryPerformanceCounter(&counter);
    return time_point(duration(static_cast<rep>((double)counter.QuadPart /
                                                frequency.QuadPart *
                                                period::den / period::num)));
  }
};

#endif

/**
 *  author: Preston Bannister
 */
class WallClockTimer {
public:
#ifdef _WIN32
  typedef qpc_clock clock;
#else
  typedef std::chrono::high_resolution_clock clock;
#endif

  std::chrono::time_point<clock> t1, t2;
  WallClockTimer() : t1(), t2() {
    t1 = clock::now();
    t2 = t1;
  }
  void reset() {
    t1 = clock::now();
    t2 = t1;
  }
  uint64_t elapsed() {
    std::chrono::microseconds delta =
        std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
    return delta.count();
  }
  uint64_t split() {
    t2 = clock::now();
    return elapsed();
  }
};

#ifndef _WIN32

class CPUTimer {
public:
  // clock_t t1, t2;
  struct rusage t1, t2;

  CPUTimer() : t1(), t2() {
    getrusage(RUSAGE_SELF, &t1);
    // t1 = clock();
    t2 = t1;
  }
  void reset() {
    getrusage(RUSAGE_SELF, &t1);
    t2 = t1;
  }
  // proxy for userelapsed
  uint64_t elapsed() { return totalelapsed(); }

  uint64_t totalelapsed() { return userelapsed() + systemelapsed(); }
  // returns the *user* CPU time in micro seconds (mu s)
  uint64_t userelapsed() {
    return ((t2.ru_utime.tv_sec - t1.ru_utime.tv_sec) * 1000ULL * 1000ULL) +
           ((t2.ru_utime.tv_usec - t1.ru_utime.tv_usec));
  }

  // returns the *system* CPU time in micro seconds (mu s)
  uint64_t systemelapsed() {
    return ((t2.ru_stime.tv_sec - t1.ru_stime.tv_sec) * 1000ULL * 1000ULL) +
           ((t2.ru_stime.tv_usec - t1.ru_stime.tv_usec));
  }

  uint64_t split() {
    getrusage(RUSAGE_SELF, &t2);
    return elapsed();
  }
};

#endif

} // namespace FastPFor

#endif