Timer.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "Common/Timer.h"
  4. #include <chrono>
  5. #ifdef _WIN32
  6. #include <Windows.h>
  7. #include <ctime>
  8. #include <timeapi.h>
  9. #else
  10. #include <sys/time.h>
  11. #endif
  12. #include "Common/CommonTypes.h"
  13. namespace Common
  14. {
  15. template <typename Clock, typename Duration>
  16. static typename Clock::rep time_now()
  17. {
  18. return std::chrono::time_point_cast<Duration>(Clock::now()).time_since_epoch().count();
  19. }
  20. template <typename Duration>
  21. static auto steady_time_now()
  22. {
  23. return time_now<std::chrono::steady_clock, Duration>();
  24. }
  25. u64 Timer::NowUs()
  26. {
  27. return steady_time_now<std::chrono::microseconds>();
  28. }
  29. u64 Timer::NowMs()
  30. {
  31. return steady_time_now<std::chrono::milliseconds>();
  32. }
  33. void Timer::Start()
  34. {
  35. m_start_ms = NowMs();
  36. m_end_ms = 0;
  37. m_running = true;
  38. }
  39. void Timer::StartWithOffset(u64 offset)
  40. {
  41. Start();
  42. m_start_ms -= offset;
  43. }
  44. void Timer::Stop()
  45. {
  46. m_end_ms = NowMs();
  47. m_running = false;
  48. }
  49. u64 Timer::ElapsedMs() const
  50. {
  51. const u64 end = m_running ? NowMs() : m_end_ms;
  52. // Can handle up to 1 rollover event (underflow produces correct result)
  53. // If Start() has never been called, will return 0
  54. return end - m_start_ms;
  55. }
  56. u64 Timer::GetLocalTimeSinceJan1970()
  57. {
  58. // TODO Would really, really like to use std::chrono here, but Windows did not support
  59. // std::chrono::current_zone() until 19H1, and other compilers don't even provide support for
  60. // timezone-related parts of chrono. Someday!
  61. // see https://bugs.dolphin-emu.org/issues/13007#note-4
  62. time_t sysTime, tzDiff, tzDST;
  63. time(&sysTime);
  64. tm* gmTime = localtime(&sysTime);
  65. // Account for DST where needed
  66. if (gmTime->tm_isdst == 1)
  67. tzDST = 3600;
  68. else
  69. tzDST = 0;
  70. // Lazy way to get local time in sec
  71. gmTime = gmtime(&sysTime);
  72. tzDiff = sysTime - mktime(gmTime);
  73. return static_cast<u64>(sysTime + tzDiff + tzDST);
  74. }
  75. void Timer::IncreaseResolution()
  76. {
  77. #ifdef _WIN32
  78. // Disable execution speed and timer resolution throttling process-wide.
  79. // This mainly will keep Dolphin marked as high performance if it's in the background. The OS
  80. // should make it high performance if it's in the foreground anyway (or for some specific
  81. // threads e.g. audio).
  82. // This is best-effort (i.e. the call may fail on older versions of Windows, where such throttling
  83. // doesn't exist, anyway), and we don't bother reverting once set.
  84. // This adjusts behavior on CPUs with "performance" and "efficiency" cores
  85. PROCESS_POWER_THROTTLING_STATE PowerThrottling{};
  86. PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
  87. PowerThrottling.ControlMask =
  88. PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
  89. PowerThrottling.StateMask = 0;
  90. SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling,
  91. sizeof(PowerThrottling));
  92. // Not actually sure how useful this is these days.. :')
  93. timeBeginPeriod(1);
  94. #endif
  95. }
  96. void Timer::RestoreResolution()
  97. {
  98. #ifdef _WIN32
  99. timeEndPeriod(1);
  100. #endif
  101. }
  102. } // Namespace Common