aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/common/profiler.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner <yuriks@yuriks.net>2015-02-15 15:49:27 -0200
committerGravatar Yuri Kunde Schlesner <yuriks@yuriks.net>2015-03-01 21:47:14 -0300
commitdc8a3f8bc842df1b3eeeb5a283556ac644ab3183 (patch)
tree82bc4d610bd0b77ba6f2ac4e514e68d1c251b251 /src/common/profiler.cpp
parentcd1fbfcf1b70e365d81480ec0f56db19ed02454f (diff)
Profiler: Implement QPCClock to get better precision on Win32
MSVC 2013 (at least) doesn't use QueryPerformanceCounter to implement std::chrono::high_resolution_clock, so it has bad precision. Manually implementing our own clock type using it works around this for now.
Diffstat (limited to 'src/common/profiler.cpp')
-rw-r--r--src/common/profiler.cpp23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/common/profiler.cpp b/src/common/profiler.cpp
index c37546af..65c3df16 100644
--- a/src/common/profiler.cpp
+++ b/src/common/profiler.cpp
@@ -6,6 +6,12 @@
#include "common/profiler_reporting.h"
#include "common/assert.h"
+#if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013.
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h> // For QueryPerformanceCounter/Frequency
+#endif
+
namespace Common {
namespace Profiling {
@@ -13,6 +19,23 @@ namespace Profiling {
thread_local Timer* Timer::current_timer = nullptr;
#endif
+#if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013
+QPCClock::time_point QPCClock::now() {
+ static LARGE_INTEGER freq;
+ // Use this dummy local static to ensure this gets initialized once.
+ static BOOL dummy = QueryPerformanceFrequency(&freq);
+
+ LARGE_INTEGER ticks;
+ QueryPerformanceCounter(&ticks);
+
+ // This is prone to overflow when multiplying, which is why I'm using micro instead of nano. The
+ // correct way to approach this would be to just return ticks as a time_point and then subtract
+ // and do this conversion when creating a duration from two time_points, however, as far as I
+ // could tell the C++ requirements for these types are incompatible with this approach.
+ return time_point(duration(ticks.QuadPart * std::micro::den / freq.QuadPart));
+}
+#endif
+
TimingCategory::TimingCategory(const char* name, TimingCategory* parent)
: accumulated_duration(0) {