summaryrefslogtreecommitdiffstats
path: root/base/time
diff options
context:
space:
mode:
authorfmeawad@chromium.org <fmeawad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-06 06:21:18 +0000
committerfmeawad@chromium.org <fmeawad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-06 06:21:18 +0000
commit3687b2f8321ad2ddfc0dfbf51547fbdcc53491ad (patch)
tree4636403132db2c4fccf76cb3737907b4f05335f2 /base/time
parentb55d82b903f41d485eb30c37baaa7a516e660fd2 (diff)
downloadchromium_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.h5
-rw-r--r--base/time/time_win.cc14
-rw-r--r--base/time/time_win_unittest.cc31
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