7std::chrono::steady_clock::time_point Profiler::start_point;
9Profiler& Profiler::get_instance(){
11 static std::mutex mut;
12 std::lock_guard<std::mutex>
lock(mut);
13 if(inst.start_point.time_since_epoch() == std::chrono::steady_clock::duration::zero()){
14 inst.start_point = std::chrono::steady_clock::now();
19void Profiler::write_events(
const std::vector<Profile_event>& events){
23 std::lock_guard<std::mutex>
lock(io_mut);
24 for(
const auto& event : events){
26 auto ts =
event.start;
28 out_file <<
"{ \"name\": \"" <<
event.name <<
"\""
29 <<
", \"cat\": \"function\""
31 <<
", \"pid\": \"" << pid <<
"\""
32 <<
", \"tid\": \"" <<
event.thread_id <<
"\""
33 <<
", \"ts\": \"" <<
ts <<
"\""
34 <<
", \"dur\": \"" << end -
ts <<
"\""
35 <<
", \"dbg_end\": \"" << end <<
"\""
41 const char *env_p = std::getenv(
"UG_PROFILE");
42 active = env_p && env_p[0] !=
'\0';
47 std::string filename =
"ug_";
51 pid = std::this_thread::get_id();
52 out_file.open(filename);
57Profiler_thread_inst::Profiler_thread_inst(Profiler& profiler) : profiler(profiler) {
58 thread_events.reserve(THREAD_EVENT_BUF_SIZE);
62Profiler_thread_inst& Profiler_thread_inst::get_instance(){
63 static thread_local Profiler_thread_inst inst(Profiler::get_instance());
67Profiler_thread_inst::~Profiler_thread_inst(){
68 profiler.write_events(thread_events);
71void Profiler_thread_inst::add_event(Profile_event&& event){
72 if(thread_events.size() == THREAD_EVENT_BUF_SIZE){
73 profiler.write_events(thread_events);
74 thread_events.clear();
77 thread_events.emplace_back(std::move(event));
80void Profiler_thread_inst::push_timer(
const char *
name){
81 c_timers.emplace_back(std::ref(*
this), std::string(
name));
84void Profiler_thread_inst::pop_timer(){
88Profile_timer::Profile_timer(Profiler_thread_inst& profiler, std::string
name) :
90 event(
name, std::this_thread::get_id())
92 auto ts = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - profiler.profiler.get_start_point()).count();
98 if(
ts <= profiler.last_ts){
99 ts = profiler.last_ts + 1;
103 profiler.last_ts =
ts;
106Profile_timer::Profile_timer(Profile_timer&& o) :
109 std::swap(event, o.event);
112Profile_timer::~Profile_timer(){
116Profile_timer& Profile_timer::operator=(Profile_timer&& rhs) {
117 std::swap(event, rhs.event);
118 std::swap(profiler, rhs.profiler);
122void Profile_timer::commit(){
123 if(event.name.empty())
126 event.end = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - profiler.get().profiler.get_start_point()).count();
127 profiler.get().add_event(std::move(event));
130void push_prof_timer(
const char *
name){
131 Profiler_thread_inst::get_instance().push_timer(
name);
134void pop_prof_timer(){
135 Profiler_thread_inst::get_instance().pop_timer();