Skip to content

Instantly share code, notes, and snippets.

@dnbaker
Created June 18, 2020 15:56
Show Gist options
  • Save dnbaker/a4f3e5e1dda6ffa1b62bda07389c00c7 to your computer and use it in GitHub Desktop.
Save dnbaker/a4f3e5e1dda6ffa1b62bda07389c00c7 to your computer and use it in GitHub Desktop.
TimeStamper - runtime summarization
#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