Index: base/time/time_win.cc |
diff --git a/base/time/time_win.cc b/base/time/time_win.cc |
index b81cadf39f67207d2c5e4988d7674c21bf10aafb..ff1e0169daf2f3853cf8b58de80634c0f6bb2882 100644 |
--- a/base/time/time_win.cc |
+++ b/base/time/time_win.cc |
@@ -95,6 +95,15 @@ const int kMinTimerIntervalLowResMs = 4; |
bool g_high_res_timer_enabled = false; |
// How many times the high resolution timer has been called. |
uint32_t g_high_res_timer_count = 0; |
+// Start time of the high resolution timer usage monitoring. This is needed |
+// to calculate the usage as percentage of the total elapsed time. |
+TimeTicks g_high_res_timer_usage_start; |
+// The cumulative time the high resolution timer has been in use since |
+// |g_high_res_timer_usage_start| moment. |
+TimeDelta g_high_res_timer_usage; |
+// Timestamp of the last activation change of the high resolution timer. This |
+// is used to calculate the cumulative usage. |
+TimeTicks g_high_res_timer_last_activation; |
// The lock to control access to the above two variables. |
base::Lock* GetHighResLock() { |
static auto* lock = new base::Lock(); |
@@ -218,13 +227,18 @@ bool Time::ActivateHighResolutionTimer(bool activating) { |
if (activating) { |
DCHECK_NE(g_high_res_timer_count, max); |
++g_high_res_timer_count; |
- if (g_high_res_timer_count == 1) |
+ if (g_high_res_timer_count == 1) { |
+ g_high_res_timer_last_activation = TimeTicks::Now(); |
timeBeginPeriod(period); |
+ } |
} else { |
DCHECK_NE(g_high_res_timer_count, 0u); |
--g_high_res_timer_count; |
- if (g_high_res_timer_count == 0) |
+ if (g_high_res_timer_count == 0) { |
+ g_high_res_timer_usage += |
+ TimeTicks::Now() - g_high_res_timer_last_activation; |
timeEndPeriod(period); |
+ } |
} |
return (period == kMinTimerIntervalHighResMs); |
} |
@@ -236,6 +250,35 @@ bool Time::IsHighResolutionTimerInUse() { |
} |
// static |
+void Time::ResetHighResolutionTimerUsage() { |
+ base::AutoLock lock(*GetHighResLock()); |
+ g_high_res_timer_usage = TimeDelta(); |
+ g_high_res_timer_usage_start = TimeTicks::Now(); |
+ if (g_high_res_timer_count > 0) |
+ g_high_res_timer_last_activation = g_high_res_timer_usage_start; |
+} |
+ |
+// static |
+double Time::GetHighResolutionTimerUsage() { |
+ base::AutoLock lock(*GetHighResLock()); |
+ TimeTicks now = TimeTicks::Now(); |
+ TimeDelta elapsed_time = now - g_high_res_timer_usage_start; |
+ if (elapsed_time.is_zero()) { |
+ // This is unexpected but possible if TimeTicks resolution is low and |
+ // GetHighResolutionTimerUsage() is called promptly after |
+ // ResetHighResolutionTimerUsage(). |
+ return 0.0; |
+ } |
+ TimeDelta used_time = g_high_res_timer_usage; |
+ if (g_high_res_timer_count > 0) { |
+ // If currently activated add the remainder of time since the last |
+ // activation. |
+ used_time += now - g_high_res_timer_last_activation; |
+ } |
+ return used_time.InMillisecondsF() / elapsed_time.InMillisecondsF() * 100; |
+} |
+ |
+// static |
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { |
// Create the system struct representing our exploded time. It will either be |
// in local time or UTC.If casting from int to WORD results in overflow, |