Skip to content

Instantly share code, notes, and snippets.

@markdewing
Created May 17, 2024 21:12
Show Gist options
  • Save markdewing/982877af92e5b852fc25daec25cc59f6 to your computer and use it in GitHub Desktop.
Save markdewing/982877af92e5b852fc25daec25cc59f6 to your computer and use it in GitHub Desktop.
Collect timing information and write out a trace file in Chrome Tracing Format
#include "trace.h"
#include <iostream>
#include <unistd.h>
int main()
{
Timer t1("first");
t1.start();
sleep(1);
Timer t2("second");
t2.start();
sleep(1);
t2.stop();
sleep(1);
t1.stop();
writeTrace("out1.json");
return 0;
}
#include "trace.h"
#include <chrono>
#include <fstream>
#include <map>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
// Structure to save trace event information
struct EventRecord {
double timestamp; // in seconds
char event_type;
std::string name;
std::thread::id tid;
double duration; // in seconds
EventRecord(double ts, char type, const std::string &name,
std::thread::id tid1, double dur = 0.0)
: timestamp(ts), event_type(type), name(name), tid(tid1), duration(dur) {}
};
std::vector<EventRecord> events;
std::mutex event_mutex; // for thread safety
using TimePoint = std::chrono::steady_clock::time_point;
// Track program start time in order to compute times relative to it
TimePoint program_start = std::chrono::steady_clock::now();
void Timer::start() {
start_time_ = std::chrono::steady_clock::now();
}
void Timer::stop() {
TimePoint stop_time = std::chrono::steady_clock::now();
std::chrono::duration<double> from_program_start =
start_time_ - program_start;
std::chrono::duration<double> dur = stop_time - start_time_;
std::thread::id tid = std::this_thread::get_id();
event_mutex.lock();
events.push_back(
EventRecord(from_program_start.count(), 'X', name_, tid, dur.count()));
event_mutex.unlock();
}
void writeTrace(const std::string &fname) {
// Map thread id to a small integer
int small_tid = 0;
std::map<std::thread::id, int> tid_map;
std::ofstream f(fname);
f << "{\n";
f << R"("traceEvents": [)" << "\n";
for (int idx = 0; idx < events.size(); idx++) {
EventRecord &er = events[idx];
if (tid_map.find(er.tid) == tid_map.end()) {
tid_map[er.tid] = small_tid++;
}
f << R"({"name":")" << er.name << R"(",)" << R"("ph":")" << er.event_type
<< R"(",)" << R"("pid":")" << 1 << R"(",)" << R"("tid":")"
<< tid_map[er.tid] << R"(",)" << R"("ts":)" << (er.timestamp * 1.0e6);
if (er.event_type == 'X')
f << R"(,"dur":)" << (er.duration * 1.0e6);
f << "}";
// Ensure last item is not followed by a comma
if (idx < events.size() - 1) {
f << ",\n";
} else {
f << "\n";
}
}
f << "}" << std::endl;
}
#ifndef TRACE_H
#define TRACE_H
#include <string>
#include <chrono>
// Collect timing information and write out a trace file in Chrome Tracing Format
// One possible implementation of a timer
class Timer {
public:
using TimePoint = std::chrono::steady_clock::time_point;
void start();
void stop();
Timer(const std::string& name) : name_(name) {}
private:
TimePoint start_time_;
std::string name_;
};
// Write trace to file in JSON format
void writeTrace(const std::string& fname);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment