#pragma once /* * Created by Brett on 20/09/23. * Licensed under GNU General Public License V3.0 * See LICENSE file for license detail */ #ifndef BLT_PROFILER_V2_H #define BLT_PROFILER_V2_H #include #include #include #include namespace blt { // use the historical values (average) instead of the latest values static inline constexpr std::uint32_t PRINT_HISTORY = 0x1; // print out the cycles static inline constexpr std::uint32_t PRINT_CYCLES = 0x2; // print out the wall time static inline constexpr std::uint32_t PRINT_WALL = 0x4; // print out the thread CPU time static inline constexpr std::uint32_t PRINT_THREAD = 0x8; enum class sort_by { CYCLES, WALL, THREAD }; // 32 bit currently not supported typedef std::int64_t pf_time_t; typedef std::uint64_t pf_cycle_t; struct interval_t { pf_time_t wall_start = 0; pf_time_t wall_end = 0; pf_time_t wall_total = 0; pf_time_t thread_start = 0; pf_time_t thread_end = 0; pf_time_t thread_total = 0; pf_cycle_t cycles_start = 0; pf_cycle_t cycles_end = 0; pf_cycle_t cycles_total = 0; std::uint64_t count = 0; std::string interval_name; }; struct cycle_interval_t { pf_cycle_t cycles_start = 0; pf_cycle_t cycles_end = 0; pf_cycle_t cycles_total = 0; std::uint64_t count = 0; std::string interval_name; }; struct profile_t { std::vector intervals; std::vector cycle_intervals; std::string name; explicit profile_t(std::string name): name(std::move(name)) {} profile_t(const profile_t& p) = delete; profile_t& operator=(const profile_t& p) = delete; ~profile_t(); }; interval_t* createInterval(profile_t& profiler, std::string interval_name); void startInterval(interval_t* interval); inline interval_t* startInterval(profile_t& profiler, std::string interval_name){ auto* p = createInterval(profiler, std::move(interval_name)); startInterval(p); return p; } void endInterval(interval_t* interval); void printProfile(profile_t& profiler, std::uint32_t flags = PRINT_HISTORY | PRINT_CYCLES | PRINT_THREAD | PRINT_WALL, sort_by sort = sort_by::CYCLES, blt::logging::log_level log_level = blt::logging::log_level::NONE); void writeProfile(std::ifstream& stream, const profile_t& profiler); void clearProfile(profile_t& profiler); namespace _internal { void startInterval(const std::string& profile_name, const std::string& interval_name); void endInterval(const std::string& profile_name, const std::string& interval_name); void printProfile(const std::string& profile_name, std::uint32_t flags = PRINT_HISTORY | PRINT_CYCLES | PRINT_THREAD | PRINT_WALL, sort_by sort = sort_by::CYCLES, blt::logging::log_level log_level = blt::logging::log_level::NONE); void writeProfile(std::ifstream& stream, const std::string& profile_name); } class auto_interval { private: interval_t* iv; public: auto_interval(std::string interval_name, profile_t& profiler) { iv = blt::createInterval(profiler, std::move(interval_name)); blt::startInterval(iv); } explicit auto_interval(interval_t* iv): iv(iv) { blt::startInterval(iv); } auto_interval(const auto_interval& i) = delete; auto_interval& operator=(const auto_interval& i) = delete; ~auto_interval() { blt::endInterval(iv); } }; } #ifdef BLT_DISABLE_PROFILING #define BLT_START_INTERVAL(profileName, intervalName) #define BLT_END_INTERVAL(profileName, intervalName) #define BLT_PRINT_PROFILE(profileName, ...) #define BLT_WRITE_PROFILE(stream, profileName) #else /** * Starts an interval to be measured, when ended the row will be added to the specified profile. */ #define BLT_START_INTERVAL(profileName, intervalName) blt::_internal::startInterval(profileName, intervalName) /** * Ends an interval, adds the interval to the profile. */ #define BLT_END_INTERVAL(profileName, intervalName) blt::_internal::endInterval(profileName, intervalName) /** * Prints the profile order from least time to most time. * @param profileName the profile to print * @param loggingLevel blt::logging::LOG_LEVEL to log with (default: BLT_NONE) * @param averageHistory use the historical collection of interval rows in an average or just the latest? (default: false) */ #define BLT_PRINT_PROFILE(profileName, ...) blt::_internal::printProfile(profileName, ##__VA_ARGS__) /** * writes the profile to an output stream, ordered from least time to most time, in CSV format. */ #define BLT_WRITE_PROFILE(stream, profileName) blt::_internal::writeProfile(stream, profileName) #endif #endif //BLT_PROFILER_V2_H