summaryrefslogtreecommitdiffstats
path: root/chrome/browser/metrics/time_ticks_experiment_win.cc
diff options
context:
space:
mode:
authorsimonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-30 19:46:05 +0000
committersimonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-30 19:46:05 +0000
commitaa31281d74a2d0a4a37185ec2888d06eb726eb16 (patch)
tree96a9403e28a301d040c272af6e28fbac354ca345 /chrome/browser/metrics/time_ticks_experiment_win.cc
parente98a235bf3764de80423b0854b84de76c81f1778 (diff)
downloadchromium_src-aa31281d74a2d0a4a37185ec2888d06eb726eb16.zip
chromium_src-aa31281d74a2d0a4a37185ec2888d06eb726eb16.tar.gz
chromium_src-aa31281d74a2d0a4a37185ec2888d06eb726eb16.tar.bz2
Create a field trial to test if we can detect good QPC implementations.
We'd like to use QPC (TimeTicks::HighResNow) for all uses of TimeTicks. It's likely this will only work on some subset of Windows systems. This field trial is meant to determine if an implementation is good and if our heuristics are able to detect a good implementation. This particular CL checks for an Intel CPU parameter that indicates rdtsc is consistently incremented. Firefox uses the same check. I hope to determine that this is in fact correct and on which versions of Windows QPC calls rdtsc directly. We can add more heuristics later. BUG=158234 Review URL: https://chromiumcodereview.appspot.com/13583007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@197431 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/metrics/time_ticks_experiment_win.cc')
-rw-r--r--chrome/browser/metrics/time_ticks_experiment_win.cc108
1 files changed, 108 insertions, 0 deletions
diff --git a/chrome/browser/metrics/time_ticks_experiment_win.cc b/chrome/browser/metrics/time_ticks_experiment_win.cc
new file mode 100644
index 0000000..3e1250b
--- /dev/null
+++ b/chrome/browser/metrics/time_ticks_experiment_win.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/time_ticks_experiment_win.h"
+
+#if defined(OS_WIN)
+
+#include "base/cpu.h"
+#include "base/metrics/histogram.h"
+#include "base/win/windows_version.h"
+
+#include <windows.h>
+
+namespace chrome {
+
+namespace {
+
+const int kNumIterations = 1000;
+
+} // anonymous namespace
+
+void CollectTimeTicksStats() {
+ // This bit is supposed to indicate that rdtsc is safe across cores. If so, we
+ // can use QPC as long as it uses rdtsc.
+ // TODO(simonjam): We should look for other signals that QPC might be safe and
+ // test them out here.
+ base::CPU cpu;
+ UMA_HISTOGRAM_BOOLEAN("WinTimeTicks.NonStopTsc",
+ cpu.has_non_stop_time_stamp_counter());
+ if (!cpu.has_non_stop_time_stamp_counter()) {
+ return;
+ }
+
+ DWORD_PTR default_mask;
+ DWORD_PTR system_mask;
+ if (!GetProcessAffinityMask(GetCurrentProcess(),
+ &default_mask, &system_mask)) {
+ return;
+ }
+
+ SYSTEM_INFO sys_info;
+ GetSystemInfo(&sys_info);
+ DWORD num_cores = sys_info.dwNumberOfProcessors;
+ DWORD current_core = 0;
+ bool failed_to_change_cores = false;
+
+ base::win::OSInfo* info = base::win::OSInfo::GetInstance();
+ UMA_HISTOGRAM_ENUMERATION("WinTimeTicks.VersionTotal", info->version(),
+ base::win::VERSION_WIN_LAST);
+
+ LARGE_INTEGER qpc_frequency;
+ QueryPerformanceFrequency(&qpc_frequency);
+
+ int min_delta = 1e9;
+ LARGE_INTEGER qpc_last;
+ QueryPerformanceCounter(&qpc_last);
+ for (int i = 0; i < kNumIterations; ++i) {
+ LARGE_INTEGER qpc_now;
+ QueryPerformanceCounter(&qpc_now);
+ int delta = static_cast<int>(qpc_now.QuadPart - qpc_last.QuadPart);
+ if (delta != 0) {
+ min_delta = std::min(min_delta, delta);
+ }
+ qpc_last = qpc_now;
+
+ if (num_cores > 1 && (i % 100) == 0) {
+ ++current_core;
+ if (current_core > num_cores) {
+ current_core = 0;
+ }
+ if (!SetThreadAffinityMask(GetCurrentThread(), 1 << current_core)) {
+ failed_to_change_cores = true;
+ break;
+ }
+ }
+ }
+
+ if (num_cores > 1) {
+ SetThreadAffinityMask(GetCurrentThread(), default_mask);
+ if (failed_to_change_cores) {
+ UMA_HISTOGRAM_ENUMERATION("WinTimeTicks.FailedToChangeCores",
+ info->version(), base::win::VERSION_WIN_LAST);
+ return;
+ }
+ }
+
+ if (min_delta < 0) {
+ UMA_HISTOGRAM_ENUMERATION("WinTimeTicks.TickedBackwards", info->version(),
+ base::win::VERSION_WIN_LAST);
+ return;
+ }
+
+ int min_delta_ns = static_cast<int>(
+ min_delta * (1e9 / qpc_frequency.QuadPart));
+ UMA_HISTOGRAM_CUSTOM_COUNTS("WinTimeTicks.MinResolutionNanoseconds",
+ min_delta_ns, 1, 1000000, 50);
+
+ bool success = min_delta_ns <= 10000;
+ if (success) {
+ UMA_HISTOGRAM_ENUMERATION("WinTimeTicks.VersionSuccessful",
+ info->version(), base::win::VERSION_WIN_LAST);
+ }
+}
+
+} // namespace chrome
+
+#endif // defined(OS_WIN)