Skip to content

Commit 1aae04f

Browse files
committed
issue #3978: improve st_utime's default impl.
1 parent 954b1b7 commit 1aae04f

File tree

7 files changed

+175
-12
lines changed

7 files changed

+175
-12
lines changed

trunk/3rdparty/st-srs/Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ LDFLAGS += -arch $(CPU_ARCHS)
107107
LDFLAGS += -dynamiclib -install_name /sw/lib/libst.$(MAJOR).$(DSO_SUFFIX) -compatibility_version $(MAJOR) -current_version $(VERSION)
108108
OTHER_FLAGS = -Wall
109109
DEFINES += -DMD_HAVE_KQUEUE -DMD_HAVE_SELECT
110+
# https://github.com/ossrs/srs/issues/3978
111+
# if your mac os version is less than 10.12, then add
112+
# DEFINES += -DMD_OSX_HAS_NO_CLOCK_GETTIME
110113
endif
111114

112115
ifeq ($(OS), LINUX)

trunk/3rdparty/st-srs/md.h

+21-10
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,21 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
110110
MD_GET_SP(_thread) = (long) (_sp); \
111111
ST_END_MACRO
112112

113-
#define MD_GET_UTIME() \
114-
struct timeval tv; \
115-
(void) gettimeofday(&tv, NULL); \
116-
return (tv.tv_sec * 1000000LL + tv.tv_usec)
113+
#if defined (MD_OSX_HAS_NO_CLOCK_GETTIME)
114+
#define MD_GET_UTIME() \
115+
struct timeval tv; \
116+
(void) gettimeofday(&tv, NULL); \
117+
return (tv.tv_sec * 1000000LL + tv.tv_usec)
118+
#else
119+
/*
120+
* https://github.com/ossrs/srs/issues/3978
121+
* use clock_gettime to get the timestamp in microseconds.
122+
*/
123+
#define MD_GET_UTIME() \
124+
struct timespec ts; \
125+
clock_gettime(CLOCK_MONOTONIC, &ts); \
126+
return (ts.tv_sec * 1000000LL + ts.tv_nsec / 1000)
127+
#endif
117128

118129
#elif defined (LINUX)
119130

@@ -129,13 +140,13 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
129140
#define MD_HAVE_SOCKLEN_T
130141

131142
/*
132-
* All architectures and flavors of linux have the gettimeofday
133-
* function but if you know of a faster way, use it.
143+
* https://github.com/ossrs/srs/issues/3978
144+
* use clock_gettime to get the timestamp in microseconds.
134145
*/
135-
#define MD_GET_UTIME() \
136-
struct timeval tv; \
137-
(void) gettimeofday(&tv, NULL); \
138-
return (tv.tv_sec * 1000000LL + tv.tv_usec)
146+
#define MD_GET_UTIME() \
147+
struct timespec ts; \
148+
clock_gettime(CLOCK_MONOTONIC, &ts); \
149+
return (ts.tv_sec * 1000000LL + ts.tv_nsec / 1000)
139150

140151
#if defined(__i386__)
141152
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[4]))

trunk/auto/depends.sh

+3
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ fi
254254
# for osx, use darwin for st, donot use epoll.
255255
if [[ $SRS_OSX == YES ]]; then
256256
_ST_MAKE=darwin-debug && _ST_OBJ="DARWIN_`uname -r`_DBG"
257+
if [[ $SRS_OSX_HAS_CLOCK_GETTIME != YES ]]; then
258+
_ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DMD_OSX_HAS_NO_CLOCK_GETTIME"
259+
fi
257260
fi
258261
# for windows/cygwin
259262
if [[ $SRS_CYGWIN64 = YES ]]; then

trunk/auto/options.sh

+15-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ SRS_CROSS_BUILD_HOST=
111111
SRS_CROSS_BUILD_PREFIX=
112112
# For cache build
113113
SRS_BUILD_CACHE=YES
114+
115+
SRS_OSX_HAS_CLOCK_GETTIME=
114116
#
115117
#####################################################################################
116118
# Toolchain for cross-build on Ubuntu for ARM or MIPS.
@@ -149,7 +151,19 @@ function apply_system_options() {
149151
OS_IS_RISCV=$(gcc -dM -E - </dev/null |grep -q '#define __riscv 1' && echo YES)
150152

151153
# Set the os option automatically.
152-
if [[ $OS_IS_OSX == YES ]]; then SRS_OSX=YES; fi
154+
if [[ $OS_IS_OSX == YES ]]; then
155+
SRS_OSX=YES;
156+
OSX_VERSION_ARR=($(sw_vers --productVersion | tr "." "\n"))
157+
# OSX version >= 10.12 has api clock_gettime; check man clock_gettime
158+
if [[ ${OSX_VERSION_ARR[0]} -gt 10 ]]; then
159+
SRS_OSX_HAS_CLOCK_GETTIME=YES
160+
elif [[ ${OSX_VERSION_ARR[0]} -eq 10 && ${OSX_VERSION_ARR[1]} -ge 12 ]]; then
161+
SRS_OSX_HAS_CLOCK_GETTIME=YES
162+
else
163+
echo "Warning: your OSX $(sw_vers --productVersion) has no api clock_gettime"
164+
SRS_OSX_HAS_CLOCK_GETTIME=NO
165+
fi
166+
fi
153167
if [[ $OS_IS_CYGWIN == YES ]]; then SRS_CYGWIN64=YES; fi
154168

155169
if [[ $OS_IS_OSX == YES ]]; then SRS_JOBS=$(sysctl -n hw.ncpu 2>/dev/null || echo 1); fi

trunk/configure

+1-1
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ if [[ $SRS_UTEST == YES ]]; then
464464
MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_kernel" "srs_utest_core"
465465
"srs_utest_config" "srs_utest_rtmp" "srs_utest_http" "srs_utest_avc" "srs_utest_reload"
466466
"srs_utest_mp4" "srs_utest_service" "srs_utest_app" "srs_utest_rtc" "srs_utest_config2"
467-
"srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2")
467+
"srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2" "srs_utest_st")
468468
if [[ $SRS_SRT == YES ]]; then
469469
MODULE_FILES+=("srs_utest_srt")
470470
fi

trunk/src/utest/srs_utest_st.cpp

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//
2+
// Copyright (c) 2013-2024 The SRS Authors
3+
//
4+
// SPDX-License-Identifier: MIT
5+
//
6+
#include <srs_utest_st.hpp>
7+
#include <sys/time.h>
8+
#include <time.h>
9+
#include <unistd.h>
10+
11+
using namespace std;
12+
13+
VOID TEST(StTest, StUtimeInMicroseconds)
14+
{
15+
st_utime_t st_time_1 = st_utime();
16+
// sleep 1 microsecond
17+
#if !defined(SRS_CYGWIN64)
18+
usleep(1);
19+
#endif
20+
st_utime_t st_time_2 = st_utime();
21+
22+
EXPECT_GT(st_time_1, 0);
23+
EXPECT_GT(st_time_2, 0);
24+
EXPECT_GT(st_time_2, st_time_1);
25+
// st_time_2 - st_time_1 should be in range of [1, 100] microseconds
26+
EXPECT_GE(st_time_2 - st_time_1, 1);
27+
EXPECT_LE(st_time_2 - st_time_1, 100);
28+
}
29+
30+
static inline st_utime_t time_gettimeofday() {
31+
struct timeval tv;
32+
gettimeofday(&tv, NULL);
33+
return (tv.tv_sec * 1000000LL + tv.tv_usec);
34+
}
35+
36+
VOID TEST(StTest, StUtimePerformance)
37+
{
38+
clock_t start;
39+
int gettimeofday_elapsed_time = 0;
40+
int st_utime_elapsed_time = 0;
41+
42+
// Both the st_utime(clock_gettime or gettimeofday) and gettimeofday's
43+
// elpased time to execute is dependence on whether it is the first time be called.
44+
// In general, the gettimeofday has better performance, but the gap between
45+
// them is really small, maybe less than 10 clock ~ 10 microseconds.
46+
47+
// check st_utime first, then gettimeofday
48+
{
49+
start = clock();
50+
st_utime_t t2 = st_utime();
51+
int elapsed_time = clock() - start;
52+
st_utime_elapsed_time += elapsed_time;
53+
EXPECT_GT(t2, 0);
54+
55+
start = clock();
56+
st_utime_t t1 = time_gettimeofday();
57+
elapsed_time = clock() - start;
58+
gettimeofday_elapsed_time += elapsed_time;
59+
EXPECT_GT(t1, 0);
60+
61+
62+
EXPECT_GE(gettimeofday_elapsed_time, 0);
63+
EXPECT_GE(st_utime_elapsed_time, 0);
64+
65+
// pass the test, if
66+
EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ?
67+
gettimeofday_elapsed_time - st_utime_elapsed_time :
68+
st_utime_elapsed_time - gettimeofday_elapsed_time, 10);
69+
}
70+
71+
// check gettimeofday first, then st_utime
72+
{
73+
start = clock();
74+
st_utime_t t1 = time_gettimeofday();
75+
int elapsed_time = clock() - start;
76+
gettimeofday_elapsed_time += elapsed_time;
77+
EXPECT_GT(t1, 0);
78+
79+
start = clock();
80+
st_utime_t t2 = st_utime();
81+
elapsed_time = clock() - start;
82+
st_utime_elapsed_time += elapsed_time;
83+
EXPECT_GT(t2, 0);
84+
85+
EXPECT_GE(gettimeofday_elapsed_time, 0);
86+
EXPECT_GE(st_utime_elapsed_time, 0);
87+
88+
EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ?
89+
gettimeofday_elapsed_time - st_utime_elapsed_time :
90+
st_utime_elapsed_time - gettimeofday_elapsed_time, 10);
91+
}
92+
93+
// compare st_utime & gettimeofday in a loop
94+
for (int i = 0; i < 100; i++) {
95+
start = clock();
96+
st_utime_t t2 = st_utime();
97+
int elapsed_time = clock() - start;
98+
st_utime_elapsed_time = elapsed_time;
99+
EXPECT_GT(t2, 0);
100+
usleep(1);
101+
102+
start = clock();
103+
st_utime_t t1 = time_gettimeofday();
104+
elapsed_time = clock() - start;
105+
gettimeofday_elapsed_time = elapsed_time;
106+
EXPECT_GT(t1, 0);
107+
usleep(1);
108+
109+
EXPECT_GE(gettimeofday_elapsed_time, 0);
110+
EXPECT_GE(st_utime_elapsed_time, 0);
111+
112+
EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ?
113+
gettimeofday_elapsed_time - st_utime_elapsed_time :
114+
st_utime_elapsed_time - gettimeofday_elapsed_time, 10);
115+
116+
}
117+
}

trunk/src/utest/srs_utest_st.hpp

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// Copyright (c) 2013-2024 The SRS Authors
3+
//
4+
// SPDX-License-Identifier: MIT
5+
//
6+
7+
#ifndef SRS_UTEST_ST_HPP
8+
#define SRS_UTEST_ST_HPP
9+
10+
#include <srs_utest.hpp>
11+
12+
#include <st.h>
13+
14+
#endif // SRS_UTEST_ST_HPP
15+

0 commit comments

Comments
 (0)