From 248fce09b5474dd65a4a4f9ad8f004bfb8209b13 Mon Sep 17 00:00:00 2001 From: Christopher Dykes Date: Wed, 22 Mar 2017 11:42:02 -0700 Subject: [PATCH] Use Folly's VDSO wrapper Summary: Because it falls back to an implementation that works on all platforms that HHVM supports. This also allows the logic in a few other places to be simplified due to the fact that Folly's portability headers implement `clock_gettime` for OSX, including thread cpu time. Reviewed By: bmaurer Differential Revision: D3903554 fbshipit-source-id: 84140a0e14ca75f66b23949f88da2f1f30c5a732 --- hphp/runtime/ext/hotprofiler/ext_hotprofiler.cpp | 21 +-------- hphp/runtime/ext/xhprof/ext_xhprof.cpp | 12 ----- hphp/util/timer.cpp | 60 ++---------------------- hphp/util/{vdso.h => vdso.cpp} | 45 ++++++++++++------ hphp/util/vdso.h | 9 ++-- 5 files changed, 41 insertions(+), 106 deletions(-) copy hphp/util/{vdso.h => vdso.cpp} (58%) diff --git a/hphp/runtime/ext/hotprofiler/ext_hotprofiler.cpp b/hphp/runtime/ext/hotprofiler/ext_hotprofiler.cpp index 667f95833dd..a5b6b034f27 100644 --- a/hphp/runtime/ext/hotprofiler/ext_hotprofiler.cpp +++ b/hphp/runtime/ext/hotprofiler/ext_hotprofiler.cpp @@ -232,31 +232,14 @@ tv_to_cycles(const struct timeval& tv, int64_t MHz) static inline uint64_t to_usec(int64_t cycles, int64_t MHz, bool cpu_time = false) { - static bool vdso_usable = -#ifdef CLOCK_THREAD_CPUTIME_ID - vdso::clock_gettime_ns(CLOCK_THREAD_CPUTIME_ID) >= 0 -#else - false -#endif - ; - - if (cpu_time && vdso_usable) { + if (cpu_time) { return cycles / 1000; } return (cycles + MHz/2) / MHz; } static inline uint64_t cpuTime(int64_t MHz) { -#ifdef CLOCK_THREAD_CPUTIME_ID - auto const rval = vdso::clock_gettime_ns(CLOCK_THREAD_CPUTIME_ID); - if (rval >= 0) { - return rval; - } -#endif - struct rusage usage; - getrusage(RUSAGE_SELF, &usage); - return - tv_to_cycles(usage.ru_utime, MHz) + tv_to_cycles(usage.ru_stime, MHz); + return vdso::clock_gettime_ns(CLOCK_THREAD_CPUTIME_ID); } uint64_t diff --git a/hphp/runtime/ext/xhprof/ext_xhprof.cpp b/hphp/runtime/ext/xhprof/ext_xhprof.cpp index f21e3b396bf..58f25fe9c29 100644 --- a/hphp/runtime/ext/xhprof/ext_xhprof.cpp +++ b/hphp/runtime/ext/xhprof/ext_xhprof.cpp @@ -48,18 +48,6 @@ void HHVM_FUNCTION(xhprof_enable, int64_t flags/* = 0 */, return; } - bool missingClockGetTimeNS = true; -#ifdef CLOCK_THREAD_CPUTIME_ID - missingClockGetTimeNS = vdso::clock_gettime_ns(CLOCK_THREAD_CPUTIME_ID) == -1; -#endif - - if (missingClockGetTimeNS) { - // Both TrackVtsc and TrackCPU mean "do CPU time profiling". - // - // TrackVtsc means: require clock_gettime, or else no data. - // TrackCPU means: prefer clock_gettime, but fall back to getrusage. - flags &= ~TrackVtsc; - } if (flags & TrackVtsc) { flags |= TrackCPU; } diff --git a/hphp/util/timer.cpp b/hphp/util/timer.cpp index 2980567d788..f22e504c95f 100644 --- a/hphp/util/timer.cpp +++ b/hphp/util/timer.cpp @@ -17,11 +17,6 @@ #include -#ifdef __APPLE__ -#include -#include -#endif - #include #include @@ -51,26 +46,6 @@ namespace { default: not_reached(); \ } -int gettime_helper(clockid_t clock, timespec* ts) { -#ifdef _MSC_VER - // Let's bypass trying to load vdso. - return clock_gettime(clock, ts); -#elif defined(__APPLE__) || defined(__FreeBSD__) - // XXX: OSX doesn't support realtime so we ignore 'clock'. - timeval tv; - auto const ret = gettimeofday(&tv, nullptr); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; - return ret; -#else - static bool vdso_usable = vdso::clock_gettime(clock, ts) == 0; - if (vdso_usable) { - return vdso::clock_gettime(clock, ts); - } - return clock_gettime(clock, ts); -#endif -} - /////////////////////////////////////////////////////////////////////////////// } @@ -101,27 +76,11 @@ void Timer::report() const { } void Timer::GetMonotonicTime(timespec &ts) { -#ifndef __APPLE__ - gettime(CLOCK_MONOTONIC, &ts); -#else - timeval tv; - gettimeofday(&tv, nullptr); - TIMEVAL_TO_TIMESPEC(&tv, &ts); -#endif + vdso::clock_gettime(CLOCK_MONOTONIC, &ts); } void Timer::GetRealtimeTime(timespec &ts) { -#ifndef __APPLE__ - clock_gettime(CLOCK_REALTIME, &ts); -#else - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - ts.tv_sec = mts.tv_sec; - ts.tv_nsec = mts.tv_nsec; -#endif + vdso::clock_gettime(CLOCK_REALTIME, &ts); } static int64_t to_usec(const timeval& tv) { @@ -151,16 +110,7 @@ int64_t Timer::GetRusageMicros(Type t, Who who) { } int64_t Timer::GetThreadCPUTimeNanos() { -#ifdef CLOCK_THREAD_CPUTIME_ID - auto const ns = vdso::clock_gettime_ns(CLOCK_THREAD_CPUTIME_ID); - if (ns != -1) return ns; -#endif - -#ifdef RUSAGE_THREAD - return GetRusageMicros(TotalCPU, Thread) * 1000; -#else - return -1; -#endif + return vdso::clock_gettime_ns(CLOCK_THREAD_CPUTIME_ID); } int64_t Timer::measure() const { @@ -205,8 +155,7 @@ int64_t SlowTimer::getTime() const { /////////////////////////////////////////////////////////////////////////////// int gettime(clockid_t clock, timespec* ts) { - auto const ret = gettime_helper(clock, ts); -#ifdef CLOCK_THREAD_CPUTIME_ID + auto const ret = vdso::clock_gettime(clock, ts); if (clock == CLOCK_THREAD_CPUTIME_ID) { always_assert(ts->tv_nsec < 1000000000); @@ -218,7 +167,6 @@ int gettime(clockid_t clock, timespec* ts) { } ts->tv_nsec = res; } -#endif return ret; } diff --git a/hphp/util/vdso.h b/hphp/util/vdso.cpp similarity index 58% copy from hphp/util/vdso.h copy to hphp/util/vdso.cpp index f55113217bb..d9f4b948139 100644 --- a/hphp/util/vdso.h +++ b/hphp/util/vdso.cpp @@ -14,26 +14,41 @@ +----------------------------------------------------------------------+ */ -#ifndef incl_HPHP_UTIL_VDSO_H -#define incl_HPHP_UTIL_VDSO_H +#include "hphp/util/vdso.h" -#include "hphp/util/compatibility.h" +#ifdef FACEBOOK +#include "common/time/ClockGettimeNS.h" // nolint +#endif + +#include namespace HPHP { namespace vdso { -/////////////////////////////////////////////////////////////////////////////// -/* - * Tries to call __vdso_clock_gettime(). Will return -1 on error. - */ -int clock_gettime(clockid_t, timespec*); +int clock_gettime(clockid_t clock, timespec* ts) { +#ifdef FACEBOOK + uint64_t time; + constexpr uint64_t sec_to_ns = 1000000000; -/* - * A custom version of vdso::clock_gettime() that returns its result in - * nanoseconds. Not usable outside of internal facebook code. - */ -int64_t clock_gettime_ns(clockid_t); + if (clock == CLOCK_THREAD_CPUTIME_ID && + !fb_perf_get_thread_cputime_ns(&time)) { + ts->tv_sec = time / sec_to_ns; + ts->tv_nsec = time % sec_to_ns; + return 0; + } +#endif + return folly::chrono::clock_gettime(clock, ts); +} -//////////////////////////////////////////////////////////////////////////////// -}} +int64_t clock_gettime_ns(clockid_t clock) { +#ifdef FACEBOOK + uint64_t time; + if (clock == CLOCK_THREAD_CPUTIME_ID && + !fb_perf_get_thread_cputime_ns(&time)) { + return time; + } #endif + return folly::chrono::clock_gettime_ns(clock); +} + +}} diff --git a/hphp/util/vdso.h b/hphp/util/vdso.h index f55113217bb..1ee502fa037 100644 --- a/hphp/util/vdso.h +++ b/hphp/util/vdso.h @@ -17,19 +17,20 @@ #ifndef incl_HPHP_UTIL_VDSO_H #define incl_HPHP_UTIL_VDSO_H -#include "hphp/util/compatibility.h" +#include namespace HPHP { namespace vdso { /////////////////////////////////////////////////////////////////////////////// /* - * Tries to call __vdso_clock_gettime(). Will return -1 on error. + * Calls __vdso_clock_gettime() if available, otherwise falls back + * to calling clock_gettime(). */ int clock_gettime(clockid_t, timespec*); /* - * A custom version of vdso::clock_gettime() that returns its result in - * nanoseconds. Not usable outside of internal facebook code. + * A custom version of clock_gettime() that returns its result in + * nanoseconds. */ int64_t clock_gettime_ns(clockid_t); -- 2.11.4.GIT