From 537ed7500c087786f28f51ff5222f1c2113776d3 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 6 May 2015 22:06:00 -0700 Subject: [PATCH] Use CLOCK_REALTIME_COARSE when available. On systems that have CLOCK_REALTIME_COARSE with good enough resolution, we can avoid making a system call to get the current time; it's serviced from the vDSO. BUG= LOG=N Review URL: https://codereview.chromium.org/1125003002 Cr-Commit-Position: refs/heads/master@{#28280} --- src/base/platform/time.cc | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/base/platform/time.cc b/src/base/platform/time.cc index b6a11cf..cb38deb 100644 --- a/src/base/platform/time.cc +++ b/src/base/platform/time.cc @@ -24,6 +24,11 @@ #include "src/base/logging.h" #include "src/base/platform/platform.h" +// CLOCK_REALTIME_COARSE was added in Linux 2.6.32. +#if V8_OS_LINUX && !defined(CLOCK_REALTIME_COARSE) +#define CLOCK_REALTIME_COARSE 5 +#endif + namespace v8 { namespace base { @@ -252,11 +257,44 @@ FILETIME Time::ToFiletime() const { #elif V8_OS_POSIX Time Time::Now() { +#ifdef CLOCK_REALTIME_COARSE + struct timespec ts; + // clockid_t is an int32_t; loads and stores are atomic. + static const clockid_t kInvalidClockId = static_cast(-1); + static clockid_t clock_id = kInvalidClockId; + if (V8_UNLIKELY(clock_id == kInvalidClockId)) { + // CLOCK_REALTIME_COARSE is not supported on Linux kernels < 2.6.32. + // Probe the kernel to see if it's available and has <= 1 ms resolution. + // + // CLOCK_REALTIME_COARSE, unlike CLOCK_REALTIME, can often be serviced + // entirely from the vDSO without the need to make a system call. + // It can have a dramatic impact on applications that frequently + // query the current time. + // + // One caveat is that CLOCK_REALTIME_COARSE is tied to CONFIG_HZ, the + // number of ticks per second that the kernel runs at. Its granularity + // can be as low as one update every 300 ms so we need to make sure that + // it is accurate enough. Fortunately, many if not most kernels are built + // with CONFIG_HZ=1000, giving it a one millisecond precision and that is + // good enough for our purposes. + if (clock_getres(CLOCK_REALTIME_COARSE, &ts) < 0 || ts.tv_sec > 0 || + ts.tv_nsec > 1000 * 1000) { + clock_id = CLOCK_REALTIME; // Not available or not suitable. + } else { + clock_id = CLOCK_REALTIME_COARSE; + } + } + int result = clock_gettime(clock_id, &ts); + DCHECK_EQ(0, result); + USE(result); + return FromTimespec(ts); +#else struct timeval tv; int result = gettimeofday(&tv, NULL); DCHECK_EQ(0, result); USE(result); return FromTimeval(tv); +#endif } -- 2.7.4