9 #ifndef zakero_Profiler_h
10 #define zakero_Profiler_h
256 #include <experimental/source_location>
268 #ifdef ZAKERO_PROFILER_ENABLE
301 #define ZAKERO_PROFILER_INIT(output_) \
302 zakero::Profiler::init(output_, {});
345 #define ZAKERO_PROFILER_INIT_METADATA(output_, meta_data_) \
346 zakero::Profiler::init(output_, meta_data_);
393 #define ZAKERO_PROFILER_ACTIVATE \
394 zakero::Profiler::activate();
403 #define ZAKERO_PROFILER_DEACTIVATE \
404 zakero::Profiler::deactivate();
420 #define ZAKERO_PROFILER_UNIQUE(name_) ZAKERO_CONCAT(name_, __LINE__)
461 #define ZAKERO_PROFILER_DURATION(category_, name_) \
462 zakero::Profiler::Duration ZAKERO_PROFILER_UNIQUE(zakero_profiler_duration_) \
465 , std::experimental::source_location::current() \
480 #define ZAKERO_PROFILER_INSTANT(category_, name_) \
482 zakero::Profiler::Instant ZAKERO_PROFILER_UNIQUE(zakero_profiler_instant_) \
485 , std::experimental::source_location::current() \
491 #define ZAKERO_PROFILER_INIT(output_)
492 #define ZAKERO_PROFILER_INIT_METADATA(output_, meta_data_)
493 #define ZAKERO_PROFILER_ACTIVATE
494 #define ZAKERO_PROFILER_DEACTIVATE
495 #define ZAKERO_PROFILER_DURATION(category_, name_)
496 #define ZAKERO_PROFILER_INSTANT(category_, name_)
509 using MetaData = std::map<std::string, std::string>;
513 std::string category;
515 std::experimental::source_location location;
516 std::chrono::microseconds::rep time_stamp;
517 std::thread::id thread_id;
521 Data(
const char,
const std::string&,
const std::string&,
const std::experimental::source_location&) noexcept;
525 :
public zakero::Profiler::Data
529 Duration(
const std::string&,
const std::string&,
const std::experimental::source_location&) noexcept;
530 ~Duration() noexcept;
534 :
public zakero::Profiler::Data
536 Instant(
const std::string&,
const std::string&,
const std::experimental::source_location&) noexcept;
540 ~Profiler() noexcept;
542 static void init(std::ostream&, zakero::Profiler::MetaData) noexcept;
543 static void init(std::string, zakero::Profiler::MetaData) noexcept;
545 static void activate() noexcept;
546 static void deactivate() noexcept;
548 static void report(
const zakero::Profiler::Data&) noexcept;
552 std::ostream* stream;
553 std::ofstream file_output;
562 #ifdef ZAKERO_PROFILER_IMPLEMENTATION
567 #ifdef ZAKERO__DOXYGEN_DEFINE_DOCS
582 #define ZAKERO_PROFILER_IMPLEMENTATION
594 #define ZAKERO_PROFILER_ENABLE
596 #endif // ZAKERO__DOXYGEN_DEFINE_DOCS
610 #include <sys/types.h>
612 #define ZAKERO_PROFILER__PID getpid()
614 #define ZAKERO_PROFILER__PID -1
625 zakero::Profiler zakero_profiler;
669 Profiler::Profiler() noexcept
683 Profiler::~Profiler() noexcept
685 std::lock_guard<std::mutex> lock(zakero_profiler.mutex);
687 if(stream !=
nullptr)
689 (*stream) <<
"]}" << std::endl;
691 if(file_output.is_open())
713 void zakero::Profiler::init(std::string file_name
714 , zakero::Profiler::MetaData meta_data
717 if(zakero_profiler.stream !=
nullptr)
722 zakero_profiler.file_output.open(file_name);
724 init(zakero_profiler.file_output, meta_data);
738 void zakero::Profiler::init(std::ostream& output_stream
739 , zakero::Profiler::MetaData meta_data
742 std::lock_guard<std::mutex> lock(zakero_profiler.mutex);
744 if(zakero_profiler.stream !=
nullptr)
749 zakero_profiler.stream = &output_stream;
752 if(meta_data.contains(
"date") ==
false)
754 std::time_t time = std::chrono::system_clock::to_time_t(
755 std::chrono::system_clock::now()
759 std::strftime(buf,
sizeof(buf),
"%F %T", std::localtime(&time));
761 meta_data[
"date"] = buf;
764 if(meta_data.contains(
"traceEvents"))
766 meta_data.erase(
"traceEvents");
769 meta_data[
"displayTimeUnit"] =
"ms";
771 (*zakero_profiler.stream) <<
"{";
773 for(
const auto& iter : meta_data)
775 (*zakero_profiler.stream) <<
"\"" << iter.first <<
"\":\"" << iter.second <<
"\",";
778 (*zakero_profiler.stream) <<
"\"traceEvents\":[{}\n";
788 void zakero::Profiler::activate() noexcept
790 zakero_profiler.is_active =
true;
803 void zakero::Profiler::deactivate() noexcept
805 zakero_profiler.is_active =
false;
814 void Profiler::report(
const zakero::Profiler::Data& data
817 std::lock_guard<std::mutex> lock(zakero_profiler.mutex);
822 (*zakero_profiler.stream)
823 <<
",{\"ph\":\"" << data.phase <<
"\""
824 <<
",\"ts\":" << data.time_stamp
825 <<
",\"pid\":" << data.process_id
826 <<
",\"tid\":" << data.thread_id
827 <<
",\"cat\":\"" << data.category <<
"\""
828 <<
",\"name\":\"" << data.name <<
"\""
830 <<
"{\"file_name\":\"" << data.location.file_name() <<
"\""
831 <<
",\"function_name\":\"" << data.location.function_name() <<
"\""
880 Profiler::Data::Data(
const char phase
881 ,
const std::string& category
882 ,
const std::string& name
883 ,
const std::experimental::source_location& location
889 , thread_id(std::this_thread::get_id())
890 , process_id(ZAKERO_PROFILER__PID)
914 Profiler::Duration::Duration(
const std::string& category
915 ,
const std::string& name
916 ,
const std::experimental::source_location& location
918 : zakero::Profiler::Data(
'B', category, name, location)
919 , was_active(zakero_profiler.is_active)
929 Profiler::Duration::~Duration() noexcept
931 if(was_active || zakero_profiler.is_active)
933 zakero::Profiler::report(*
this);
937 zakero::Profiler::report(*
this);
960 Profiler::Instant::Instant(
const std::string& category
961 ,
const std::string& name
962 ,
const std::experimental::source_location& location
964 : zakero::Profiler::Data(
'I', category, name, location)
966 if(zakero_profiler.is_active)
968 zakero::Profiler::report(*
this);
974 #endif // ZAKERO_PROFILER_IMPLEMENTATION
978 #endif // zakero_Profiler_h