Created
June 18, 2020 15:56
-
-
Save dnbaker/a4f3e5e1dda6ffa1b62bda07389c00c7 to your computer and use it in GitHub Desktop.
TimeStamper - runtime summarization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef TIMESTAMPER_H__ | |
#define TIMESTAMPER_H__ | |
#include <chrono> | |
#include <cstdint> | |
#include <vector> | |
#include <iostream> | |
#include <numeric> | |
#include <algorithm> | |
namespace timestamp { | |
using hrc = std::chrono::high_resolution_clock; | |
template<typename Clock> | |
static inline double timediff2ms(std::chrono::time_point<Clock> start, std::chrono::time_point<Clock> stop) { | |
if(stop < start) std::swap(stop, start); | |
return std::chrono::duration<double, std::milli>(stop - start).count(); | |
} | |
struct TimeStamper { | |
using value_type = std::chrono::time_point<std::chrono::high_resolution_clock>; | |
using v_t = value_type; | |
struct Event { | |
std::string label; | |
v_t time; | |
Event(std::string l, v_t t): label(l), time(t) {} | |
}; | |
static auto now() {return std::chrono::high_resolution_clock::now();} | |
std::vector<Event> events; | |
bool emit_on_close_ = false; | |
TimeStamper(std::string msg, bool emit_on_close=true): events({Event{msg, now()}}), emit_on_close_(emit_on_close) {} | |
TimeStamper() {} | |
void restart(std::string label) { | |
events = {Event{label, now()}}; | |
} | |
void add_event(std::string label) { | |
events.emplace_back(label, now()); | |
} | |
~TimeStamper() { | |
if(emit_on_close_) { | |
emit(); | |
} | |
} | |
std::vector<std::pair<std::string, double>> to_intervals() const { | |
auto t = now(); | |
std::vector<std::pair<std::string, double>> ret(events.size()); | |
for(size_t i = 0; i < events.size(); ++i) { | |
auto nt = i == events.size() - 1 ? t: events[i + 1].time; | |
ret[i] = {events[i].label, timediff2ms(events[i].time, nt)}; | |
} | |
return ret; | |
} | |
void emit() const { | |
auto ivls = to_intervals(); | |
auto total_time = std::accumulate(ivls.begin(), ivls.end(), 0., [](auto x, const auto &y) {return x + y.second;}); | |
auto prod = 100. / total_time; | |
for(const auto &ivl: ivls) { | |
std::fprintf(stderr, "Event '%s' took %gms, %%%g of total %g\n", ivl.first.data(), ivl.second, ivl.second * prod, total_time); | |
} | |
std::vector<unsigned> idx(ivls.size()); | |
std::iota(idx.data(), idx.data() + ivls.size(), 0); | |
std::sort(idx.begin(), idx.end(), [&](auto x, auto y) {return ivls[x].second > ivls[y].second;}); | |
for(size_t i = 0; i < ivls.size(); ++i) { | |
std::fprintf(stderr, "%d/%s is %zu{st/th/nd} most expensive %u with %%%0.12g of total time\n", | |
idx[i], events[idx[i]].label.data(), i + 1, idx[i], ivls[idx[i]].second * prod); | |
} | |
} | |
}; | |
} // timestamp | |
#ifdef TIMESTAMP_MAIN | |
#include <memory> | |
#include <string> | |
int main() { | |
timestamp::TimeStamper ts("time things"); | |
ts.add_event("Allocate vector of strings"); | |
static constexpr unsigned long long nelem = 1000000; | |
auto strs = std::make_unique<std::string[]>(nelem); | |
auto strb = strs.get(), stre = strs.get() + nelem; | |
ts.add_event("Set strings to be integer encoding"); | |
for(unsigned i = 0; i < 1000000; ++i) { | |
strs[i] = std::to_string(i); | |
} | |
ts.add_event("Sort by lexicographic order"); | |
std::sort(strb, stre); | |
ts.add_event("Sort by reverse lexicographic order"); | |
std::sort(strb, stre, [](const auto &x, const auto &y) {return x > y;}); | |
ts.add_event("Destroy strings"); | |
{ | |
auto newstrs = std::move(strs); | |
} | |
ts.add_event("Stack unwinding"); | |
} | |
/* | |
* | |
* Example output: | |
* | |
Event 'time things' took 0.013ms, %0.00195519 of total 664.898 | |
Event 'Allocate vector of strings' took 16.498ms, %2.48128 of total 664.898 | |
Event 'Set strings to be integer encoding' took 86.783ms, %13.0521 of total 664.898 | |
Event 'Sort by lexicographic order' took 441.233ms, %66.361 of total 664.898 | |
Event 'Sort by reverse lexicographic order' took 115.764ms, %17.4108 of total 664.898 | |
Event 'Destroy strings' took 4.607ms, %0.692888 of total 664.898 | |
Event 'Stack unwinding' took 0ms, %0 of total 664.898 | |
3/Sort by lexicographic order is 1{st/th/nd} most expensive 3 with %66.3610057483 of total time | |
4/Sort by reverse lexicographic order is 2{st/th/nd} most expensive 4 with %17.4107908281 of total time | |
2/Set strings to be integer encoding is 3{st/th/nd} most expensive 2 with %13.0520771607 of total time | |
1/Allocate vector of strings is 4{st/th/nd} most expensive 1 with %2.48128284338 of total time | |
5/Destroy strings is 5{st/th/nd} most expensive 5 with %0.692888232481 of total time | |
0/time things is 6{st/th/nd} most expensive 0 with %0.00195518711141 of total time | |
6/Stack unwinding is 7{st/th/nd} most expensive 6 with %0 of total time | |
*/ | |
#endif | |
#endif /*TIMESTAMPER_H__ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment