diff options
author | ernstm@chromium.org <ernstm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 06:36:04 +0000 |
---|---|---|
committer | ernstm@chromium.org <ernstm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 06:36:04 +0000 |
commit | 58cd0281ab5631db2ab8a56a4874347d8fb0c10f (patch) | |
tree | 902a93f8c2659a40bbf43de642d9eb2987c4e710 /base | |
parent | a9162fdc76b8806da3814f6d1b613c39ce509503 (diff) | |
download | chromium_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.h | 18 | ||||
-rw-r--r-- | base/time/time_mac.cc | 6 | ||||
-rw-r--r-- | base/time/time_posix.cc | 60 | ||||
-rw-r--r-- | base/time/time_unittest.cc | 23 | ||||
-rw-r--r-- | base/time/time_win.cc | 6 |
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(); } |