source: trunk/GDE/SINA/builddir/src/timer.h

Last change on this file was 19170, checked in by westram, 2 years ago
  • sina source
    • unpack + remove tarball
    • no longer ignore sina builddir.
File size: 5.9 KB
Line 
1/*
2  Copyright (c) 2006-2018 Elmar Pruesse <elmar.pruesse@ucdenver.edu>
3
4  This file is part of SINA.
5  SINA is free software: you can redistribute it and/or modify it under
6  the terms of the GNU General Public License as published by the Free
7  Software Foundation, either version 3 of the License, or (at your
8  option) any later version.
9
10  SINA is distributed in the hope that it will be useful, but WITHOUT ANY
11  WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  for more details.
14
15  You should have received a copy of the GNU General Public License
16  along with SINA.  If not, see <http://www.gnu.org/licenses/>.
17
18  Additional permission under GNU GPL version 3 section 7
19
20  If you modify SINA, or any covered work, by linking or combining it
21  with components of ARB (or a modified version of that software),
22  containing parts covered by the terms of the
23  ARB-public-library-license, the licensors of SINA grant you additional
24  permission to convey the resulting work. Corresponding Source for a
25  non-source form of such a combination shall include the source code
26  for the parts of ARB used as well as that of the covered work.
27*/
28
29#include <sys/time.h>
30#include <ctime>
31#include <vector>
32#include <algorithm>
33#include <iomanip>
34#include <iterator>
35#include <string>
36#include <iostream>
37#include <sstream>
38#include <numeric>
39#include <thread>
40
41#include <tbb/concurrent_unordered_map.h>
42
43#ifndef _TIMER_H_
44#define _TIMER_H_
45
46/* defined in time.h
47struct timeval {
48  time_t         tv_sec;   // seconds
49  suseconds_t    tv_usec;  // microseconds
50};
51*/
52
53namespace sina {
54
55struct timestamp : private timeval {
56    timestamp(int /*unused*/) {
57        tv_sec = 0;
58        tv_usec = 0;
59    }
60
61    void get() {
62        // Adjusting the system clock breaks things
63        // should use clock_gettime(CLOCK_MONOTONIC, ...)
64        // (but that needs macos 10.12)
65        gettimeofday(this, nullptr);
66    }
67
68    timestamp() {
69        get();
70    }
71
72    operator float() {
73        return tv_sec + float(tv_usec)/1000000;
74    }
75   
76    timestamp operator-(const timestamp& rval) {
77        timestamp result(0);
78        if (tv_usec < rval.tv_usec) {
79            result.tv_sec = tv_sec - rval.tv_sec - 1;
80            result.tv_usec = 1000000 + tv_usec - rval.tv_usec;
81        } else {
82            result.tv_sec =  tv_sec - rval.tv_sec;
83            result.tv_usec = tv_usec - rval.tv_usec;
84        }
85        return result;
86    }
87
88    timestamp operator+(const timestamp& rval) {
89        timestamp result(0);
90        if (tv_usec + rval.tv_usec >= 1000000) {
91            result.tv_sec = tv_sec + rval.tv_sec + 1;
92            result.tv_usec = tv_usec + rval.tv_usec - 1000000;
93        } else {
94            result.tv_sec = tv_sec + rval.tv_sec;
95            result.tv_usec = tv_usec +  rval.tv_usec;
96        }
97        return result;
98    }
99
100    timestamp& operator+=(const timestamp& rval) {
101        if (tv_usec + rval.tv_usec >= 1000000) {
102            tv_sec += rval.tv_sec + 1;
103            tv_usec = tv_usec + rval.tv_usec - 1000000;
104        } else {
105            tv_sec += rval.tv_sec;
106            tv_usec += rval.tv_usec;
107        }
108        return *this;
109    }
110
111    friend std::ostream& operator<<(std::ostream& out, const timestamp& t) {
112        return out << t.tv_sec
113                   << "." << std::setfill('0') << std::setw(3) << t.tv_usec/1000
114                   << "s";
115    }
116};
117
118
119
120class timer {
121    std::vector<timestamp> timings;
122    std::vector<const char*> names;
123    std::vector<timestamp>::iterator time_it;
124    timestamp t_last;
125    unsigned int calls{0};
126public:
127    timer() : timings(1, 0), t_last(0) {}
128
129    void start() {
130        time_it = timings.begin();
131        t_last.get();
132        ++calls;
133    }
134
135    void stop(const char* name=nullptr) {
136        timestamp t_now;
137        if (++time_it == timings.end()) {
138            names.push_back(name);
139            timings.emplace_back(0);
140            time_it = timings.end() - 1;
141        }
142        *time_it +=  t_now - t_last;
143        t_last.get();
144    }
145
146    void end_loop(int i) {
147        time_it-=i;
148        t_last.get();
149    }
150
151    timer& operator+=(const timer& o) {
152        if (timings.size() != o.timings.size()) {
153            throw std::runtime_error("Tried to add incompatible timers");
154        }
155        for (size_t i = 0; i < timings.size(); i++) {
156            timings[i] += o.timings[i];
157        }
158        calls += o.calls;
159        return *this;
160    }
161
162    friend std::ostream& operator<<(std::ostream& out , const timer& t) {
163        out << std::accumulate(t.timings.begin(), t.timings.end(), timestamp(0))
164            << " (" << t.calls << " calls, ";
165        for (size_t i = 0; i < t.names.size(); ++i) {
166            if (i > 0) {
167                out << ", ";
168            }
169            if (t.names[i] != nullptr) {
170                out << t.names[i];
171            } else {
172                out << i;
173            }
174            out << ": " << t.timings[i];
175        }
176        out << ")";
177        return out;
178    }
179};
180
181class timer_mt {
182    tbb::concurrent_unordered_map<std::thread::id, timer, std::hash<std::thread::id>> timers;
183public:
184    timer& get_timer() {
185        return timers[std::this_thread::get_id()];
186    }
187
188    friend std::ostream& operator<<(std::ostream& out , const timer_mt& mt) {
189        auto it = mt.timers.begin();
190        auto end = mt.timers.end();
191        if (it == end) {
192            out << "never called";
193        } else {
194            timer sum((it++)->second);
195            for (; it!=end; ++it) {
196                sum += it->second;
197            }
198            out << sum;
199        }
200        return out;
201    }
202};
203
204} // namespace sina
205#endif
206/*
207  Local Variables:
208  mode:c++
209  c-file-style:"stroustrup"
210  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
211  indent-tabs-mode:nil
212  fill-column:99
213  End:
214*/
215// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
216
Note: See TracBrowser for help on using the repository browser.