Program Listing for File statistics.h

Return to documentation for file (aslam_cv2/aslam_cv_common/include/aslam/common/statistics/statistics.h)


#include <chrono>
#include <map>
#include <mutex>
#include <string>
#include <vector>

#include "aslam/common/statistics/accumulator.h"

// Example usage:
// #define ENABLE_STATISTICS 1 // Turn on/off the statistics calculation
// #include <aslam/common/statistics/statistics.h>
// double my_distance = measureDistance();
// statistics::DebugStatsCollector distance_stat("Distance measurement");
// distance_stat.AddSample(my_distance);
// std::cout << statistics::Statistics::Print();

namespace statistics {

const double kNumSecondsPerNanosecond = 1.e-9;

struct StatisticsMapValue {
  static const int kWindowSize = 100;

  inline StatisticsMapValue()
      : time_last_called_(std::chrono::system_clock::from_time_t(0)),
        epoch_clock_(std::chrono::system_clock::from_time_t(0)) {}

  inline void AddValue(double sample) {
    std::chrono::time_point<std::chrono::system_clock> now =

    // Only calculate delta time if it has been called before.
    if (time_last_called_ != epoch_clock_) {
      double dt = static_cast<double>(
                          now - time_last_called_)
                          .count()) *

    time_last_called_ = now;
  inline double GetLastDeltaTime() const {
    if (time_deltas_.total_samples()) {
      return time_deltas_.GetMostRecent();
    } else {
      return 0;
  inline double GetLastValue() const {
    if (values_.total_samples()) {
      return values_.GetMostRecent();
    } else {
      return 0;
  inline double Sum() const {
    return values_.sum();
  int TotalSamples() const {
    return values_.total_samples();
  double Mean() const {
    return values_.Mean();
  double RollingMean() const {
    return values_.RollingMean();
  double Max() const {
    return values_.max();
  double Min() const {
    return values_.min();
  double LazyVariance() const {
    return values_.LazyVariance();
  double MeanCallsPerSec() const {
    double mean_dt = time_deltas_.Mean();
    if (mean_dt != 0) {
      return 1.0 / mean_dt;
    } else {
      return -1.0;

  double MeanDeltaTime() const {
    return time_deltas_.Mean();
  double RollingMeanDeltaTime() const {
    return time_deltas_.RollingMean();
  double MaxDeltaTime() const {
    return time_deltas_.max();
  double MinDeltaTime() const {
    return time_deltas_.min();
  double LazyVarianceDeltaTime() const {
    return time_deltas_.LazyVariance();

  // Create an accumulator with specified window size.
  Accumulator<double, double, kWindowSize> values_;
  Accumulator<double, double, kWindowSize> time_deltas_;
  std::chrono::time_point<std::chrono::system_clock> time_last_called_;
  std::chrono::time_point<std::chrono::system_clock> epoch_clock_;

// A class that has the statistics interface but does nothing. Swapping this in
// in place of the Statistics class (say with a typedef) eliminates the function
// calls.
class DummyStatsCollector {
  explicit DummyStatsCollector(size_t /*handle*/) {}
  explicit DummyStatsCollector(std::string const& /*tag*/) {}
  void AddSample(double /*sample*/) const {}
  void IncrementOne() const {}
  size_t GetHandle() const {
    return 0u;

class StatsCollectorImpl {
  explicit StatsCollectorImpl(size_t handle);
  explicit StatsCollectorImpl(std::string const& tag);
  ~StatsCollectorImpl() = default;

  void AddSample(double sample) const;
  void IncrementOne() const;
  size_t GetHandle() const;

  size_t handle_;

class Statistics {
  typedef std::map<std::string, size_t> map_t;
  friend class StatsCollectorImpl;
  // Definition of static functions to query the stats.
  static size_t GetHandle(std::string const& tag);
  static bool HasHandle(std::string const& tag);
  static std::string GetTag(size_t handle);
  static double GetLastValue(size_t handle);
  static double GetLastValue(std::string const& tag);
  static double GetTotal(size_t handle);
  static double GetTotal(std::string const& tag);
  static double GetMean(size_t handle);
  static double GetMean(std::string const& tag);
  static size_t GetNumSamples(size_t handle);
  static size_t GetNumSamples(std::string const& tag);
  static double GetVariance(size_t handle);
  static double GetVariance(std::string const& tag);
  static double GetMin(size_t handle);
  static double GetMin(std::string const& tag);
  static double GetMax(size_t handle);
  static double GetMax(std::string const& tag);
  static double GetHz(size_t handle);
  static double GetHz(std::string const& tag);

  static double GetMeanDeltaTime(std::string const& tag);
  static double GetMeanDeltaTime(size_t handle);
  static double GetMaxDeltaTime(std::string const& tag);
  static double GetMaxDeltaTime(size_t handle);
  static double GetMinDeltaTime(std::string const& tag);
  static double GetMinDeltaTime(size_t handle);
  static double GetLastDeltaTime(std::string const& tag);
  static double GetLastDeltaTime(size_t handle);
  static double GetVarianceDeltaTime(std::string const& tag);
  static double GetVarianceDeltaTime(size_t handle);

  static void WriteToYamlFile(const std::string& path);
  static void Print(std::ostream& out);  // NOLINT
  static std::string Print();
  static std::string SecondsToTimeString(double seconds);
  static void Reset();
  static const map_t& GetStatsCollectors() {
    return Instance().tag_map_;

  void AddSample(size_t handle, double sample);

  static Statistics& Instance();


  typedef std::vector<statistics::StatisticsMapValue> list_t;

  list_t stats_collectors_;
  map_t tag_map_;
  size_t max_tag_length_;
  std::mutex mutex_;

typedef StatsCollectorImpl StatsCollector;
typedef DummyStatsCollector StatsCollector;

}  // namespace statistics