Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
brpc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
brpc
Commits
189098f9
Commit
189098f9
authored
Oct 10, 2018
by
gejun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert time.cpp and use monotonic-time to implement cpuwide_time outside baidu
parent
8aabf87f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
50 additions
and
132 deletions
+50
-132
time.cpp
src/butil/time.cpp
+38
-132
time.h
src/butil/time.h
+12
-0
No files found.
src/butil/time.cpp
View file @
189098f9
...
@@ -25,7 +25,6 @@
...
@@ -25,7 +25,6 @@
#endif
#endif
#include <string.h> // memmem
#include <string.h> // memmem
#undef _GNU_SOURCE
#undef _GNU_SOURCE
#include <ctype.h>
#include "butil/time.h"
#include "butil/time.h"
...
@@ -82,7 +81,8 @@ int64_t monotonic_time_ns() {
...
@@ -82,7 +81,8 @@ int64_t monotonic_time_ns() {
namespace
detail
{
namespace
detail
{
static
int64_t
read_cpu_current_frequency
(
char
*
buf
,
ssize_t
n
)
{
// read_cpu_frequency() is modified from source code of glibc.
int64_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
...
@@ -90,148 +90,54 @@ static int64_t read_cpu_current_frequency(char* buf, ssize_t n) {
...
@@ -90,148 +90,54 @@ static int64_t read_cpu_current_frequency(char* buf, ssize_t n) {
cpu MHz : 497.841
cpu MHz : 497.841
We search for this line and convert the number in an integer. */
We search for this line and convert the number in an integer. */
int64_t
result
=
0
;
char
*
mhz
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"cpu MHz"
,
7
));
if
(
mhz
!=
NULL
)
{
char
*
endp
=
buf
+
n
;
int
seen_decpoint
=
0
;
int
ndigits
=
0
;
/* Search for the beginning of the string. */
while
(
mhz
<
endp
&&
(
*
mhz
<
'0'
||
*
mhz
>
'9'
)
&&
*
mhz
!=
'\n'
)
{
++
mhz
;
}
while
(
mhz
<
endp
&&
*
mhz
!=
'\n'
)
{
if
(
*
mhz
>=
'0'
&&
*
mhz
<=
'9'
)
{
result
*=
10
;
result
+=
*
mhz
-
'0'
;
if
(
seen_decpoint
)
++
ndigits
;
}
else
if
(
*
mhz
==
'.'
)
{
seen_decpoint
=
1
;
}
++
mhz
;
}
/* Compensate for missing digits at the end. */
while
(
ndigits
++
<
6
)
{
result
*=
10
;
}
}
return
result
;
}
#if defined(__x86_64__) || defined(__i386__)
#if defined(__pic__) && defined(__i386__)
static
void
__cpuid
(
uint32_t
reg
[
4
],
uint32_t
code
)
{
__asm__
volatile
(
"mov %%ebx, %%edi
\n
"
"cpuid
\n
"
"xchg %%edi, %%ebx
\n
"
:
"=a"
(
reg
[
0
]),
"=D"
(
reg
[
1
]),
"=c"
(
reg
[
2
]),
"=d"
(
reg
[
3
])
:
"a"
(
code
)
);
}
#else
static
void
__cpuid
(
uint32_t
reg
[
4
],
uint32_t
code
)
{
__asm__
volatile
(
"cpuid
\n\t
"
:
"=a"
(
reg
[
0
]),
"=b"
(
reg
[
1
]),
"=c"
(
reg
[
2
]),
"=d"
(
reg
[
3
])
:
"a"
(
code
)
);
}
#endif
#endif
static
int64_t
read_cpu_frequency_by_cpuid
()
{
int64_t
result
=
0
;
#if defined(__x86_64__) || defined(__i386__)
uint32_t
reg
[
4
];
__cpuid
(
reg
,
0
);
if
(
reg
[
0
]
>=
0x16
&&
reg
[
1
]
==
0x756e6547
&&
reg
[
2
]
==
0x6c65746e
&&
reg
[
3
]
==
0x49656e69
)
{
//Intel CPU only
__cpuid
(
reg
,
0x16
);
return
static_cast
<
uint64_t
>
(
reg
[
0
])
*
1000000UL
;
}
#endif
return
result
;
}
static
int64_t
read_cpu_frequency_from_brand_string
()
{
int64_t
result
=
0
;
#if defined(__x86_64__) || defined(__i386__)
union
{
char
brand
[
48
];
uint32_t
reg
[
12
];
}
buf
;
__cpuid
(
buf
.
reg
,
0x80000000
);
if
(
buf
.
reg
[
0
]
<
0x80000004
)
{
return
0
;
}
__cpuid
(
buf
.
reg
,
0x80000002
);
__cpuid
(
buf
.
reg
+
4
,
0x80000003
);
__cpuid
(
buf
.
reg
+
8
,
0x80000004
);
//Get something like: Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz
char
*
end
=
buf
.
brand
+
sizeof
(
buf
.
brand
);
char
*
p
=
buf
.
brand
;
while
(
p
!=
end
&&
*
p
!=
'@'
)
{
if
(
*
p
++
==
'\n'
)
{
return
0
;
}
}
while
(
p
!=
end
&&
!
isdigit
(
*
p
))
{
p
++
;
}
//expect x.xxGhz
//FSB may be 0.10GHz or 0.133...GHz
if
(
end
-
p
<
7
||
p
[
1
]
!=
'.'
||
!
isdigit
(
p
[
2
])
||
!
isdigit
(
p
[
3
])
||
p
[
4
]
!=
'G'
)
{
return
0
;
}
result
=
(
p
[
0
]
-
'0'
)
*
10
+
(
p
[
2
]
-
'0'
);
int64_t
last
=
p
[
3
]
-
'0'
;
if
(
last
==
7
)
{
last
=
6
;
}
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
result
=
result
*
10
+
last
;
}
#endif
return
result
;
}
// read_cpu_frequency() is modified from source code of glibc.
int64_t
read_cpu_frequency
(
bool
*
invariant_tsc
)
{
const
int
fd
=
open
(
"/proc/cpuinfo"
,
O_RDONLY
);
const
int
fd
=
open
(
"/proc/cpuinfo"
,
O_RDONLY
);
if
(
fd
<
0
)
{
if
(
fd
<
0
)
{
return
0
;
return
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
));
close
(
fd
);
if
(
n
>
0
)
{
if
(
n
<=
0
)
{
char
*
mhz
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"cpu MHz"
,
7
));
return
0
;
}
if
(
mhz
!=
NULL
)
{
char
*
endp
=
buf
+
n
;
int
seen_decpoint
=
0
;
int
ndigits
=
0
;
if
(
invariant_tsc
)
{
/* Search for the beginning of the string. */
char
*
flags_pos
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"flags"
,
5
));
while
(
mhz
<
endp
&&
(
*
mhz
<
'0'
||
*
mhz
>
'9'
)
&&
*
mhz
!=
'\n'
)
{
if
(
flags_pos
++
mhz
;
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"constant_tsc"
,
12
)
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"nonstop_tsc"
,
11
))
{
int64_t
result
=
read_cpu_frequency_by_cpuid
();
if
(
result
<=
0
)
{
result
=
read_cpu_frequency_from_brand_string
();
}
}
if
(
result
>
0
)
{
while
(
mhz
<
endp
&&
*
mhz
!=
'\n'
)
{
*
invariant_tsc
=
true
;
if
(
*
mhz
>=
'0'
&&
*
mhz
<=
'9'
)
{
return
result
;
result
*=
10
;
result
+=
*
mhz
-
'0'
;
if
(
seen_decpoint
)
++
ndigits
;
}
else
if
(
*
mhz
==
'.'
)
{
seen_decpoint
=
1
;
}
++
mhz
;
}
}
/* Compensate for missing digits at the end. */
while
(
ndigits
++
<
6
)
{
result
*=
10
;
}
}
if
(
invariant_tsc
)
{
char
*
flags_pos
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"flags"
,
5
));
*
invariant_tsc
=
(
flags_pos
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"constant_tsc"
,
12
)
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"nonstop_tsc"
,
11
));
}
}
//current frequency is usually not invariant
*
invariant_tsc
=
false
;
}
}
return
read_cpu_current_frequency
(
buf
,
n
);
close
(
fd
);
return
result
;
}
}
// Return value must be >= 0
// Return value must be >= 0
...
...
src/butil/time.h
View file @
189098f9
...
@@ -236,6 +236,17 @@ extern int64_t invariant_cpu_freq;
...
@@ -236,6 +236,17 @@ extern int64_t invariant_cpu_freq;
// note: Inlining shortens time cost per-call for 15ns in a loop of many
// note: Inlining shortens time cost per-call for 15ns in a loop of many
// calls to this function.
// calls to this function.
inline
int64_t
cpuwide_time_ns
()
{
inline
int64_t
cpuwide_time_ns
()
{
#if !defined(BAIDU_INTERNAL)
// 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.
// Since clock_gettime() in newer glibc/kernel is much faster(~30ns)
// which is closer to the previous impl. of cpuwide_time(~10ns), we
// simply use the monotonic time to get rid of all related issues.
timespec
now
;
clock_gettime
(
CLOCK_MONOTONIC
,
&
now
);
return
now
.
tv_sec
*
1000000000L
+
now
.
tv_nsec
;
#else
int64_t
cpu_freq
=
detail
::
invariant_cpu_freq
;
int64_t
cpu_freq
=
detail
::
invariant_cpu_freq
;
if
(
cpu_freq
>
0
)
{
if
(
cpu_freq
>
0
)
{
const
uint64_t
tsc
=
detail
::
clock_cycles
();
const
uint64_t
tsc
=
detail
::
clock_cycles
();
...
@@ -253,6 +264,7 @@ inline int64_t cpuwide_time_ns() {
...
@@ -253,6 +264,7 @@ inline int64_t cpuwide_time_ns() {
detail
::
invariant_cpu_freq
=
detail
::
read_invariant_cpu_frequency
();
detail
::
invariant_cpu_freq
=
detail
::
read_invariant_cpu_frequency
();
return
cpuwide_time_ns
();
return
cpuwide_time_ns
();
}
}
#endif // defined(BAIDU_INTERNAL)
}
}
inline
int64_t
cpuwide_time_us
()
{
inline
int64_t
cpuwide_time_us
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment