From 03a5cc4a294d02c007562e1354b65f4e0527df7b Mon Sep 17 00:00:00 2001 From: dwh110 <707264794@qq.com> Date: Wed, 25 Feb 2026 12:13:40 +0800 Subject: [PATCH 1/4] cputime optimize for arm64 Update src/butil/time.cpp modify using __attribute__((constructor)) and merge init_invariant_cpu_freq to inside function read_invariant_cpu_frequency --- src/butil/time.cpp | 12 +++++++++--- src/butil/time.h | 11 +++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/butil/time.cpp b/src/butil/time.cpp index 2c726d9b52..1714a5b4e6 100644 --- a/src/butil/time.cpp +++ b/src/butil/time.cpp @@ -143,16 +143,22 @@ int64_t read_cpu_frequency(bool* invariant_tsc) { } // Return value must be >= 0 -int64_t read_invariant_cpu_frequency() { +static int64_t read_invariant_cpu_frequency() { bool invariant_tsc = false; - const int64_t freq = read_cpu_frequency(&invariant_tsc); + int64_t freq = -1; +#if defined(__aarch64__) + __asm__ __volatile__("mrs %0, CNTFRQ_EL0" : "=r"(freq)); +#else + freq = read_cpu_frequency(&invariant_tsc); if (!invariant_tsc || freq < 0) { return 0; } +#endif + return freq; } -int64_t invariant_cpu_freq = -1; +int64_t invariant_cpu_freq = read_invariant_cpu_frequency(); } // namespace detail } // namespace butil diff --git a/src/butil/time.h b/src/butil/time.h index c57000ea99..fa197e5b07 100644 --- a/src/butil/time.h +++ b/src/butil/time.h @@ -265,7 +265,7 @@ inline uint64_t clock_cycles() { #error "unsupported arch" #endif } -extern int64_t read_invariant_cpu_frequency(); + // Be positive iff: // 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and // nonstop_tsc(check flags in /proc/cpuinfo) @@ -279,7 +279,7 @@ extern int64_t invariant_cpu_freq; // note: Inlining shortens time cost per-call for 15ns in a loop of many // calls to this function. inline int64_t cpuwide_time_ns() { -#if !defined(BAIDU_INTERNAL) +#if !defined(BAIDU_INTERNAL) && !defined(__aarch64__) // nearly impossible to get the correct invariant cpu frequency on // different CPU and machines. CPU-ID rarely works and frequencies // in "model name" and "cpu Mhz" are both unreliable. @@ -298,14 +298,9 @@ inline int64_t cpuwide_time_ns() { const uint64_t remain = tsc % cpu_freq; // TODO: should be OK until CPU's frequency exceeds 16GHz. return remain * 1000000000L / cpu_freq + sec * 1000000000L; - } else if (!cpu_freq) { + } else { // 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 - detail::invariant_cpu_freq = detail::read_invariant_cpu_frequency(); - return cpuwide_time_ns(); } #endif // defined(BAIDU_INTERNAL) } From e705415ad7c7cbba0b0674a631de92323e7f6e85 Mon Sep 17 00:00:00 2001 From: seekdwh Date: Thu, 30 Jul 2026 21:43:38 +0800 Subject: [PATCH 2/4] Add the macro switch BUTIL_USE_CPU_FREQUENCY while preserving the original default behavior for ARM64 --- src/butil/time.cpp | 2 +- src/butil/time.h | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/butil/time.cpp b/src/butil/time.cpp index 1714a5b4e6..e929997ad6 100644 --- a/src/butil/time.cpp +++ b/src/butil/time.cpp @@ -146,7 +146,7 @@ int64_t read_cpu_frequency(bool* invariant_tsc) { static int64_t read_invariant_cpu_frequency() { bool invariant_tsc = false; int64_t freq = -1; -#if defined(__aarch64__) +#if defined(__aarch64__) && defined(BUTIL_USE_CPU_FREQUENCY) __asm__ __volatile__("mrs %0, CNTFRQ_EL0" : "=r"(freq)); #else freq = read_cpu_frequency(&invariant_tsc); diff --git a/src/butil/time.h b/src/butil/time.h index fa197e5b07..71156b3f13 100644 --- a/src/butil/time.h +++ b/src/butil/time.h @@ -269,6 +269,8 @@ inline uint64_t clock_cycles() { // Be positive iff: // 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and // nonstop_tsc(check flags in /proc/cpuinfo) +// 2 aarch64, where the counter frequency is read from CNTFRQ_EL0. +// Only computed when BUTIL_USE_CPU_FREQUENCY is defined. extern int64_t invariant_cpu_freq; } // namespace detail @@ -279,7 +281,7 @@ extern int64_t invariant_cpu_freq; // note: Inlining shortens time cost per-call for 15ns in a loop of many // calls to this function. inline int64_t cpuwide_time_ns() { -#if !defined(BAIDU_INTERNAL) && !defined(__aarch64__) +#if !defined(BAIDU_INTERNAL) && !defined(BUTIL_USE_CPU_FREQUENCY) // nearly impossible to get the correct invariant cpu frequency on // different CPU and machines. CPU-ID rarely works and frequencies // in "model name" and "cpu Mhz" are both unreliable. @@ -302,7 +304,7 @@ inline int64_t cpuwide_time_ns() { // Lack of necessary features, return system-wide monotonic time instead. return monotonic_time_ns(); } -#endif // defined(BAIDU_INTERNAL) +#endif // defined(BAIDU_INTERNAL) || defined(BUTIL_USE_CPU_FREQUENCY) } // Get cpu clock time of the current thread in nanoseconds without the time spent in blocking I/O operations. From 9538fdf5576aa2de477d4d83479a96213650539a Mon Sep 17 00:00:00 2001 From: seekdwh Date: Wed, 5 Aug 2026 19:31:34 +0800 Subject: [PATCH 3/4] =?UTF-8?q?1=E3=80=81Activation=20options:=20CMake=20-?= =?UTF-8?q?DWITH=5FCPU=5FFREQUENCY=3DON,=20Bazel=20--define=20BUTIL=5FUSE?= =?UTF-8?q?=5FCPU=5FFREQUENCY=3Dtrue,=20script=20argument=20--with-cpu-fre?= =?UTF-8?q?quency.=202=E3=80=81Disabled=20by=20default=20for=20consistent?= =?UTF-8?q?=20legacy=20behavior.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BUILD.bazel | 13 ++++++++++++- CMakeLists.txt | 10 ++++++++++ bazel/config/BUILD.bazel | 6 ++++++ config.h.in | 5 +++++ config_brpc.sh | 11 +++++++++-- example/BUILD.bazel | 3 +++ src/butil/time.cpp | 2 +- src/butil/time.h | 6 +++--- 8 files changed, 49 insertions(+), 7 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index 5dc5fcf726..670d3e88fb 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -60,7 +60,10 @@ DEFINES = [ }) + select({ "//bazel/config:brpc_with_no_pthread_mutex_hook": ["NO_PTHREAD_MUTEX_HOOK"], "//conditions:default": [], - }) + }) + select({ + "//bazel/config:brpc_with_cpu_frequency": ["-DBUTIL_USE_CPU_FREQUENCY=1"], + "//conditions:default": ["-DBUTIL_USE_CPU_FREQUENCY=0"], +}) LINKOPTS = [ "-pthread", @@ -116,6 +119,14 @@ genrule( "//conditions:default": "0", }) + """ +#ifdef BUTIL_USE_CPU_FREQUENCY +#undef BUTIL_USE_CPU_FREQUENCY +#endif +#define BUTIL_USE_CPU_FREQUENCY """ + select({ + "//bazel/config:brpc_with_cpu_frequency": "1", + "//conditions:default": "0", + }) + + """ #endif // BUTIL_CONFIG_H EOF """, diff --git a/CMakeLists.txt b/CMakeLists.txt index 915b7d2977..ba46e97e3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ option(WITH_RDMA "With RDMA" OFF) option(WITH_UBRING "With UB" OFF) option(WITH_DEBUG_BTHREAD_SCHE_SAFETY "With debugging bthread sche safety" OFF) option(WITH_DEBUG_LOCK "With debugging lock" OFF) +option(WITH_CPU_FREQUENCY "Use CPU frequency for cpuwide_time" OFF) option(WITH_ASAN "With AddressSanitizer" OFF) option(BUILD_UNIT_TESTS "Whether to build unit tests" OFF) option(BUILD_FUZZ_TESTS "Whether to build fuzz tests" OFF) @@ -76,6 +77,12 @@ if(WITH_GLOG) set(BRPC_WITH_GLOG 1) endif() +set(WITH_CPU_FREQUENCY_VAL "0") +if(WITH_CPU_FREQUENCY) + set(WITH_CPU_FREQUENCY_VAL "1") + set(BUTIL_USE_CPU_FREQUENCY 1) +endif() + if(WITH_DEBUG_SYMBOLS) list(APPEND BRPC_COMMON_COMPILE_OPTIONS -g) endif() @@ -156,6 +163,7 @@ list(APPEND BRPC_COMMON_DEFINITIONS BRPC_WITH_UBRING=${WITH_UBRING_VAL} BRPC_DEBUG_BTHREAD_SCHE_SAFETY=${WITH_DEBUG_BTHREAD_SCHE_SAFETY_VAL} BRPC_DEBUG_LOCK=${WITH_DEBUG_LOCK_VAL} + BUTIL_USE_CPU_FREQUENCY=${WITH_CPU_FREQUENCY_VAL} BTHREAD_USE_FAST_PTHREAD_MUTEX __const__=__unused__ _GNU_SOURCE @@ -166,12 +174,14 @@ list(APPEND BRPC_COMMON_DEFINITIONS __STDC_CONSTANT_MACROS __STRICT_ANSI__ ) + if(NOT DEBUG) list(APPEND BRPC_COMMON_DEFINITIONS NDEBUG) endif() if(WITH_ASAN) list(APPEND BRPC_COMMON_COMPILE_OPTIONS -fsanitize=address) list(APPEND BRPC_COMMON_LINK_OPTIONS -fsanitize=address) + endif() if(WITH_MESALINK) list(APPEND BRPC_COMMON_DEFINITIONS USE_MESALINK) diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel index eec551da8b..fabc4be061 100644 --- a/bazel/config/BUILD.bazel +++ b/bazel/config/BUILD.bazel @@ -36,6 +36,12 @@ config_setting( define_values = {"BRPC_WITH_GLOG": "true"}, ) +config_setting( + name = "brpc_with_cpu_frequency", + define_values = {"BUTIL_USE_CPU_FREQUENCY": "true"}, + visibility = ["//visibility:public"], +) + selects.config_setting_group( name = "brpc_with_mesalink", match_any = [ diff --git a/config.h.in b/config.h.in index 4f26e57775..d8de111be9 100644 --- a/config.h.in +++ b/config.h.in @@ -21,4 +21,9 @@ #endif #cmakedefine BRPC_WITH_GLOG @WITH_GLOG_VAL@ +#ifdef BUTIL_USE_CPU_FREQUENCY +#undef BUTIL_USE_CPU_FREQUENCY +#endif +#cmakedefine BUTIL_USE_CPU_FREQUENCY @WITH_CPU_FREQUENCY_VAL@ + #endif // BUTIL_CONFIG_H diff --git a/config_brpc.sh b/config_brpc.sh index 1c05942068..3237d6630d 100755 --- a/config_brpc.sh +++ b/config_brpc.sh @@ -54,7 +54,7 @@ else LDD=ldd fi -TEMP=`getopt -o v: --long headers:,libs:,cc:,cxx:,with-glog,with-thrift,with-rdma,with-mesalink,with-bthread-tracer,with-debug-bthread-sche-safety,with-debug-lock,with-asan,with-riscv-zvbc,with-riscv-zbc,nodebugsymbols,werror -n 'config_brpc' -- "$@"` +TEMP=`getopt -o v: --long headers:,libs:,cc:,cxx:,with-glog,with-thrift,with-rdma,with-mesalink,with-bthread-tracer,with-debug-bthread-sche-safety,with-debug-lock,with-asan,with-riscv-zvbc,with-riscv-zbc,with-cpu-frequency,nodebugsymbols,werror -n 'config_brpc' -- "$@"` WITH_GLOG=0 WITH_THRIFT=0 WITH_RDMA=0 @@ -67,6 +67,7 @@ BRPC_DEBUG_BTHREAD_SCHE_SAFETY=0 DEBUGSYMBOLS=-g WERROR= BRPC_DEBUG_LOCK=0 +WITH_CPU_FREQUENCY=0 if [ $? != 0 ] ; then >&2 $ECHO "Terminating..."; exit 1 ; fi @@ -93,6 +94,7 @@ while true; do --with-bthread-tracer) WITH_BTHREAD_TRACER=1; shift 1 ;; --with-debug-bthread-sche-safety ) BRPC_DEBUG_BTHREAD_SCHE_SAFETY=1; shift 1 ;; --with-debug-lock ) BRPC_DEBUG_LOCK=1; shift 1 ;; + --with-cpu-frequency ) WITH_CPU_FREQUENCY=1; shift 1 ;; --with-asan) WITH_ASAN=1; shift 1 ;; --with-riscv-zvbc) WITH_RISCV_ZVBC=1; shift 1 ;; --with-riscv-zbc) WITH_RISCV_ZBC=1; shift 1 ;; @@ -479,7 +481,7 @@ append_to_output "STATIC_LINKINGS=$STATIC_LINKINGS" append_to_output "DYNAMIC_LINKINGS=$DYNAMIC_LINKINGS" # CPP means C PreProcessing, not C PlusPlus -CPPFLAGS="${CPPFLAGS} -DBRPC_WITH_GLOG=$WITH_GLOG -DBRPC_DEBUG_BTHREAD_SCHE_SAFETY=$BRPC_DEBUG_BTHREAD_SCHE_SAFETY -DBRPC_DEBUG_LOCK=$BRPC_DEBUG_LOCK" +CPPFLAGS="${CPPFLAGS} -DBRPC_WITH_GLOG=$WITH_GLOG -DBRPC_DEBUG_BTHREAD_SCHE_SAFETY=$BRPC_DEBUG_BTHREAD_SCHE_SAFETY -DBRPC_DEBUG_LOCK=$BRPC_DEBUG_LOCK -DBUTIL_USE_CPU_FREQUENCY=$WITH_CPU_FREQUENCY" # Avoid over-optimizations of TLS variables by GCC>=4.8 # See: https://github.com/apache/brpc/issues/1693 @@ -649,6 +651,11 @@ cat << EOF > src/butil/config.h #endif #define BRPC_WITH_GLOG $WITH_GLOG +#ifdef BUTIL_USE_CPU_FREQUENCY +#undef BUTIL_USE_CPU_FREQUENCY +#endif +#define BUTIL_USE_CPU_FREQUENCY $WITH_CPU_FREQUENCY + #endif // BUTIL_CONFIG_H EOF diff --git a/example/BUILD.bazel b/example/BUILD.bazel index 4ee7cb140f..d0115dc43a 100644 --- a/example/BUILD.bazel +++ b/example/BUILD.bazel @@ -31,6 +31,9 @@ COPTS = [ ] + select({ "//bazel/config:brpc_with_glog": ["-DBRPC_WITH_GLOG=1"], "//conditions:default": ["-DBRPC_WITH_GLOG=0"], +}) + select({ + "//bazel/config:brpc_with_cpu_frequency": ["-DBUTIL_USE_CPU_FREQUENCY=1"], + "//conditions:default": ["-DBUTIL_USE_CPU_FREQUENCY=0"], }) + select({ "//bazel/config:brpc_with_rdma": ["-DBRPC_WITH_RDMA=1"], "//conditions:default": [""], diff --git a/src/butil/time.cpp b/src/butil/time.cpp index e929997ad6..ad91831fc3 100644 --- a/src/butil/time.cpp +++ b/src/butil/time.cpp @@ -146,7 +146,7 @@ int64_t read_cpu_frequency(bool* invariant_tsc) { static int64_t read_invariant_cpu_frequency() { bool invariant_tsc = false; int64_t freq = -1; -#if defined(__aarch64__) && defined(BUTIL_USE_CPU_FREQUENCY) +#if defined(__aarch64__) && BUTIL_USE_CPU_FREQUENCY __asm__ __volatile__("mrs %0, CNTFRQ_EL0" : "=r"(freq)); #else freq = read_cpu_frequency(&invariant_tsc); diff --git a/src/butil/time.h b/src/butil/time.h index 71156b3f13..d0daaa5ff4 100644 --- a/src/butil/time.h +++ b/src/butil/time.h @@ -270,7 +270,7 @@ inline uint64_t clock_cycles() { // 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and // nonstop_tsc(check flags in /proc/cpuinfo) // 2 aarch64, where the counter frequency is read from CNTFRQ_EL0. -// Only computed when BUTIL_USE_CPU_FREQUENCY is defined. +// Only computed when BUTIL_USE_CPU_FREQUENCY is enabled. extern int64_t invariant_cpu_freq; } // namespace detail @@ -281,7 +281,7 @@ extern int64_t invariant_cpu_freq; // note: Inlining shortens time cost per-call for 15ns in a loop of many // calls to this function. inline int64_t cpuwide_time_ns() { -#if !defined(BAIDU_INTERNAL) && !defined(BUTIL_USE_CPU_FREQUENCY) +#if !defined(BAIDU_INTERNAL) && !BUTIL_USE_CPU_FREQUENCY // nearly impossible to get the correct invariant cpu frequency on // different CPU and machines. CPU-ID rarely works and frequencies // in "model name" and "cpu Mhz" are both unreliable. @@ -304,7 +304,7 @@ inline int64_t cpuwide_time_ns() { // Lack of necessary features, return system-wide monotonic time instead. return monotonic_time_ns(); } -#endif // defined(BAIDU_INTERNAL) || defined(BUTIL_USE_CPU_FREQUENCY) +#endif // defined(BAIDU_INTERNAL) || BUTIL_USE_CPU_FREQUENCY } // Get cpu clock time of the current thread in nanoseconds without the time spent in blocking I/O operations. From 8405013a49aed534232b5d7d63488c62fef6f236 Mon Sep 17 00:00:00 2001 From: seekdwh Date: Thu, 6 Aug 2026 09:02:32 +0800 Subject: [PATCH 4/4] fix compile failed --- BUILD.bazel | 4 ++-- CMakeLists.txt | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index 670d3e88fb..b1676c4a62 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -61,8 +61,8 @@ DEFINES = [ "//bazel/config:brpc_with_no_pthread_mutex_hook": ["NO_PTHREAD_MUTEX_HOOK"], "//conditions:default": [], }) + select({ - "//bazel/config:brpc_with_cpu_frequency": ["-DBUTIL_USE_CPU_FREQUENCY=1"], - "//conditions:default": ["-DBUTIL_USE_CPU_FREQUENCY=0"], + "//bazel/config:brpc_with_cpu_frequency": ["BUTIL_USE_CPU_FREQUENCY=1"], + "//conditions:default": ["BUTIL_USE_CPU_FREQUENCY=0"], }) LINKOPTS = [ diff --git a/CMakeLists.txt b/CMakeLists.txt index ba46e97e3b..2b92dca1c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,7 +181,6 @@ endif() if(WITH_ASAN) list(APPEND BRPC_COMMON_COMPILE_OPTIONS -fsanitize=address) list(APPEND BRPC_COMMON_LINK_OPTIONS -fsanitize=address) - endif() if(WITH_MESALINK) list(APPEND BRPC_COMMON_DEFINITIONS USE_MESALINK)