#ifndef RIPPLE_BASICS_FUNCTIONPROFILER_H_INCLUDED #define RIPPLE_BASICS_FUNCTIONPROFILER_H_INCLUDED #include #include #include #include #include #include #include #include namespace beast { void logProfilingResults(); class FunctionProfiler { public: std::string functionName; std::chrono::steady_clock::time_point start; std::uint64_t cpuCycleStart; inline static std::mutex mutex_; struct StatisticData { std::chrono::nanoseconds timeInTotal; std::uint64_t cpuCyclesInTotal; std::int64_t count; }; inline static std::unordered_map< std::string, StatisticData> funcionDurations; FunctionProfiler( std::string const& tag, std::source_location location = std::source_location::current()) : functionName(location.function_name() + tag) , start(std::chrono::steady_clock::now()) , cpuCycleStart(__rdtsc()) { } ~FunctionProfiler() noexcept { auto duration = std::chrono::steady_clock::now() - start; std::lock_guard lock{mutex_}; if (funcionDurations[functionName].count == std::numeric_limits::max()) { return; } funcionDurations[functionName].timeInTotal += duration; funcionDurations[functionName].cpuCyclesInTotal += (__rdtsc() - cpuCycleStart); funcionDurations[functionName].count++; } }; inline std::string getProfilingResults() { std::lock_guard lock{FunctionProfiler::mutex_}; std::stringstream ss; ss << "Function profiling results:" << std::endl; ss << "name,time,count" << std::endl; for (auto const& [name, duration] : FunctionProfiler::funcionDurations) { ss << name << "," << duration.first.count() << " ns" << "," << duration.second << std::endl; } return ss.str(); } } // namespace beast #endif