From e7a543b77f9c03a171db8e8e13c8fd88c270720a Mon Sep 17 00:00:00 2001 From: Georgy Stolbovoy Date: Fri, 12 Jun 2026 17:27:22 +0300 Subject: [PATCH] fix time measurement when EASY_CHRONO_CLOCK is defined --- easy_profiler_core/event_trace_win.cpp | 27 ++++++++++++++++++++++++++ easy_profiler_core/profile_manager.cpp | 10 +++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/easy_profiler_core/event_trace_win.cpp b/easy_profiler_core/event_trace_win.cpp index bdb4d7b1..01a6b81d 100644 --- a/easy_profiler_core/event_trace_win.cpp +++ b/easy_profiler_core/event_trace_win.cpp @@ -209,6 +209,26 @@ static thread_process_info_map THREAD_PROCESS_INFO_TABLE; ////////////////////////////////////////////////////////////////////////// +// "The frequency of the performance counter is fixed at system boot and is consistent across all processors. +// Therefore, the frequency need only be queried upon application initialization, and the result can be cached." +// © https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancefrequency +extern const LONGLONG PERFORMANCE_FREQUENCY = []() +{ + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + return freq.QuadPart; +}(); + +#ifdef EASY_CHRONO_CLOCK +static profiler::timestamp_t ticks2time(LONGLONG ticks) +{ + EASY_CONSTEXPR auto clock_freq = EASY_CHRONO_CLOCK::period::den / EASY_CHRONO_CLOCK::period::num; + return static_cast(static_cast(ticks) / PERFORMANCE_FREQUENCY * clock_freq); +} +#endif + +////////////////////////////////////////////////////////////////////////// + void WINAPI easyProcessTraceEvent(PEVENT_RECORD _traceEvent) { if (_traceEvent->EventHeader.EventDescriptor.Opcode != SWITCH_CONTEXT_OPCODE) @@ -220,7 +240,14 @@ void WINAPI easyProcessTraceEvent(PEVENT_RECORD _traceEvent) EASY_FUNCTION(EASY_COLOR_INTERNAL_EVENT, profiler::OFF); auto _contextSwitchEvent = reinterpret_cast(_traceEvent->UserData); + +#ifdef EASY_CHRONO_CLOCK + // We need to use uniform time units, so we need to cast the ticks to time of the clock. + const auto time = ticks2time(_traceEvent->EventHeader.TimeStamp.QuadPart); +#else + // OK, time is measured only in ticks. const auto time = static_cast(_traceEvent->EventHeader.TimeStamp.QuadPart); +#endif if (time > TRACING_END_TIME.load(std::memory_order_acquire)) return; diff --git a/easy_profiler_core/profile_manager.cpp b/easy_profiler_core/profile_manager.cpp index 12fe96d8..f8df9e4c 100644 --- a/easy_profiler_core/profile_manager.cpp +++ b/easy_profiler_core/profile_manager.cpp @@ -152,6 +152,12 @@ EASY_CONSTEXPR profiler::color_t EASY_COLOR_END = 0xfff44336; // profiler::color ////////////////////////////////////////////////////////////////////////// +#ifdef _WIN32 +extern const LONGLONG PERFORMANCE_FREQUENCY; +#endif + +////////////////////////////////////////////////////////////////////////// + EASY_CONSTEXPR uint8_t FORCE_ON_FLAG = profiler::FORCE_ON & ~profiler::ON; ////////////////////////////////////////////////////////////////////////// @@ -259,9 +265,7 @@ static EASY_CONSTEXPR_FCN int64_t calculate_cpu_frequency() #elif defined(_WIN32) static int64_t calculate_cpu_frequency() { - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - return static_cast(freq.QuadPart); + return static_cast(PERFORMANCE_FREQUENCY); } #else # ifndef __APPLE__