summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorernstm@chromium.org <ernstm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-31 06:36:04 +0000
committerernstm@chromium.org <ernstm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-31 06:36:04 +0000
commit58cd0281ab5631db2ab8a56a4874347d8fb0c10f (patch)
tree902a93f8c2659a40bbf43de642d9eb2987c4e710 /base
parenta9162fdc76b8806da3814f6d1b613c39ce509503 (diff)
downloadchromium_src-58cd0281ab5631db2ab8a56a4874347d8fb0c10f.zip
chromium_src-58cd0281ab5631db2ab8a56a4874347d8fb0c10f.tar.gz
chromium_src-58cd0281ab5631db2ab8a56a4874347d8fb0c10f.tar.bz2
base: Added thread-specific CPU-time clock
- TimeTicks::ThreadNow() measures the CPU time consumed by the calling thread (excluding time when the thread was de-scheduled). This features is needed for more accurate benchmarks. - Current implementation only supports Posix systems. Windows and Mac TBD. - Added unittest for new method. R=mark@chromium.org, nduca@chromium.org BUG=264306 Review URL: https://chromiumcodereview.appspot.com/20576003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214591 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/time/time.h18
-rw-r--r--base/time/time_mac.cc6
-rw-r--r--base/time/time_posix.cc60
-rw-r--r--base/time/time_unittest.cc23
-rw-r--r--base/time/time_win.cc6
5 files changed, 90 insertions, 23 deletions
diff --git a/base/time/time.h b/base/time/time.h
index 1299519..af95700 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -36,7 +36,7 @@
#endif
#if defined(OS_POSIX)
-// For struct timeval.
+#include <unistd.h>
#include <sys/time.h>
#endif
@@ -540,6 +540,22 @@ class BASE_EXPORT TimeTicks {
// SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED.
static TimeTicks HighResNow();
+ // Returns true if ThreadNow() is supported on this system.
+ static bool IsThreadNowSupported() {
+#if defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ // Returns thread-specific CPU-time on systems that support this feature.
+ // Needs to be guarded with a call to IsThreadNowSupported(). Use this timer
+ // to (approximately) measure how much time the calling thread spent doing
+ // actual work vs. being de-scheduled. May return bogus results if the thread
+ // migrates to another CPU between two calls.
+ static TimeTicks ThreadNow();
+
// Returns the current system trace time or, if none is defined, the current
// high-res time (i.e. HighResNow()). On systems where a global trace clock
// is defined, timestamping TraceEvents's with this value guarantees
diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc
index 962da6d..da46aa7 100644
--- a/base/time/time_mac.cc
+++ b/base/time/time_mac.cc
@@ -192,6 +192,12 @@ TimeTicks TimeTicks::HighResNow() {
}
// static
+TimeTicks TimeTicks::ThreadNow() {
+ NOTREACHED();
+ return TimeTicks();
+}
+
+// static
TimeTicks TimeTicks::NowFromSystemTraceTime() {
return HighResNow();
}
diff --git a/base/time/time_posix.cc b/base/time/time_posix.cc
index 64a65ea..16eb83c 100644
--- a/base/time/time_posix.cc
+++ b/base/time/time_posix.cc
@@ -9,7 +9,6 @@
#if defined(OS_ANDROID)
#include <time64.h>
#endif
-#include <unistd.h>
#include <limits>
@@ -62,6 +61,33 @@ void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
}
#endif // OS_ANDROID
+#if !defined(OS_MACOSX)
+// Helper function to get results from clock_gettime() as TimeTicks object.
+// Minimum requirement is MONOTONIC_CLOCK to be supported on the system.
+// FreeBSD 6 has CLOCK_MONOTONIC but defines _POSIX_MONOTONIC_CLOCK to -1.
+#if (defined(OS_POSIX) && \
+ defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
+ defined(OS_BSD) || defined(OS_ANDROID)
+base::TimeTicks ClockNow(clockid_t clk_id) {
+ uint64_t absolute_micro;
+
+ struct timespec ts;
+ if (clock_gettime(clk_id, &ts) != 0) {
+ NOTREACHED() << "clock_gettime(" << clk_id << ") failed.";
+ return base::TimeTicks();
+ }
+
+ absolute_micro =
+ (static_cast<int64>(ts.tv_sec) * base::Time::kMicrosecondsPerSecond) +
+ (static_cast<int64>(ts.tv_nsec) / base::Time::kNanosecondsPerMicrosecond);
+
+ return base::TimeTicks::FromInternalValue(absolute_micro);
+}
+#else // _POSIX_MONOTONIC_CLOCK
+#error No usable tick clock function on this platform.
+#endif // _POSIX_MONOTONIC_CLOCK
+#endif // !defined(OS_MACOSX)
+
} // namespace
namespace base {
@@ -228,36 +254,26 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) {
}
// TimeTicks ------------------------------------------------------------------
-// FreeBSD 6 has CLOCK_MONOLITHIC but defines _POSIX_MONOTONIC_CLOCK to -1.
-#if (defined(OS_POSIX) && \
- defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
- defined(OS_BSD) || defined(OS_ANDROID)
-
// static
TimeTicks TimeTicks::Now() {
- uint64_t absolute_micro;
-
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
- NOTREACHED() << "clock_gettime(CLOCK_MONOTONIC) failed.";
- return TimeTicks();
- }
-
- absolute_micro =
- (static_cast<int64>(ts.tv_sec) * Time::kMicrosecondsPerSecond) +
- (static_cast<int64>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond);
-
- return TimeTicks(absolute_micro);
+ return ClockNow(CLOCK_MONOTONIC);
}
-#else // _POSIX_MONOTONIC_CLOCK
-#error No usable tick clock function on this platform.
-#endif // _POSIX_MONOTONIC_CLOCK
// static
TimeTicks TimeTicks::HighResNow() {
return Now();
}
+// static
+TimeTicks TimeTicks::ThreadNow() {
+#if defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)
+ return ClockNow(CLOCK_THREAD_CPUTIME_ID);
+#else
+ NOTREACHED();
+ return TimeTicks();
+#endif
+}
+
#if defined(OS_CHROMEOS)
// Force definition of the system trace clock; it is a chromeos-only api
// at the moment and surfacing it in the right place requires mucking
diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc
index d25c441..29ceff0 100644
--- a/base/time/time_unittest.cc
+++ b/base/time/time_unittest.cc
@@ -7,6 +7,7 @@
#include <time.h>
#include "base/compiler_specific.h"
+#include "base/rand_util.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -611,6 +612,28 @@ TEST(TimeTicks, HighResNow) {
HighResClockTest(&TimeTicks::HighResNow);
}
+TEST(TimeTicks, ThreadNow) {
+ if (TimeTicks::IsThreadNowSupported()) {
+ TimeTicks begin = TimeTicks::Now();
+ TimeTicks begin_thread = TimeTicks::ThreadNow();
+ // Do some arbitrary work
+ double accu = 0.0f;
+ for (double i = 0; i < 1e4f; i++)
+ accu += base::RandDouble();
+ // Sleep for 10 milliseconds to get the thread de-scheduled
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
+ TimeTicks end_thread = TimeTicks::ThreadNow();
+ TimeTicks end = TimeTicks::Now();
+ TimeDelta delta = end - begin;
+ TimeDelta delta_thread = end_thread - begin_thread;
+ TimeDelta difference = delta - delta_thread;
+ // Make a decision based on accu's value to prevent the compiler from
+ // optimizing away its computation (we don't care what the actual value is)
+ EXPECT_GE(accu, 0.0f);
+ EXPECT_GE(difference.InMicroseconds(), 9000);
+ }
+}
+
TEST(TimeTicks, NowFromSystemTraceTime) {
// Re-use HighResNow test for now since clock properties are identical.
HighResClockTest(&TimeTicks::NowFromSystemTraceTime);
diff --git a/base/time/time_win.cc b/base/time/time_win.cc
index 81b2527..3680ee2a 100644
--- a/base/time/time_win.cc
+++ b/base/time/time_win.cc
@@ -457,6 +457,12 @@ TimeTicks TimeTicks::HighResNow() {
}
// static
+TimeTicks TimeTicks::ThreadNow() {
+ NOTREACHED();
+ return TimeTicks();
+}
+
+// static
TimeTicks TimeTicks::NowFromSystemTraceTime() {
return HighResNow();
}