summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Timer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/Common/Timer.cpp')
-rw-r--r--Source/Core/Common/Timer.cpp247
1 files changed, 53 insertions, 194 deletions
diff --git a/Source/Core/Common/Timer.cpp b/Source/Core/Common/Timer.cpp
index f6d4c983cb..fb81164390 100644
--- a/Source/Core/Common/Timer.cpp
+++ b/Source/Core/Common/Timer.cpp
@@ -4,180 +4,75 @@
#include "Common/Timer.h"
#include <chrono>
-#include <string>
#ifdef _WIN32
-#include <cwchar>
-
-#include <windows.h>
-#include <mmsystem.h>
-#include <sys/timeb.h>
+#include <Windows.h>
+#include <timeapi.h>
#else
#include <sys/time.h>
#endif
-#include <fmt/format.h>
-
#include "Common/CommonTypes.h"
-#include "Common/StringUtil.h"
namespace Common
{
-u32 Timer::GetTimeMs()
+template <typename Clock, typename Duration>
+static typename Clock::rep time_now()
{
-#ifdef _WIN32
- return timeGetTime();
-#elif defined __APPLE__
- struct timeval t;
- (void)gettimeofday(&t, nullptr);
- return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
-#else
- struct timespec t;
- (void)clock_gettime(CLOCK_MONOTONIC, &t);
- return ((u32)(t.tv_sec * 1000 + t.tv_nsec / 1000000));
-#endif
+ return std::chrono::time_point_cast<Duration>(Clock::now()).time_since_epoch().count();
}
-#ifdef _WIN32
-double GetFreq()
+template <typename Duration>
+static auto steady_time_now()
{
- LARGE_INTEGER freq;
- QueryPerformanceFrequency(&freq);
- return 1000000.0 / double(freq.QuadPart);
+ return time_now<std::chrono::steady_clock, Duration>();
}
-#endif
-u64 Timer::GetTimeUs()
+u64 Timer::NowUs()
{
-#ifdef _WIN32
- LARGE_INTEGER time;
- static double freq = GetFreq();
- QueryPerformanceCounter(&time);
- return u64(double(time.QuadPart) * freq);
-#elif defined __APPLE__
- struct timeval t;
- (void)gettimeofday(&t, nullptr);
- return ((u64)(t.tv_sec * 1000000 + t.tv_usec));
-#else
- struct timespec t;
- (void)clock_gettime(CLOCK_MONOTONIC, &t);
- return ((u64)(t.tv_sec * 1000000 + t.tv_nsec / 1000));
-#endif
+ return steady_time_now<std::chrono::microseconds>();
}
-// --------------------------------------------
-// Initiate, Start, Stop, and Update the time
-// --------------------------------------------
-
-// Set initial values for the class
-Timer::Timer() : m_LastTime(0), m_StartTime(0), m_Running(false)
+u64 Timer::NowMs()
{
- Update();
+ return steady_time_now<std::chrono::milliseconds>();
}
-// Write the starting time
void Timer::Start()
{
- m_StartTime = GetTimeMs();
- m_Running = true;
-}
-
-// Stop the timer
-void Timer::Stop()
-{
- // Write the final time
- m_LastTime = GetTimeMs();
- m_Running = false;
-}
-
-// Update the last time variable
-void Timer::Update()
-{
- m_LastTime = GetTimeMs();
- // TODO(ector) - QPF
-}
-
-// -------------------------------------
-// Get time difference and elapsed time
-// -------------------------------------
-
-// Get the number of milliseconds since the last Update()
-u64 Timer::GetTimeDifference()
-{
- return GetTimeMs() - m_LastTime;
-}
-
-// Add the time difference since the last Update() to the starting time.
-// This is used to compensate for a paused game.
-void Timer::AddTimeDifference()
-{
- m_StartTime += GetTimeDifference();
-}
-
-// Get the time elapsed since the Start()
-u64 Timer::GetTimeElapsed()
-{
- // If we have not started yet, return zero
- if (m_StartTime == 0)
- return 0;
-
- // Return the final timer time if the timer is stopped
- if (!m_Running)
- return (m_LastTime - m_StartTime);
-
- return (GetTimeMs() - m_StartTime);
-}
-
-// Get the formatted time elapsed since the Start()
-std::string Timer::GetTimeElapsedFormatted() const
-{
- // If we have not started yet, return zero
- if (m_StartTime == 0)
- return "00:00:00:000";
-
- // The number of milliseconds since the start.
- // Use a different value if the timer is stopped.
- u64 Milliseconds;
- if (m_Running)
- Milliseconds = GetTimeMs() - m_StartTime;
- else
- Milliseconds = m_LastTime - m_StartTime;
- // Seconds
- u32 Seconds = (u32)(Milliseconds / 1000);
- // Minutes
- u32 Minutes = Seconds / 60;
- // Hours
- u32 Hours = Minutes / 60;
-
- return fmt::format("{:02}:{:02}:{:02}:{:03}", Hours, Minutes % 60, Seconds % 60,
- Milliseconds % 1000);
+ m_start_ms = NowMs();
+ m_end_ms = 0;
+ m_running = true;
}
-// Get current time
-void Timer::IncreaseResolution()
+void Timer::StartWithOffset(u64 offset)
{
-#ifdef _WIN32
- timeBeginPeriod(1);
-#endif
+ Start();
+ m_start_ms -= offset;
}
-void Timer::RestoreResolution()
+void Timer::Stop()
{
-#ifdef _WIN32
- timeEndPeriod(1);
-#endif
+ m_end_ms = NowMs();
+ m_running = false;
}
-// Get the number of seconds since January 1 1970
-u64 Timer::GetTimeSinceJan1970()
+u64 Timer::ElapsedMs() const
{
- time_t ltime;
- time(&ltime);
- return ((u64)ltime);
+ 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()
{
+#ifdef _MSC_VER
+ std::chrono::zoned_seconds seconds(
+ std::chrono::current_zone(),
+ std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()));
+ return seconds.get_local_time().time_since_epoch().count();
+#else
time_t sysTime, tzDiff, tzDST;
time(&sysTime);
tm* gmTime = localtime(&sysTime);
@@ -193,72 +88,36 @@ u64 Timer::GetLocalTimeSinceJan1970()
tzDiff = sysTime - mktime(gmTime);
return static_cast<u64>(sysTime + tzDiff + tzDST);
+#endif
}
-// Return the current time formatted as Minutes:Seconds:Milliseconds
-// in the form 00:00:000.
-std::string Timer::GetTimeFormatted()
+void Timer::IncreaseResolution()
{
- time_t sysTime;
- time(&sysTime);
-
- struct tm* gmTime = localtime(&sysTime);
-
-#ifdef _WIN32
- wchar_t tmp[13];
- wcsftime(tmp, 6, L"%M:%S", gmTime);
-#else
- char tmp[13];
- strftime(tmp, 6, "%M:%S", gmTime);
-#endif
-
-// Now tack on the milliseconds
#ifdef _WIN32
- struct timeb tp;
- (void)::ftime(&tp);
- return WStringToUTF8(tmp) + fmt::format(":{:03}", tp.millitm);
-#elif defined __APPLE__
- struct timeval t;
- (void)gettimeofday(&t, nullptr);
- return fmt::format("{}:{:03}", tmp, t.tv_usec / 1000);
-#else
- struct timespec t;
- (void)clock_gettime(CLOCK_MONOTONIC, &t);
- return fmt::format("{}:{:03}", tmp, t.tv_nsec / 1000000);
+ // 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
}
-// Returns a timestamp with decimals for precise time comparisons
-double Timer::GetDoubleTime()
-{
- // FYI: std::chrono::system_clock epoch is not required to be 1970 until c++20.
- // We will however assume time_t IS unix time.
- using Clock = std::chrono::system_clock;
-
- // TODO: Use this on switch to c++20:
- // const auto since_epoch = Clock::now().time_since_epoch();
- const auto unix_epoch = Clock::from_time_t({});
- const auto since_epoch = Clock::now() - unix_epoch;
-
- const auto since_double_time_epoch = since_epoch - std::chrono::seconds(DOUBLE_TIME_OFFSET);
- return std::chrono::duration_cast<std::chrono::duration<double>>(since_double_time_epoch).count();
-}
-
-// Formats a timestamp from GetDoubleTime() into a date and time string
-std::string Timer::GetDateTimeFormatted(double time)
+void Timer::RestoreResolution()
{
- // revert adjustments from GetDoubleTime() to get a normal Unix timestamp again
- time_t seconds = (time_t)time + DOUBLE_TIME_OFFSET;
- tm* localTime = localtime(&seconds);
-
#ifdef _WIN32
- wchar_t tmp[32] = {};
- wcsftime(tmp, std::size(tmp), L"%x %X", localTime);
- return WStringToUTF8(tmp);
-#else
- char tmp[32] = {};
- strftime(tmp, sizeof(tmp), "%x %X", localTime);
- return tmp;
+ timeEndPeriod(1);
#endif
}