Commit e4168e88 authored by gejun's avatar gejun

Remove fast_realtime* & monotonic_time and cpuwide_time is callable before…

Remove fast_realtime* & monotonic_time and cpuwide_time is callable before main() & remove CLOCK_MONOTONIC_RAW related code
parent 345e31e1
...@@ -31,47 +31,17 @@ ...@@ -31,47 +31,17 @@
namespace butil { namespace butil {
clockid_t get_monotonic_clockid() {
// http://lxr.free-electrons.com/source/include/uapi/linux/time.h#L44
const clockid_t MY_CLOCK_MONOTONIC_RAW = 4;
timespec ts;
if (0 == syscall(SYS_clock_gettime, MY_CLOCK_MONOTONIC_RAW, &ts)) {
return MY_CLOCK_MONOTONIC_RAW;
}
return CLOCK_MONOTONIC;
}
extern const clockid_t monotonic_clockid = get_monotonic_clockid();
int64_t monotonic_time_ns() { int64_t monotonic_time_ns() {
// MONOTONIC_RAW is slower than MONOTONIC in linux 2.6.32, trying to
// use the RAW version does not make sense anymore.
// NOTE: Not inline to keep ABI-compatible with previous versions.
timespec now; timespec now;
syscall(SYS_clock_gettime, monotonic_clockid, &now); clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_sec * 1000000000L + now.tv_nsec; return now.tv_sec * 1000000000L + now.tv_nsec;
} }
/* // read_cpu_frequency() is modified from source code of glibc.
read_cpu_frequency() is modified from source code of glibc. int64_t read_cpu_frequency(bool* invariant_tsc) {
Copyright (C) 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
uint64_t read_cpu_frequency(bool* invariant_tsc) {
/* We read the information from the /proc filesystem. It contains at /* We read the information from the /proc filesystem. It contains at
least one line like least one line like
cpu MHz : 497.840237 cpu MHz : 497.840237
...@@ -84,7 +54,7 @@ uint64_t read_cpu_frequency(bool* invariant_tsc) { ...@@ -84,7 +54,7 @@ uint64_t read_cpu_frequency(bool* invariant_tsc) {
return 0; return 0;
} }
uint64_t result = 0; int64_t result = 0;
char buf[4096]; // should be enough char buf[4096]; // should be enough
const ssize_t n = read(fd, buf, sizeof(buf)); const ssize_t n = read(fd, buf, sizeof(buf));
if (n > 0) { if (n > 0) {
...@@ -129,15 +99,16 @@ uint64_t read_cpu_frequency(bool* invariant_tsc) { ...@@ -129,15 +99,16 @@ uint64_t read_cpu_frequency(bool* invariant_tsc) {
return result; return result;
} }
uint64_t read_invariant_cpu_frequency() { // Return value must be >= 0
int64_t read_invariant_cpu_frequency() {
bool invariant_tsc = false; bool invariant_tsc = false;
const uint64_t freq = read_cpu_frequency(&invariant_tsc); const int64_t freq = read_cpu_frequency(&invariant_tsc);
return (invariant_tsc ? freq : 0); if (!invariant_tsc || freq < 0) {
return 0;
}
return freq;
} }
extern const uint64_t invariant_cpu_freq = read_invariant_cpu_frequency(); int64_t invariant_cpu_freq = -1;
__thread int64_t tls_realtime_ns = 0;
__thread int64_t tls_cpuwidetime_ns = 0;
} // namespace butil } // namespace butil
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
// Measuring time // Measuring time
#ifndef BAIDU_BASE_TIME_H #ifndef BAIDU_BUTIL_TIME_H
#define BAIDU_BASE_TIME_H #define BAIDU_BUTIL_TIME_H
#include <time.h> // timespec, clock_gettime #include <time.h> // timespec, clock_gettime
#include <sys/time.h> // timeval, gettimeofday #include <sys/time.h> // timeval, gettimeofday
...@@ -184,7 +184,6 @@ inline timeval seconds_to_timeval(int64_t s) { ...@@ -184,7 +184,6 @@ inline timeval seconds_to_timeval(int64_t s) {
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Get system-wide monotonic time. // Get system-wide monotonic time.
// Cost ~85ns on 2.6.32_1-12-0-0, Intel(R) Xeon(R) CPU E5620 @ 2.40GHz
// --------------------------------------------------------------- // ---------------------------------------------------------------
extern int64_t monotonic_time_ns(); extern int64_t monotonic_time_ns();
...@@ -217,20 +216,30 @@ inline uint64_t clock_cycles() { ...@@ -217,20 +216,30 @@ inline uint64_t clock_cycles() {
// Get cpu-wide (wall-) time. // Get cpu-wide (wall-) time.
// Cost ~9ns on Intel(R) Xeon(R) CPU E5620 @ 2.40GHz // Cost ~9ns on Intel(R) Xeon(R) CPU E5620 @ 2.40GHz
// --------------------------------------------------------------- // ---------------------------------------------------------------
// note: Inlining shortens time cost per-call for 15ns in a loop of many
// calls to this function.
inline int64_t cpuwide_time_ns() { inline int64_t cpuwide_time_ns() {
extern const uint64_t invariant_cpu_freq; // will be non-zero iff: extern int64_t read_invariant_cpu_frequency();
// Be positive iff:
// 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and // 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and
// nonstop_tsc(check flags in /proc/cpuinfo) // nonstop_tsc(check flags in /proc/cpuinfo)
extern int64_t invariant_cpu_freq;
if (invariant_cpu_freq) { if (invariant_cpu_freq > 0) {
const uint64_t tsc = detail::clock_cycles(); const uint64_t tsc = detail::clock_cycles();
const uint64_t sec = tsc / invariant_cpu_freq; const uint64_t sec = tsc / invariant_cpu_freq;
// TODO: should be OK until CPU's frequency exceeds 16GHz. // TODO: should be OK until CPU's frequency exceeds 16GHz.
return (tsc - sec * invariant_cpu_freq) * 1000000000L / return (tsc - sec * invariant_cpu_freq) * 1000000000L /
invariant_cpu_freq + sec * 1000000000L; invariant_cpu_freq + sec * 1000000000L;
} else if (!invariant_cpu_freq) {
// Lack of necessary features, return system-wide monotonic time instead.
return monotonic_time_ns();
} else {
// Use a thread-unsafe method(OK to us) to initialize the freq
// to save a "if" test comparing to using a local static variable
invariant_cpu_freq = read_invariant_cpu_frequency();
return cpuwide_time_ns();
} }
// Lack of necessary features, return system-wide monotonic time instead.
return monotonic_time_ns();
} }
inline int64_t cpuwide_time_us() { inline int64_t cpuwide_time_us() {
...@@ -337,60 +346,6 @@ private: ...@@ -337,60 +346,6 @@ private:
int64_t _start; int64_t _start;
}; };
// NOTE: Don't call fast_realtime*! they're still experimental.
inline int64_t fast_realtime_ns() {
extern const uint64_t invariant_cpu_freq;
extern __thread int64_t tls_cpuwidetime_ns;
extern __thread int64_t tls_realtime_ns;
if (invariant_cpu_freq) {
// 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and
// nonstop_tsc(check flags in /proc/cpuinfo)
const uint64_t tsc = detail::clock_cycles();
const uint64_t sec = tsc / invariant_cpu_freq;
// TODO: should be OK until CPU's frequency exceeds 16GHz.
const int64_t diff = (tsc - sec * invariant_cpu_freq) * 1000000000L /
invariant_cpu_freq + sec * 1000000000L - tls_cpuwidetime_ns;
if (__builtin_expect(diff < 10000000, 1)) {
return diff + tls_realtime_ns;
}
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
tls_cpuwidetime_ns += diff;
tls_realtime_ns = timespec_to_nanoseconds(ts);
return tls_realtime_ns;
}
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return timespec_to_nanoseconds(ts);
}
inline int fast_realtime(timespec* ts) {
extern const uint64_t invariant_cpu_freq;
extern __thread int64_t tls_cpuwidetime_ns;
extern __thread int64_t tls_realtime_ns;
if (invariant_cpu_freq) {
const uint64_t tsc = detail::clock_cycles();
const uint64_t sec = tsc / invariant_cpu_freq;
// TODO: should be OK until CPU's frequency exceeds 16GHz.
const int64_t diff = (tsc - sec * invariant_cpu_freq) * 1000000000L /
invariant_cpu_freq + sec * 1000000000L - tls_cpuwidetime_ns;
if (__builtin_expect(diff < 10000000, 1)) {
const int64_t now = diff + tls_realtime_ns;
ts->tv_sec = now / 1000000000L;
ts->tv_nsec = now - ts->tv_sec * 1000000000L;
return 0;
}
const int rc = clock_gettime(CLOCK_REALTIME, ts);
tls_cpuwidetime_ns += diff;
tls_realtime_ns = timespec_to_nanoseconds(*ts);
return rc;
}
return clock_gettime(CLOCK_REALTIME, ts);
}
} // namespace butil } // namespace butil
#endif // BAIDU_BASE_TIME_H #endif // BAIDU_BUTIL_TIME_H
...@@ -9,20 +9,8 @@ ...@@ -9,20 +9,8 @@
#include "butil/macros.h" #include "butil/macros.h"
#include "butil/logging.h" #include "butil/logging.h"
namespace butil {
extern const clockid_t monotonic_clockid;
extern const uint64_t invariant_cpu_freq;
}
namespace { namespace {
TEST(BaiduTimeTest, cpuwide_time) {
const long t1 = butil::cpuwide_time_us();
usleep(10000);
const long t2 = butil::cpuwide_time_us();
printf("elp=%luus freq=%lu\n", t2-t1, butil::invariant_cpu_freq);
}
TEST(BaiduTimeTest, diff_between_gettimeofday_and_REALTIME) { TEST(BaiduTimeTest, diff_between_gettimeofday_and_REALTIME) {
long t1 = butil::gettimeofday_us(); long t1 = butil::gettimeofday_us();
timespec time; timespec time;
...@@ -46,20 +34,6 @@ const char* clock_desc[] = { ...@@ -46,20 +34,6 @@ const char* clock_desc[] = {
"CLOCK_TAI" //11 "CLOCK_TAI" //11
}; };
TEST(BaiduTimeTest, fast_realtime) {
for (size_t i = 0; i < 10; ++i) {
long t1 = butil::gettimeofday_us();
timespec time;
clock_gettime(CLOCK_REALTIME, &time);
long t2 = butil::timespec_to_microseconds(time);
butil::fast_realtime(&time);
long t3 = butil::timespec_to_microseconds(time);
long t4 = butil::fast_realtime_ns() / 1000L;
LOG(INFO) << "t1=" << t1 << " t2=" << t2 << " t3=" << t3 << " t4=" << t4;
usleep(7000);
}
}
TEST(BaiduTimeTest, cost_of_timer) { TEST(BaiduTimeTest, cost_of_timer) {
printf("sizeof(time_t)=%lu\n", sizeof(time_t)); printf("sizeof(time_t)=%lu\n", sizeof(time_t));
...@@ -90,25 +64,24 @@ TEST(BaiduTimeTest, cost_of_timer) { ...@@ -90,25 +64,24 @@ TEST(BaiduTimeTest, cost_of_timer) {
t1.start(); t1.start();
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
s += butil::fast_realtime_ns(); s += butil::gettimeofday_us();
} }
t1.stop(); t1.stop();
printf("fast_realtime_ns takes %luns\n", t1.n_elapsed() / N); printf("gettimeofday_us takes %luns\n", t1.n_elapsed() / N);
t1.start(); t1.start();
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
s += butil::gettimeofday_us(); time(NULL);
} }
t1.stop(); t1.stop();
printf("gettimeofday_us takes %luns\n", t1.n_elapsed() / N); printf("time(NULL) takes %luns\n", t1.n_elapsed() / N);
t1.start(); t1.start();
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
timespec ts2; s += butil::monotonic_time_ns();
butil::fast_realtime(&ts2);
} }
t1.stop(); t1.stop();
printf("fast_realtime takes %luns\n", t1.n_elapsed() / N); printf("monotonic_time_ns takes %luns\n", t1.n_elapsed() / N);
for (size_t i = 0; i < arraysize(clock_desc); ++i) { for (size_t i = 0; i < arraysize(clock_desc); ++i) {
if (0 == syscall(SYS_clock_gettime, (clockid_t)i, &ts)) { if (0 == syscall(SYS_clock_gettime, (clockid_t)i, &ts)) {
...@@ -130,13 +103,6 @@ TEST(BaiduTimeTest, cost_of_timer) { ...@@ -130,13 +103,6 @@ TEST(BaiduTimeTest, cost_of_timer) {
clock_desc[i], t1.n_elapsed() / N); clock_desc[i], t1.n_elapsed() / N);
} }
} }
t1.start();
for (size_t i = 0; i < N; ++i) {
time(NULL);
}
t1.stop();
printf("time(NULL) takes %luns\n", t1.n_elapsed() / N);
} }
TEST(BaiduTimeTest, timespec) { TEST(BaiduTimeTest, timespec) {
...@@ -209,7 +175,8 @@ TEST(BaiduTimeTest, every_many_us) { ...@@ -209,7 +175,8 @@ TEST(BaiduTimeTest, every_many_us) {
const long start_time = butil::gettimeofday_ms(); const long start_time = butil::gettimeofday_ms();
while (1) { while (1) {
if (every_10ms) { if (every_10ms) {
printf("enter this branch at %lums\n", butil::gettimeofday_ms() - start_time); printf("enter this branch at %lums\n",
butil::gettimeofday_ms() - start_time);
if (++i >= 10) { if (++i >= 10) {
break; break;
} }
...@@ -217,13 +184,6 @@ TEST(BaiduTimeTest, every_many_us) { ...@@ -217,13 +184,6 @@ TEST(BaiduTimeTest, every_many_us) {
} }
} }
TEST(BaiduTimeTest, monotonic_time) {
const long t1 = butil::monotonic_time_ms();
usleep(10000L);
const long t2 = butil::monotonic_time_ms();
printf("clockid=%d %lums\n", butil::monotonic_clockid, t2-t1);
}
TEST(BaiduTimeTest, timer_auto_start) { TEST(BaiduTimeTest, timer_auto_start) {
butil::Timer t(butil::Timer::STARTED); butil::Timer t(butil::Timer::STARTED);
usleep(100); usleep(100);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment