diff options
author | fmeawad@chromium.org <fmeawad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-06 06:21:18 +0000 |
---|---|---|
committer | fmeawad@chromium.org <fmeawad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-06 06:21:18 +0000 |
commit | 3687b2f8321ad2ddfc0dfbf51547fbdcc53491ad (patch) | |
tree | 4636403132db2c4fccf76cb3737907b4f05335f2 /base/time | |
parent | b55d82b903f41d485eb30c37baaa7a516e660fd2 (diff) | |
download | chromium_src-3687b2f8321ad2ddfc0dfbf51547fbdcc53491ad.zip chromium_src-3687b2f8321ad2ddfc0dfbf51547fbdcc53491ad.tar.gz chromium_src-3687b2f8321ad2ddfc0dfbf51547fbdcc53491ad.tar.bz2 |
Make QPCValueToMicroseconds faster in case the value is less than 44 bits
If the QPC value is less than 44 bits, it is safe to multiply by a 20 bits
value (1000000) without risking overflow. This optimization reduces the
call time by half.
BUG=158234
Review URL: https://codereview.chromium.org/429743002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287704 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/time')
-rw-r--r-- | base/time/time.h | 5 | ||||
-rw-r--r-- | base/time/time_win.cc | 14 | ||||
-rw-r--r-- | base/time/time_win_unittest.cc | 31 |
3 files changed, 45 insertions, 5 deletions
diff --git a/base/time/time.h b/base/time/time.h index 41d662a..79346f1 100644 --- a/base/time/time.h +++ b/base/time/time.h @@ -230,6 +230,11 @@ class BASE_EXPORT Time { // this global header and put in the platform-specific ones when we remove the // migration code. static const int64 kWindowsEpochDeltaMicroseconds; +#else + // To avoid overflow in QPC to Microseconds calculations, since we multiply + // by kMicrosecondsPerSecond, then the QPC value should not exceed + // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. + static const int64 kQPCOverflowThreshold = 0x8637BD05AF7; #endif // Represents an exploded time that can be formatted nicely. This is kind of diff --git a/base/time/time_win.cc b/base/time/time_win.cc index cf7be68..5fa899d 100644 --- a/base/time/time_win.cc +++ b/base/time/time_win.cc @@ -393,11 +393,14 @@ class HighResNowSingleton { int64 QPCValueToMicroseconds(LONGLONG qpc_value) { if (!ticks_per_second_) return 0; - - // Intentionally calculate microseconds in a round about manner to avoid - // overflow and precision issues. Think twice before simplifying! + // If the QPC Value is below the overflow threshold, we proceed with + // simple multiply and divide. + if (qpc_value < Time::kQPCOverflowThreshold) + return qpc_value * Time::kMicrosecondsPerSecond / ticks_per_second_; + // Otherwise, calculate microseconds in a round about manner to avoid + // overflow and precision issues. int64 whole_seconds = qpc_value / ticks_per_second_; - int64 leftover_ticks = qpc_value % ticks_per_second_; + int64 leftover_ticks = qpc_value - (whole_seconds * ticks_per_second_); int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) + ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_); @@ -447,7 +450,8 @@ NowFunction now_function = RolloverProtectedNow; bool CPUReliablySupportsHighResTime() { base::CPU cpu; - if (!cpu.has_non_stop_time_stamp_counter()) + if (!cpu.has_non_stop_time_stamp_counter() || + !GetHighResNowSingleton()->IsUsingHighResClock()) return false; if (IsBuggyAthlon(cpu)) diff --git a/base/time/time_win_unittest.cc b/base/time/time_win_unittest.cc index 46e256e..c6bb66c 100644 --- a/base/time/time_win_unittest.cc +++ b/base/time/time_win_unittest.cc @@ -241,3 +241,34 @@ TEST(TimeTicks, DISABLED_Drift) { printf("average time drift in microseconds: %lld\n", total_drift / kIterations); } + +int64 QPCValueToMicrosecondsSafely(LONGLONG qpc_value, + int64 ticks_per_second) { + int64 whole_seconds = qpc_value / ticks_per_second; + int64 leftover_ticks = qpc_value % ticks_per_second; + int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) + + ((leftover_ticks * Time::kMicrosecondsPerSecond) / + ticks_per_second); + return microseconds; +} + +TEST(TimeTicks, FromQPCValue) { + if (!TimeTicks::IsHighResClockWorking()) + return; + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + int64 ticks_per_second = frequency.QuadPart; + LONGLONG qpc_value = Time::kQPCOverflowThreshold; + TimeTicks expected_value = TimeTicks::FromInternalValue( + QPCValueToMicrosecondsSafely(qpc_value + 1, ticks_per_second)); + EXPECT_EQ(expected_value, + TimeTicks::FromQPCValue(qpc_value + 1)); + expected_value = TimeTicks::FromInternalValue( + QPCValueToMicrosecondsSafely(qpc_value, ticks_per_second)); + EXPECT_EQ(expected_value, + TimeTicks::FromQPCValue(qpc_value)); + expected_value = TimeTicks::FromInternalValue( + QPCValueToMicrosecondsSafely(qpc_value - 1, ticks_per_second)); + EXPECT_EQ(expected_value, + TimeTicks::FromQPCValue(qpc_value - 1)); +}
\ No newline at end of file |