Skip to content

Commit

Permalink
issue #3978: improve st_utime's default impl.
Browse files Browse the repository at this point in the history
  • Loading branch information
suzp1984 committed Mar 18, 2024
1 parent 954b1b7 commit 1aae04f
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 12 deletions.
3 changes: 3 additions & 0 deletions trunk/3rdparty/st-srs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
31 changes: 21 additions & 10 deletions trunk/3rdparty/st-srs/md.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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]))
Expand Down
3 changes: 3 additions & 0 deletions trunk/auto/depends.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 15 additions & 1 deletion trunk/auto/options.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -149,7 +151,19 @@ function apply_system_options() {
OS_IS_RISCV=$(gcc -dM -E - </dev/null |grep -q '#define __riscv 1' && echo YES)

# Set the os option automatically.
if [[ $OS_IS_OSX == YES ]]; then SRS_OSX=YES; fi
if [[ $OS_IS_OSX == YES ]]; then
SRS_OSX=YES;
OSX_VERSION_ARR=($(sw_vers --productVersion | tr "." "\n"))
# OSX version >= 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
Expand Down
2 changes: 1 addition & 1 deletion trunk/configure
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
117 changes: 117 additions & 0 deletions trunk/src/utest/srs_utest_st.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//
// Copyright (c) 2013-2024 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_utest_st.hpp>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

using namespace std;

VOID TEST(StTest, StUtimeInMicroseconds)
{
st_utime_t st_time_1 = st_utime();
// sleep 1 microsecond
#if !defined(SRS_CYGWIN64)
usleep(1);
#endif
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);

}
}
15 changes: 15 additions & 0 deletions trunk/src/utest/srs_utest_st.hpp
Original file line number Diff line number Diff line change
@@ -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 <srs_utest.hpp>

#include <st.h>

#endif // SRS_UTEST_ST_HPP

0 comments on commit 1aae04f

Please sign in to comment.