Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
benchmark
Project
Overview
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
benchmark
Commits
4f9ce87e
Commit
4f9ce87e
authored
Mar 27, 2015
by
Eric Fiselier
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into new-benchmark-interface
parents
c5f238b1
0a0bb8fe
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
170 additions
and
98 deletions
+170
-98
CMakeLists.txt
CMakeLists.txt
+1
-0
steady_clock.cpp
cmake/steady_clock.cpp
+7
-0
benchmark_api.h
include/benchmark/benchmark_api.h
+26
-16
benchmark.cc
src/benchmark.cc
+0
-28
json_reporter.cc
src/json_reporter.cc
+2
-5
reporter.cc
src/reporter.cc
+3
-6
sysinfo.cc
src/sysinfo.cc
+29
-0
sysinfo.h
src/sysinfo.h
+1
-0
walltime.cc
src/walltime.cc
+80
-35
walltime.h
src/walltime.h
+3
-8
basic_test.cc
test/basic_test.cc
+18
-0
No files found.
CMakeLists.txt
View file @
4f9ce87e
...
...
@@ -54,6 +54,7 @@ endif()
cxx_feature_check
(
STD_REGEX
)
cxx_feature_check
(
GNU_POSIX_REGEX
)
cxx_feature_check
(
POSIX_REGEX
)
cxx_feature_check
(
STEADY_CLOCK
)
# Set up directories
include_directories
(
${
PROJECT_SOURCE_DIR
}
/include
)
...
...
cmake/steady_clock.cpp
0 → 100644
View file @
4f9ce87e
#include <chrono>
int
main
()
{
typedef
std
::
chrono
::
steady_clock
Clock
;
Clock
::
time_point
tp
=
Clock
::
now
();
((
void
)
tp
);
}
include/benchmark/benchmark_api.h
View file @
4f9ce87e
...
...
@@ -432,14 +432,27 @@ class Benchmark {
// ------------------------------------------------------
// Macro to register benchmarks
// Check that __COUNTER__ is defined and that __COUNTER__ increases by 1
// every time it is expanded. X + 1 == X + 0 is used in case X is defined to be
// empty. If X is empty the expression becomes (+1 == +0).
#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
#else
#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
#endif
// Helpers for generating unique variable names
#define BENCHMARK_CONCAT(a, b, c) BENCHMARK_CONCAT2(a, b, c)
#define BENCHMARK_CONCAT2(a, b, c) a##b##c
#define BENCHMARK_PRIVATE_NAME(n) \
BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, n)
#define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
#define BENCHMARK_PRIVATE_DECLARE(n) \
static ::benchmark::internal::Benchmark* \
BENCHMARK_PRIVATE_NAME(n) BENCHMARK_UNUSED
#define BENCHMARK(n) \
static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT( \
_benchmark_, n, __LINE__) BENCHMARK_UNUSED = \
(new ::benchmark::internal::Benchmark(#n, n))
#define BENCHMARK(n) \
BENCHMARK_PRIVATE_DECLARE(n) = (new ::benchmark::internal::Benchmark(#n, n))
// Old-style macros
#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
...
...
@@ -456,21 +469,18 @@ class Benchmark {
// BENCHMARK_TEMPLATE(BM_Foo, 1);
//
// will register BM_Foo<1> as a benchmark.
#define BENCHMARK_TEMPLATE1(n, a) \
static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT( \
_benchmark_, n, __LINE__) BENCHMARK_UNUSED = \
#define BENCHMARK_TEMPLATE1(n, a) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(new ::benchmark::internal::Benchmark(#n "<" #a ">", n<a>))
#define BENCHMARK_TEMPLATE2(n, a, b) \
static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT( \
_benchmark_, n, __LINE__) BENCHMARK_UNUSED = \
#define BENCHMARK_TEMPLATE2(n, a, b) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(new ::benchmark::internal::Benchmark(#n "<" #a "," #b ">", n<a, b>))
#if __cplusplus >= 201103L
#define BENCHMARK_TEMPLATE(n, ...) \
static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT( \
_benchmark_, n, __LINE__) BENCHMARK_UNUSED = \
(new ::benchmark::internal::Benchmark( \
#define BENCHMARK_TEMPLATE(n, ...) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(new ::benchmark::internal::Benchmark( \
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>))
#else
#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
...
...
src/benchmark.cc
View file @
4f9ce87e
...
...
@@ -65,17 +65,6 @@ DEFINE_bool(color_print, true, "Enables colorized logging.");
DEFINE_int32
(
v
,
0
,
"The level of verbose logging to output"
);
// The ""'s catch people who don't pass in a literal for "str"
#define strliterallen(str) (sizeof("" str "") - 1)
// Must use a string literal for prefix.
#define memprefix(str, len, prefix) \
((((len) >= strliterallen(prefix)) && \
std::memcmp(str, prefix, strliterallen(prefix)) == 0) \
? str + strliterallen(prefix) \
: nullptr)
namespace
benchmark
{
namespace
internal
{
...
...
@@ -116,23 +105,6 @@ std::string* GetReportLabel() {
// TODO(ericwf): support MallocCounter.
//static benchmark::MallocCounter *benchmark_mc;
static
bool
CpuScalingEnabled
()
{
// On Linux, the CPUfreq subsystem exposes CPU information as files on the
// local file system. If reading the exported files fails, then we may not be
// running on Linux, so we silently ignore all the read errors.
for
(
int
cpu
=
0
,
num_cpus
=
NumCPUs
();
cpu
<
num_cpus
;
++
cpu
)
{
std
::
string
governor_file
=
StrCat
(
"/sys/devices/system/cpu/cpu"
,
cpu
,
"/cpufreq/scaling_governor"
);
FILE
*
file
=
fopen
(
governor_file
.
c_str
(),
"r"
);
if
(
!
file
)
break
;
char
buff
[
16
];
size_t
bytes_read
=
fread
(
buff
,
1
,
sizeof
(
buff
),
file
);
fclose
(
file
);
if
(
memprefix
(
buff
,
bytes_read
,
"performance"
)
==
nullptr
)
return
true
;
}
return
false
;
}
struct
ThreadStats
{
ThreadStats
()
:
bytes_processed
(
0
),
items_processed
(
0
)
{}
int64_t
bytes_processed
;
...
...
src/json_reporter.cc
View file @
4f9ce87e
...
...
@@ -65,11 +65,8 @@ bool JSONReporter::ReportContext(const Context& context) {
// Open context block and print context information.
out
<<
inner_indent
<<
"
\"
context
\"
: {
\n
"
;
std
::
string
indent
(
4
,
' '
);
int
remainder_us
;
std
::
string
walltime_value
=
walltime
::
Print
(
walltime
::
Now
(),
"%Y/%m/%d-%H:%M:%S"
,
true
,
// use local timezone
&
remainder_us
);
std
::
string
walltime_value
=
LocalDateTimeString
();
out
<<
indent
<<
FormatKV
(
"date"
,
walltime_value
)
<<
",
\n
"
;
out
<<
indent
...
...
src/reporter.cc
View file @
4f9ce87e
...
...
@@ -98,16 +98,13 @@ bool ConsoleReporter::ReportContext(const Context& context) {
context
.
mhz_per_cpu
,
(
context
.
num_cpus
>
1
)
?
"s"
:
""
);
int
remainder_us
;
std
::
string
walltime_str
=
walltime
::
Print
(
walltime
::
Now
(),
"%Y/%m/%d-%H:%M:%S"
,
true
,
// use local timezone
&
remainder_us
);
std
::
string
walltime_str
=
LocalDateTimeString
();
fprintf
(
stdout
,
"%s
\n
"
,
walltime_str
.
c_str
());
if
(
context
.
cpu_scaling_enabled
)
{
fprintf
(
stdout
,
"***WARNING*** CPU scaling is enabled, the benchmark "
"timings may be noisy
\n
"
);
"real time measurements may be noisy and will incure extra "
"overhead.
\n
"
);
}
#ifndef NDEBUG
...
...
src/sysinfo.cc
View file @
4f9ce87e
...
...
@@ -36,6 +36,7 @@
#include "internal_macros.h"
#include "log.h"
#include "sleep.h"
#include "string_util.h"
namespace
benchmark
{
namespace
{
...
...
@@ -352,4 +353,32 @@ int NumCPUs(void) {
std
::
call_once
(
cpuinfo_init
,
InitializeSystemInfo
);
return
cpuinfo_num_cpus
;
}
// The ""'s catch people who don't pass in a literal for "str"
#define strliterallen(str) (sizeof("" str "") - 1)
// Must use a string literal for prefix.
#define memprefix(str, len, prefix) \
((((len) >= strliterallen(prefix)) && \
std::memcmp(str, prefix, strliterallen(prefix)) == 0) \
? str + strliterallen(prefix) \
: nullptr)
bool
CpuScalingEnabled
()
{
// On Linux, the CPUfreq subsystem exposes CPU information as files on the
// local file system. If reading the exported files fails, then we may not be
// running on Linux, so we silently ignore all the read errors.
for
(
int
cpu
=
0
,
num_cpus
=
NumCPUs
();
cpu
<
num_cpus
;
++
cpu
)
{
std
::
string
governor_file
=
StrCat
(
"/sys/devices/system/cpu/cpu"
,
cpu
,
"/cpufreq/scaling_governor"
);
FILE
*
file
=
fopen
(
governor_file
.
c_str
(),
"r"
);
if
(
!
file
)
break
;
char
buff
[
16
];
size_t
bytes_read
=
fread
(
buff
,
1
,
sizeof
(
buff
),
file
);
fclose
(
file
);
if
(
memprefix
(
buff
,
bytes_read
,
"performance"
)
==
nullptr
)
return
true
;
}
return
false
;
}
}
// end namespace benchmark
src/sysinfo.h
View file @
4f9ce87e
...
...
@@ -6,6 +6,7 @@ double MyCPUUsage();
double
ChildrenCPUUsage
();
int
NumCPUs
();
double
CyclesPerSecond
();
bool
CpuScalingEnabled
();
}
// end namespace benchmark
#endif // BENCHMARK_SYSINFO_H_
src/walltime.cc
View file @
4f9ce87e
...
...
@@ -22,37 +22,40 @@
#include <ctime>
#include <atomic>
#include <chrono>
#include <limits>
#include <type_traits>
#include "arraysize.h"
#include "check.h"
#include "cycleclock.h"
#include "log.h"
#include "sysinfo.h"
namespace
benchmark
{
namespace
walltime
{
namespace
{
bool
SplitTimezone
(
WallTime
value
,
bool
local
,
struct
tm
*
t
,
double
*
subsecond
)
{
memset
(
t
,
0
,
sizeof
(
*
t
));
if
((
value
<
0
)
||
(
value
>
std
::
numeric_limits
<
time_t
>::
max
()))
{
*
subsecond
=
0.0
;
return
false
;
}
const
time_t
whole_time
=
static_cast
<
time_t
>
(
value
);
*
subsecond
=
value
-
whole_time
;
if
(
local
)
localtime_r
(
&
whole_time
,
t
);
else
gmtime_r
(
&
whole_time
,
t
);
return
true
;
}
namespace
{
}
// end anonymous namespace
#if defined(HAVE_STEADY_CLOCK)
template
<
bool
HighResIsSteady
=
std
::
chrono
::
high_resolution_clock
::
is_steady
>
struct
ChooseSteadyClock
{
typedef
std
::
chrono
::
high_resolution_clock
type
;
};
template
<>
struct
ChooseSteadyClock
<
false
>
{
typedef
std
::
chrono
::
steady_clock
type
;
};
#endif
namespace
{
struct
ChooseClockType
{
#if defined(HAVE_STEADY_CLOCK)
typedef
typename
ChooseSteadyClock
<>::
type
type
;
#else
typedef
std
::
chrono
::
high_resolution_clock
type
;
#endif
};
class
WallTimeImp
{
...
...
@@ -160,32 +163,74 @@ WallTimeImp::WallTimeImp()
last_adjust_time_
=
static_cast
<
uint32_t
>
(
uint64_t
(
base_cycletime_
)
>>
32
);
}
}
// end anonymous namespace
WallTime
CPUWalltimeNow
()
{
static
WallTimeImp
&
imp
=
WallTimeImp
::
GetWallTimeImp
();
return
imp
.
Now
();
}
WallTime
ChronoWalltimeNow
()
{
typedef
ChooseClockType
::
type
Clock
;
typedef
std
::
chrono
::
duration
<
WallTime
,
std
::
chrono
::
seconds
::
period
>
FPSeconds
;
static_assert
(
std
::
chrono
::
treat_as_floating_point
<
WallTime
>::
value
,
"This type must be treated as a floating point type."
);
auto
now
=
Clock
::
now
().
time_since_epoch
();
return
std
::
chrono
::
duration_cast
<
FPSeconds
>
(
now
).
count
();
}
bool
UseCpuCycleClock
()
{
bool
useWallTime
=
!
CpuScalingEnabled
();
if
(
useWallTime
)
{
VLOG
(
1
)
<<
"Using the CPU cycle clock to provide walltime::Now().
\n
"
;
}
else
{
VLOG
(
1
)
<<
"Using std::chrono to provide walltime::Now().
\n
"
;
}
return
useWallTime
;
}
}
// end anonymous namespace
// WallTimeImp doesn't work when CPU Scaling is enabled. If CPU Scaling is
// enabled at the start of the program then std::chrono::system_clock is used
// instead.
WallTime
Now
()
{
static
WallTimeImp
&
imp
=
WallTimeImp
::
GetWallTimeImp
();
return
imp
.
Now
();
static
bool
useCPUClock
=
UseCpuCycleClock
();
if
(
useCPUClock
)
{
return
CPUWalltimeNow
();
}
else
{
return
ChronoWalltimeNow
();
}
}
std
::
string
Print
(
WallTime
time
,
const
char
*
format
,
bool
local
,
int
*
remainder_us
)
{
char
storage
[
32
];
struct
tm
split
;
double
subsecond
;
if
(
!
SplitTimezone
(
time
,
local
,
&
split
,
&
subsecond
))
{
snprintf
(
storage
,
sizeof
(
storage
),
"Invalid time: %f"
,
time
);
}
// end namespace walltime
namespace
{
std
::
string
DateTimeString
(
bool
local
)
{
typedef
std
::
chrono
::
system_clock
Clock
;
std
::
time_t
now
=
Clock
::
to_time_t
(
Clock
::
now
());
char
storage
[
128
];
std
::
tm
timeinfo
;
std
::
memset
(
&
timeinfo
,
0
,
sizeof
(
std
::
tm
));
if
(
local
)
{
::
localtime_r
(
&
now
,
&
timeinfo
);
}
else
{
if
(
remainder_us
!=
nullptr
)
{
*
remainder_us
=
static_cast
<
int
>
((
subsecond
*
1000000
)
+
0.5
);
if
(
*
remainder_us
>
999999
)
*
remainder_us
=
999999
;
if
(
*
remainder_us
<
0
)
*
remainder_us
=
0
;
}
strftime
(
storage
,
sizeof
(
storage
),
format
,
&
split
);
::
gmtime_r
(
&
now
,
&
timeinfo
);
}
std
::
size_t
written
=
std
::
strftime
(
storage
,
sizeof
(
storage
),
"%F %T"
,
&
timeinfo
);
CHECK
(
written
<
arraysize
(
storage
));
((
void
)
written
);
// prevent unused variable in optimized mode.
return
std
::
string
(
storage
);
}
}
// end namespace walltime
}
// end namespace
std
::
string
LocalDateTimeString
()
{
return
DateTimeString
(
true
);
}
}
// end namespace benchmark
src/walltime.h
View file @
4f9ce87e
...
...
@@ -8,15 +8,10 @@ typedef double WallTime;
namespace
walltime
{
WallTime
Now
();
// GIVEN: walltime, generic format string (as understood by strftime),
// a boolean flag specifying if the time is local or UTC (true=local).
// RETURNS: the formatted string. ALSO RETURNS: the remaining number of
// microseconds (never printed in the string since strftime does not understand
// it)
std
::
string
Print
(
WallTime
time
,
const
char
*
format
,
bool
local
,
int
*
remainder_us
);
}
// end namespace walltime
std
::
string
LocalDateTimeString
();
}
// end namespace benchmark
#endif // BENCHMARK_WALLTIME_H_
test/basic_test.cc
View file @
4f9ce87e
...
...
@@ -59,6 +59,24 @@ void BM_spin_pause_during(benchmark::State& state) {
BASIC_BENCHMARK_TEST
(
BM_spin_pause_during
);
BASIC_BENCHMARK_TEST
(
BM_spin_pause_during
)
->
ThreadPerCpu
();
void
BM_pause_during
(
benchmark
::
State
&
state
)
{
while
(
state
.
KeepRunning
())
{
state
.
PauseTiming
();
state
.
ResumeTiming
();
}
}
BENCHMARK
(
BM_pause_during
);
BENCHMARK
(
BM_pause_during
)
->
ThreadPerCpu
();
void
BM_pause_during_realtime
(
benchmark
::
State
&
state
)
{
state
.
UseRealTime
();
while
(
state
.
KeepRunning
())
{
state
.
PauseTiming
();
state
.
ResumeTiming
();
}
}
BENCHMARK
(
BM_pause_during_realtime
);
BENCHMARK
(
BM_pause_during_realtime
)
->
ThreadPerCpu
();
void
BM_spin_pause_after
(
benchmark
::
State
&
state
)
{
while
(
state
.
KeepRunning
())
{
...
...
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