Fix the build for older macOS.
[dcpomatic.git] / src / lib / timer.cc
index 7afdc394df3cfc370e824a47a218a5f34ffcabde..caef89e0e98e5c413539c0851216acde96f6f797 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
 */
 
+
 /** @file src/timer.cc
  *  @brief Some timing classes for debugging and profiling.
  */
 
-#include <iostream>
-#include <sys/time.h>
+
+#include "compose.hpp"
 #include "timer.h"
 #include "util.h"
+#include <sys/time.h>
+#include <iostream>
 
 #include "i18n.h"
 
-using namespace std;
+
+using std::cout;
+using std::list;
+using std::max;
+using std::pair;
+using std::string;
+using boost::optional;
+
 
 /** @param n Name to use when giving output */
 PeriodTimer::PeriodTimer (string n)
@@ -38,6 +48,7 @@ PeriodTimer::PeriodTimer (string n)
        gettimeofday (&_start, 0);
 }
 
+
 /** Destroy PeriodTimer and output the time elapsed since its construction */
 PeriodTimer::~PeriodTimer ()
 {
@@ -46,9 +57,7 @@ PeriodTimer::~PeriodTimer ()
        cout << N_("T: ") << _name << N_(": ") << (seconds (stop) - seconds (_start)) << N_("\n");
 }
 
-/** @param n Name to use when giving output.
- *  @param s Initial state.
- */
+
 StateTimer::StateTimer (string n, string s)
        : _name (n)
 {
@@ -58,35 +67,79 @@ StateTimer::StateTimer (string n, string s)
        _state = s;
 }
 
-/** @param s New state that the caller is in */
+
+StateTimer::StateTimer (string n)
+       : _name (n)
+{
+
+}
+
+
+void
+StateTimer::set (string s)
+{
+       set_internal (s);
+}
+
+
 void
-StateTimer::set_state (string s)
+StateTimer::set_internal (optional<string> s)
 {
        double const last = _time;
        struct timeval t;
        gettimeofday (&t, 0);
        _time = seconds (t);
 
-       if (_totals.find (s) == _totals.end ()) {
-               _totals[s] = 0;
+       if (s && _counts.find(*s) == _counts.end()) {
+               _counts[*s] = Counts();
        }
 
-       _totals[_state] += _time - last;
+       if (_state) {
+               _counts[*_state].total_time += _time - last;
+               _counts[*_state].number++;
+       }
        _state = s;
 }
 
+
+void
+StateTimer::unset ()
+{
+       set_internal (optional<string>());
+}
+
+
 /** Destroy StateTimer and generate a summary of the state timings on cout */
 StateTimer::~StateTimer ()
 {
-       if (_state.empty ()) {
+       if (!_state) {
                return;
        }
 
+       unset ();
+
+       int longest = 0;
+       for (auto const& i: _counts) {
+               longest = max (longest, int(i.first.length()));
+       }
+
+       list<pair<double, string>> sorted;
+
+       for (auto const& i: _counts) {
+               string name = i.first + string(longest + 1 - i.first.size(), ' ');
+               char buffer[64];
+               snprintf (buffer, 64, "%.4f", i.second.total_time);
+               string total_time (buffer);
+               sorted.push_back (make_pair(i.second.total_time, String::compose("\t%1%2 %3 %4", name, total_time, i.second.number, (i.second.total_time / i.second.number))));
+       }
+
+       sorted.sort ([](pair<double, string> const& a, pair<double, string> const& b) {
+               return a.first > b.first;
+       });
 
-       set_state (N_(""));
 
        cout << _name << N_(":\n");
-       for (map<string, double>::iterator i = _totals.begin(); i != _totals.end(); ++i) {
-               cout << N_("\t") << i->first << " " << i->second << N_("\n");
+       for (auto const& i: sorted) {
+               cout << N_("\t") << i.second << "\n";
        }
 }