// 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 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(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( 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)