From 22590efd194e509e70bad787d9ff31727b402b89 Mon Sep 17 00:00:00 2001 From: Jacob Su Date: Thu, 7 Mar 2024 10:36:06 +0800 Subject: [PATCH] issue #3978: improve st_utime's default impl. --- trunk/3rdparty/st-srs/Makefile | 3 + trunk/3rdparty/st-srs/md.h | 31 ++++++--- trunk/auto/depends.sh | 3 + trunk/auto/options.sh | 16 ++++- trunk/configure | 2 +- trunk/src/utest/srs_utest_st.cpp | 115 +++++++++++++++++++++++++++++++ trunk/src/utest/srs_utest_st.hpp | 15 ++++ 7 files changed, 173 insertions(+), 12 deletions(-) create mode 100644 trunk/src/utest/srs_utest_st.cpp create mode 100644 trunk/src/utest/srs_utest_st.hpp diff --git a/trunk/3rdparty/st-srs/Makefile b/trunk/3rdparty/st-srs/Makefile index cc3fedf6deb..b163246cd77 100644 --- a/trunk/3rdparty/st-srs/Makefile +++ b/trunk/3rdparty/st-srs/Makefile @@ -107,6 +107,9 @@ LDFLAGS += -arch $(CPU_ARCHS) LDFLAGS += -dynamiclib -install_name /sw/lib/libst.$(MAJOR).$(DSO_SUFFIX) -compatibility_version $(MAJOR) -current_version $(VERSION) OTHER_FLAGS = -Wall DEFINES += -DMD_HAVE_KQUEUE -DMD_HAVE_SELECT +# https://github.com/ossrs/srs/issues/3978 +# if your mac os version is less than 10.12, then add +# DEFINES += -DMD_OSX_HAS_NO_CLOCK_GETTIME endif ifeq ($(OS), LINUX) diff --git a/trunk/3rdparty/st-srs/md.h b/trunk/3rdparty/st-srs/md.h index d3158db3fce..1269459e0be 100644 --- a/trunk/3rdparty/st-srs/md.h +++ b/trunk/3rdparty/st-srs/md.h @@ -110,10 +110,21 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val); MD_GET_SP(_thread) = (long) (_sp); \ ST_END_MACRO - #define MD_GET_UTIME() \ - struct timeval tv; \ - (void) gettimeofday(&tv, NULL); \ - return (tv.tv_sec * 1000000LL + tv.tv_usec) + #if defined (MD_OSX_HAS_NO_CLOCK_GETTIME) + #define MD_GET_UTIME() \ + struct timeval tv; \ + (void) gettimeofday(&tv, NULL); \ + return (tv.tv_sec * 1000000LL + tv.tv_usec) + #else + /* + * https://github.com/ossrs/srs/issues/3978 + * use clock_gettime to get the timestamp in microseconds. + */ + #define MD_GET_UTIME() \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + return (ts.tv_sec * 1000000LL + ts.tv_nsec / 1000) + #endif #elif defined (LINUX) @@ -129,13 +140,13 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val); #define MD_HAVE_SOCKLEN_T /* - * All architectures and flavors of linux have the gettimeofday - * function but if you know of a faster way, use it. + * https://github.com/ossrs/srs/issues/3978 + * use clock_gettime to get the timestamp in microseconds. */ - #define MD_GET_UTIME() \ - struct timeval tv; \ - (void) gettimeofday(&tv, NULL); \ - return (tv.tv_sec * 1000000LL + tv.tv_usec) + #define MD_GET_UTIME() \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + return (ts.tv_sec * 1000000LL + ts.tv_nsec / 1000) #if defined(__i386__) #define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[4])) diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index 38d09bf8352..81efbdc3926 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -254,6 +254,9 @@ fi # for osx, use darwin for st, donot use epoll. if [[ $SRS_OSX == YES ]]; then _ST_MAKE=darwin-debug && _ST_OBJ="DARWIN_`uname -r`_DBG" + if [[ $SRS_OSX_HAS_CLOCK_GETTIME != YES ]]; then + _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DMD_OSX_HAS_NO_CLOCK_GETTIME" + fi fi # for windows/cygwin if [[ $SRS_CYGWIN64 = YES ]]; then diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index 5d5e9aa299c..a3758135da6 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -111,6 +111,8 @@ SRS_CROSS_BUILD_HOST= SRS_CROSS_BUILD_PREFIX= # For cache build SRS_BUILD_CACHE=YES + +SRS_OSX_HAS_CLOCK_GETTIME= # ##################################################################################### # Toolchain for cross-build on Ubuntu for ARM or MIPS. @@ -149,7 +151,19 @@ function apply_system_options() { OS_IS_RISCV=$(gcc -dM -E - = 10.12 has api clock_gettime; check man clock_gettime + if [[ ${OSX_VERSION_ARR[0]} -gt 10 ]]; then + SRS_OSX_HAS_CLOCK_GETTIME=YES + elif [[ ${OSX_VERSION_ARR[0]} -eq 10 && ${OSX_VERSION_ARR[1]} -ge 12 ]]; then + SRS_OSX_HAS_CLOCK_GETTIME=YES + else + echo "Warning: your OSX $(sw_vers --productVersion) has no api clock_gettime" + SRS_OSX_HAS_CLOCK_GETTIME=NO + fi + fi if [[ $OS_IS_CYGWIN == YES ]]; then SRS_CYGWIN64=YES; fi if [[ $OS_IS_OSX == YES ]]; then SRS_JOBS=$(sysctl -n hw.ncpu 2>/dev/null || echo 1); fi diff --git a/trunk/configure b/trunk/configure index 24fe192c962..bea14f36f45 100755 --- a/trunk/configure +++ b/trunk/configure @@ -464,7 +464,7 @@ if [[ $SRS_UTEST == YES ]]; then MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_kernel" "srs_utest_core" "srs_utest_config" "srs_utest_rtmp" "srs_utest_http" "srs_utest_avc" "srs_utest_reload" "srs_utest_mp4" "srs_utest_service" "srs_utest_app" "srs_utest_rtc" "srs_utest_config2" - "srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2") + "srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2" "srs_utest_st") if [[ $SRS_SRT == YES ]]; then MODULE_FILES+=("srs_utest_srt") fi diff --git a/trunk/src/utest/srs_utest_st.cpp b/trunk/src/utest/srs_utest_st.cpp new file mode 100644 index 00000000000..3b86e772caa --- /dev/null +++ b/trunk/src/utest/srs_utest_st.cpp @@ -0,0 +1,115 @@ +// +// Copyright (c) 2013-2024 The SRS Authors +// +// SPDX-License-Identifier: MIT +// +#include +#include +#include +#include + +using namespace std; + +VOID TEST(StTest, StUtimeInMicroseconds) +{ + st_utime_t st_time_1 = st_utime(); + // sleep 1 microsecond + usleep(1); + st_utime_t st_time_2 = st_utime(); + + EXPECT_GT(st_time_1, 0); + EXPECT_GT(st_time_2, 0); + EXPECT_GT(st_time_2, st_time_1); + // st_time_2 - st_time_1 should be in range of [1, 100] microseconds + EXPECT_GE(st_time_2 - st_time_1, 1); + EXPECT_LE(st_time_2 - st_time_1, 100); +} + +static inline st_utime_t time_gettimeofday() { + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec * 1000000LL + tv.tv_usec); +} + +VOID TEST(StTest, StUtimePerformance) +{ + clock_t start; + int gettimeofday_elapsed_time = 0; + int st_utime_elapsed_time = 0; + + // Both the st_utime(clock_gettime or gettimeofday) and gettimeofday's + // elpased time to execute is dependence on whether it is the first time be called. + // In general, the gettimeofday has better performance, but the gap between + // them is really small, maybe less than 10 clock ~ 10 microseconds. + + // check st_utime first, then gettimeofday + { + start = clock(); + st_utime_t t2 = st_utime(); + int elapsed_time = clock() - start; + st_utime_elapsed_time += elapsed_time; + EXPECT_GT(t2, 0); + + start = clock(); + st_utime_t t1 = time_gettimeofday(); + elapsed_time = clock() - start; + gettimeofday_elapsed_time += elapsed_time; + EXPECT_GT(t1, 0); + + + EXPECT_GE(gettimeofday_elapsed_time, 0); + EXPECT_GE(st_utime_elapsed_time, 0); + + // pass the test, if + EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ? + gettimeofday_elapsed_time - st_utime_elapsed_time : + st_utime_elapsed_time - gettimeofday_elapsed_time, 10); + } + + // check gettimeofday first, then st_utime + { + start = clock(); + st_utime_t t1 = time_gettimeofday(); + int elapsed_time = clock() - start; + gettimeofday_elapsed_time += elapsed_time; + EXPECT_GT(t1, 0); + + start = clock(); + st_utime_t t2 = st_utime(); + elapsed_time = clock() - start; + st_utime_elapsed_time += elapsed_time; + EXPECT_GT(t2, 0); + + EXPECT_GE(gettimeofday_elapsed_time, 0); + EXPECT_GE(st_utime_elapsed_time, 0); + + EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ? + gettimeofday_elapsed_time - st_utime_elapsed_time : + st_utime_elapsed_time - gettimeofday_elapsed_time, 10); + } + + // compare st_utime & gettimeofday in a loop + for (int i = 0; i < 100; i++) { + start = clock(); + st_utime_t t2 = st_utime(); + int elapsed_time = clock() - start; + st_utime_elapsed_time = elapsed_time; + EXPECT_GT(t2, 0); + usleep(1); + + start = clock(); + st_utime_t t1 = time_gettimeofday(); + elapsed_time = clock() - start; + gettimeofday_elapsed_time = elapsed_time; + EXPECT_GT(t1, 0); + usleep(1); + + EXPECT_GE(gettimeofday_elapsed_time, 0); + EXPECT_GE(st_utime_elapsed_time, 0); + + EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ? + gettimeofday_elapsed_time - st_utime_elapsed_time : + st_utime_elapsed_time - gettimeofday_elapsed_time, 10); + + } +} diff --git a/trunk/src/utest/srs_utest_st.hpp b/trunk/src/utest/srs_utest_st.hpp new file mode 100644 index 00000000000..32862447a76 --- /dev/null +++ b/trunk/src/utest/srs_utest_st.hpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2013-2024 The SRS Authors +// +// SPDX-License-Identifier: MIT +// + +#ifndef SRS_UTEST_ST_HPP +#define SRS_UTEST_ST_HPP + +#include + +#include + +#endif // SRS_UTEST_ST_HPP +