// Copyright 2008 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "Common/Timer.h" #include #ifdef _WIN32 #include #include #include #else #include #endif #include "Common/CommonTypes.h" namespace Common { template static typename Clock::rep time_now() { return std::chrono::time_point_cast(Clock::now()).time_since_epoch().count(); } template static auto steady_time_now() { return time_now(); } u64 Timer::NowUs() { return steady_time_now(); } u64 Timer::NowMs() { return steady_time_now(); } void Timer::Start() { m_start_ms = NowMs(); m_end_ms = 0; m_running = true; } void Timer::StartWithOffset(u64 offset) { Start(); m_start_ms -= offset; } void Timer::Stop() { m_end_ms = NowMs(); m_running = false; } u64 Timer::ElapsedMs() const { const u64 end = m_running ? NowMs() : m_end_ms; // Can handle up to 1 rollover event (underflow produces correct result) // If Start() has never been called, will return 0 return end - m_start_ms; } u64 Timer::GetLocalTimeSinceJan1970() { // TODO Would really, really like to use std::chrono here, but Windows did not support // std::chrono::current_zone() until 19H1, and other compilers don't even provide support for // timezone-related parts of chrono. Someday! // see https://bugs.dolphin-emu.org/issues/13007#note-4 time_t sysTime, tzDiff, tzDST; time(&sysTime); tm* gmTime = localtime(&sysTime); // Account for DST where needed if (gmTime->tm_isdst == 1) tzDST = 3600; else tzDST = 0; // Lazy way to get local time in sec gmTime = gmtime(&sysTime); tzDiff = sysTime - mktime(gmTime); return static_cast(sysTime + tzDiff + tzDST); } void Timer::IncreaseResolution() { #ifdef _WIN32 // Disable execution speed and timer resolution throttling process-wide. // This mainly will keep Dolphin marked as high performance if it's in the background. The OS // should make it high performance if it's in the foreground anyway (or for some specific // threads e.g. audio). // This is best-effort (i.e. the call may fail on older versions of Windows, where such throttling // doesn't exist, anyway), and we don't bother reverting once set. // This adjusts behavior on CPUs with "performance" and "efficiency" cores PROCESS_POWER_THROTTLING_STATE PowerThrottling{}; PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION; PowerThrottling.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION; PowerThrottling.StateMask = 0; SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling, sizeof(PowerThrottling)); // Not actually sure how useful this is these days.. :') timeBeginPeriod(1); #endif } void Timer::RestoreResolution() { #ifdef _WIN32 timeEndPeriod(1); #endif } } // Namespace Common