skia2/tools/timer/SysTimer_windows.cpp
Mike Klein 912947737a Use __rdtsc on Windows.
This seems to be ~100x higher resolution than QueryPerformanceCounter.  AFAIK, all our Windows perf bots have constant_tsc, so we can be a bit more direct about using rdtsc directly: it'll always tick at the max CPU frequency.

Now, the question remains, what is the max CPU frequency to divide through by?  It looks like QueryPerformanceFrequency actually gives the CPU frequency in kHz, suspiciously exactly what we need to divide through to get elapsed milliseconds.  That was a freebie.

I did some before/after comparison on slow benchmarks.  Timings look the same.  Going to land this without review tonight to see what happens on the bots; happy to review carefully tomorrow.

R=mtklein@google.com
TBR=bungeman

BUG=skia:

Review URL: https://codereview.chromium.org/394363003
2014-07-16 19:59:32 -04:00

54 lines
1.6 KiB
C++

/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SysTimer_windows.h"
#include <intrin.h>
static ULONGLONG win_cpu_time() {
FILETIME createTime;
FILETIME exitTime;
FILETIME usrTime;
FILETIME sysTime;
if (0 == GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &sysTime, &usrTime)) {
return 0;
}
ULARGE_INTEGER start_cpu_sys;
ULARGE_INTEGER start_cpu_usr;
start_cpu_sys.LowPart = sysTime.dwLowDateTime;
start_cpu_sys.HighPart = sysTime.dwHighDateTime;
start_cpu_usr.LowPart = usrTime.dwLowDateTime;
start_cpu_usr.HighPart = usrTime.dwHighDateTime;
return start_cpu_sys.QuadPart + start_cpu_usr.QuadPart;
}
void SysTimer::startCpu() {
fStartCpu = win_cpu_time();
}
double SysTimer::endCpu() {
ULONGLONG end_cpu = win_cpu_time();
return static_cast<double>(end_cpu - fStartCpu) / 10000.0L;
}
// On recent Intel chips (roughly, "has Core or Atom in its name") __rdtsc will always tick
// at the CPU's maximum rate, even while power management clocks the CPU up and down.
// That's great, because it makes measuring wall time super simple.
void SysTimer::startWall() {
fStartWall = __rdtsc();
}
double SysTimer::endWall() {
unsigned __int64 end = __rdtsc();
// This seems to, weirdly, give the CPU frequency in kHz. That's exactly what we want!
LARGE_INTEGER freq_khz;
QueryPerformanceFrequency(&freq_khz);
return static_cast<double>(end - fStartWall) / static_cast<double>(freq_khz.QuadPart);
}