84329a5d5b058ffa2ed28c80761051fa5f15ce3f
[dcpomatic.git] / src / lib / timer.cc
1 /*
2     Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 /** @file src/timer.cc
22  *  @brief Some timing classes for debugging and profiling.
23  */
24
25 #include "timer.h"
26 #include "util.h"
27 #include "compose.hpp"
28 #include <iostream>
29 #include <sys/time.h>
30
31 #include "i18n.h"
32
33 using namespace std;
34 using boost::optional;
35
36 /** @param n Name to use when giving output */
37 PeriodTimer::PeriodTimer (string n)
38         : _name (n)
39 {
40         gettimeofday (&_start, 0);
41 }
42
43 /** Destroy PeriodTimer and output the time elapsed since its construction */
44 PeriodTimer::~PeriodTimer ()
45 {
46         struct timeval stop;
47         gettimeofday (&stop, 0);
48         cout << N_("T: ") << _name << N_(": ") << (seconds (stop) - seconds (_start)) << N_("\n");
49 }
50
51 StateTimer::StateTimer (string n, string s)
52         : _name (n)
53 {
54         struct timeval t;
55         gettimeofday (&t, 0);
56         _time = seconds (t);
57         _state = s;
58 }
59
60 StateTimer::StateTimer (string n)
61         : _name (n)
62 {
63
64 }
65
66 void
67 StateTimer::set (string s)
68 {
69         set_internal (s);
70 }
71
72 void
73 StateTimer::set_internal (optional<string> s)
74 {
75         double const last = _time;
76         struct timeval t;
77         gettimeofday (&t, 0);
78         _time = seconds (t);
79
80         if (s && _counts.find(*s) == _counts.end()) {
81                 _counts[*s] = Counts();
82         }
83
84         if (_state) {
85                 _counts[*_state].total_time += _time - last;
86                 _counts[*_state].number++;
87         }
88         _state = s;
89 }
90
91 void
92 StateTimer::unset ()
93 {
94         set_internal (optional<string>());
95 }
96
97 bool compare (pair<double, string> a, pair<double, string> b)
98 {
99         return a.first > b.first;
100 }
101
102 /** Destroy StateTimer and generate a summary of the state timings on cout */
103 StateTimer::~StateTimer ()
104 {
105         if (!_state) {
106                 return;
107         }
108
109         unset ();
110
111         int longest = 0;
112         for (auto const& i: _counts) {
113                 longest = max (longest, int(i.first.length()));
114         }
115
116         list<pair<double, string> > sorted;
117
118         for (auto const& i: _counts) {
119                 string name = i.first + string(longest + 1 - i.first.size(), ' ');
120                 char buffer[64];
121                 snprintf (buffer, 64, "%.4f", i.second.total_time);
122                 string total_time (buffer);
123                 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))));
124         }
125
126         sorted.sort (compare);
127
128         cout << _name << N_(":\n");
129         for (auto const& i: sorted) {
130                 cout << N_("\t") << i.second << "\n";
131         }
132 }