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
332f677b
Commit
332f677b
authored
Oct 07, 2016
by
Dominic Hamon
Committed by
GitHub
Oct 07, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Apply clang-format to all headers and source (#303)
parent
1100e919
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
554 additions
and
646 deletions
+554
-646
benchmark.h
include/benchmark/benchmark.h
+2
-2
benchmark_api.h
include/benchmark/benchmark_api.h
+153
-172
macros.h
include/benchmark/macros.h
+28
-28
reporter.h
include/benchmark/reporter.h
+20
-27
arraysize.h
src/arraysize.h
+3
-4
benchmark.cc
src/benchmark.cc
+66
-78
benchmark_api_internal.h
src/benchmark_api_internal.h
+23
-22
benchmark_register.cc
src/benchmark_register.cc
+50
-54
check.h
src/check.h
+21
-20
colorprint.cc
src/colorprint.cc
+10
-10
colorprint.h
src/colorprint.h
+3
-2
commandlineflags.cc
src/commandlineflags.cc
+4
-4
complexity.cc
src/complexity.cc
+1
-2
complexity.h
src/complexity.h
+3
-6
console_reporter.cc
src/console_reporter.cc
+25
-26
csv_reporter.cc
src/csv_reporter.cc
+8
-18
internal_macros.h
src/internal_macros.h
+14
-15
json_reporter.cc
src/json_reporter.cc
+22
-41
log.h
src/log.h
+6
-4
mutex.h
src/mutex.h
+23
-34
re.h
src/re.h
+5
-5
reporter.cc
src/reporter.cc
+11
-18
stat.h
src/stat.h
+1
-2
string_util.cc
src/string_util.cc
+12
-13
string_util.h
src/string_util.h
+9
-13
sysinfo.cc
src/sysinfo.cc
+18
-13
timers.cc
src/timers.cc
+13
-13
No files found.
include/benchmark/benchmark.h
View file @
332f677b
...
...
@@ -14,8 +14,8 @@
#ifndef BENCHMARK_BENCHMARK_H_
#define BENCHMARK_BENCHMARK_H_
#include "macros.h"
#include "benchmark_api.h"
#include "macros.h"
#include "reporter.h"
#endif // BENCHMARK_BENCHMARK_H_
#endif
// BENCHMARK_BENCHMARK_H_
include/benchmark/benchmark_api.h
View file @
332f677b
...
...
@@ -153,8 +153,8 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include <string>
#include <vector>
#include "macros.h"
...
...
@@ -174,7 +174,8 @@ void Initialize(int* argc, char** argv);
// report the results.
//
// The second and third overload use the specified 'console_reporter' and
// 'file_reporter' respectively. 'file_reporter' will write to the file specified
// 'file_reporter' respectively. 'file_reporter' will write to the file
// specified
// by '--benchmark_output'. If '--benchmark_output' is not given the
// 'file_reporter' is ignored.
//
...
...
@@ -184,7 +185,6 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter);
size_t
RunSpecifiedBenchmarks
(
BenchmarkReporter
*
console_reporter
,
BenchmarkReporter
*
file_reporter
);
// If this routine is called, peak memory allocation past this point in the
// benchmark is reported at the end of the benchmark report line. (It is
// computed by running the benchmark once with a single iteration and a memory
...
...
@@ -197,8 +197,9 @@ class Benchmark;
class
BenchmarkImp
;
class
BenchmarkFamilies
;
template
<
class
T
>
struct
Voider
{
typedef
void
type
;
template
<
class
T
>
struct
Voider
{
typedef
void
type
;
};
template
<
class
T
,
class
=
void
>
...
...
@@ -206,7 +207,7 @@ struct EnableIfString {};
template
<
class
T
>
struct
EnableIfString
<
T
,
typename
Voider
<
typename
T
::
basic_string
>::
type
>
{
typedef
int
type
;
typedef
int
type
;
};
void
UseCharPointer
(
char
const
volatile
*
);
...
...
@@ -219,8 +220,7 @@ Benchmark* RegisterBenchmarkInternal(Benchmark*);
int
InitializeStreams
();
BENCHMARK_UNUSED
static
int
stream_init_anchor
=
InitializeStreams
();
}
// end namespace internal
}
// end namespace internal
// The DoNotOptimize(...) function can be used to prevent a value or
// expression from being optimized away by the compiler. This function is
...
...
@@ -229,45 +229,32 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
#if defined(__GNUC__)
template
<
class
Tp
>
inline
BENCHMARK_ALWAYS_INLINE
void
DoNotOptimize
(
Tp
const
&
value
)
{
asm
volatile
(
""
:
:
"g"
(
value
)
:
"memory"
);
asm
volatile
(
""
:
:
"g"
(
value
)
:
"memory"
);
}
// Force the compiler to flush pending writes to global memory. Acts as an
// effective read/write barrier
inline
BENCHMARK_ALWAYS_INLINE
void
ClobberMemory
()
{
asm
volatile
(
""
:
:
:
"memory"
);
asm
volatile
(
""
:
:
:
"memory"
);
}
#else
template
<
class
Tp
>
inline
BENCHMARK_ALWAYS_INLINE
void
DoNotOptimize
(
Tp
const
&
value
)
{
internal
::
UseCharPointer
(
&
reinterpret_cast
<
char
const
volatile
&>
(
value
));
internal
::
UseCharPointer
(
&
reinterpret_cast
<
char
const
volatile
&>
(
value
));
}
// FIXME Add ClobberMemory() for non-gnu compilers
#endif
// TimeUnit is passed to a benchmark in order to specify the order of magnitude
// for the measured time.
enum
TimeUnit
{
kNanosecond
,
kMicrosecond
,
kMillisecond
};
enum
TimeUnit
{
kNanosecond
,
kMicrosecond
,
kMillisecond
};
// BigO is passed to a benchmark in order to specify the asymptotic computational
// complexity for the benchmark. In case oAuto is selected, complexity will be
// BigO is passed to a benchmark in order to specify the asymptotic
// computational
// complexity for the benchmark. In case oAuto is selected, complexity will be
// calculated automatically to the best fit.
enum
BigO
{
oNone
,
o1
,
oN
,
oNSquared
,
oNCubed
,
oLogN
,
oNLogN
,
oAuto
,
oLambda
};
enum
BigO
{
oNone
,
o1
,
oN
,
oNSquared
,
oNCubed
,
oLogN
,
oNLogN
,
oAuto
,
oLambda
};
// BigOFunc is passed to a benchmark in order to specify the asymptotic
// BigOFunc is passed to a benchmark in order to specify the asymptotic
// computational complexity for the benchmark.
typedef
double
(
BigOFunc
)(
int
);
...
...
@@ -280,17 +267,16 @@ enum ReportMode : unsigned {
#else
enum
ReportMode
{
#endif
RM_Unspecified
,
// The mode has not been manually specified
RM_Default
,
// The mode is user-specified as default.
RM_ReportAggregatesOnly
RM_Unspecified
,
// The mode has not been manually specified
RM_Default
,
// The mode is user-specified as default.
RM_ReportAggregatesOnly
};
}
// State is passed to a running Benchmark and contains state for the
// benchmark to use.
class
State
{
public
:
public
:
// Returns true if the benchmark should continue through another iteration.
// NOTE: A benchmark may not return from the test until KeepRunning() has
// returned false.
...
...
@@ -365,27 +351,21 @@ public:
//
// REQUIRES: a benchmark has exited its KeepRunning loop.
BENCHMARK_ALWAYS_INLINE
void
SetBytesProcessed
(
size_t
bytes
)
{
bytes_processed_
=
bytes
;
}
void
SetBytesProcessed
(
size_t
bytes
)
{
bytes_processed_
=
bytes
;
}
BENCHMARK_ALWAYS_INLINE
size_t
bytes_processed
()
const
{
return
bytes_processed_
;
}
size_t
bytes_processed
()
const
{
return
bytes_processed_
;
}
// If this routine is called with complexity_n > 0 and complexity report is requested for the
// family benchmark, then current benchmark will be part of the computation and complexity_n will
// If this routine is called with complexity_n > 0 and complexity report is
// requested for the
// family benchmark, then current benchmark will be part of the computation
// and complexity_n will
// represent the length of N.
BENCHMARK_ALWAYS_INLINE
void
SetComplexityN
(
int
complexity_n
)
{
complexity_n_
=
complexity_n
;
}
void
SetComplexityN
(
int
complexity_n
)
{
complexity_n_
=
complexity_n
;
}
BENCHMARK_ALWAYS_INLINE
int
complexity_length_n
()
{
return
complexity_n_
;
}
int
complexity_length_n
()
{
return
complexity_n_
;
}
// If this routine is called with items > 0, then an items/s
// label is printed on the benchmark report line for the currently
...
...
@@ -394,14 +374,10 @@ public:
//
// REQUIRES: a benchmark has exited its KeepRunning loop.
BENCHMARK_ALWAYS_INLINE
void
SetItemsProcessed
(
size_t
items
)
{
items_processed_
=
items
;
}
void
SetItemsProcessed
(
size_t
items
)
{
items_processed_
=
items
;
}
BENCHMARK_ALWAYS_INLINE
size_t
items_processed
()
const
{
return
items_processed_
;
}
size_t
items_processed
()
const
{
return
items_processed_
;
}
// If this routine is called, the specified label is printed at the
// end of the benchmark report line for the currently executing
...
...
@@ -422,7 +398,7 @@ public:
// has the nested typename `basic_string`. This typename should be provided
// as an injected class name in the case of std::string.
template
<
class
StringType
>
void
SetLabel
(
StringType
const
&
str
,
void
SetLabel
(
StringType
const
&
str
,
typename
internal
::
EnableIfString
<
StringType
>::
type
=
1
)
{
this
->
SetLabel
(
str
.
c_str
());
}
...
...
@@ -430,8 +406,8 @@ public:
// Range arguments for this run. CHECKs if the argument has been set.
BENCHMARK_ALWAYS_INLINE
int
range
(
std
::
size_t
pos
=
0
)
const
{
assert
(
range_
.
size
()
>
pos
);
return
range_
[
pos
];
assert
(
range_
.
size
()
>
pos
);
return
range_
[
pos
];
}
BENCHMARK_DEPRECATED_MSG
(
"use 'range(0)' instead"
)
...
...
@@ -443,7 +419,7 @@ public:
BENCHMARK_ALWAYS_INLINE
size_t
iterations
()
const
{
return
total_iterations_
;
}
private
:
private
:
bool
started_
;
bool
finished_
;
size_t
total_iterations_
;
...
...
@@ -455,10 +431,11 @@ private:
int
complexity_n_
;
public
:
public
:
// FIXME: Make this private somehow.
bool
error_occurred_
;
public
:
public
:
// Index of the executing thread. Values from [0, threads).
const
int
thread_index
;
// Number of threads concurrently executing the benchmark.
...
...
@@ -489,7 +466,7 @@ typedef void(Function)(State&);
// Each method returns "this" so that multiple method calls can
// chained into one expression.
class
Benchmark
{
public
:
public
:
virtual
~
Benchmark
();
// Note: the following methods all return "this" so that multiple
...
...
@@ -508,7 +485,8 @@ public:
// REQUIRES: The function passed to the constructor must accept an arg1.
Benchmark
*
Range
(
int
start
,
int
limit
);
// Run this benchmark once for all values in the range [start..limit] with specific step
// Run this benchmark once for all values in the range [start..limit] with
// specific step
// REQUIRES: The function passed to the constructor must accept an arg1.
Benchmark
*
DenseRange
(
int
start
,
int
limit
,
int
step
=
1
);
...
...
@@ -521,10 +499,10 @@ public:
// NOTE: This is a legacy C++03 interface provided for compatibility only.
// New code should use 'Args'.
Benchmark
*
ArgPair
(
int
x
,
int
y
)
{
std
::
vector
<
int
>
args
;
args
.
push_back
(
x
);
args
.
push_back
(
y
);
return
Args
(
args
);
std
::
vector
<
int
>
args
;
args
.
push_back
(
x
);
args
.
push_back
(
y
);
return
Args
(
args
);
}
// Run this benchmark once for a number of values picked from the
...
...
@@ -536,10 +514,10 @@ public:
// NOTE: This is a legacy C++03 interface provided for compatibility only.
// New code should use 'Ranges'.
Benchmark
*
RangePair
(
int
lo1
,
int
hi1
,
int
lo2
,
int
hi2
)
{
std
::
vector
<
std
::
pair
<
int
,
int
>
>
ranges
;
ranges
.
push_back
(
std
::
make_pair
(
lo1
,
hi1
));
ranges
.
push_back
(
std
::
make_pair
(
lo2
,
hi2
));
return
Ranges
(
ranges
);
std
::
vector
<
std
::
pair
<
int
,
int
>
>
ranges
;
ranges
.
push_back
(
std
::
make_pair
(
lo1
,
hi1
));
ranges
.
push_back
(
std
::
make_pair
(
lo2
,
hi2
));
return
Ranges
(
ranges
);
}
// Pass this benchmark object to *func, which can customize
...
...
@@ -547,7 +525,8 @@ public:
// Threads, etc.
Benchmark
*
Apply
(
void
(
*
func
)(
Benchmark
*
benchmark
));
// Set the range multiplier for non-dense range. If not called, the range multiplier
// Set the range multiplier for non-dense range. If not called, the range
// multiplier
// kRangeMultiplier will be used.
Benchmark
*
RangeMultiplier
(
int
multiplier
);
...
...
@@ -573,15 +552,17 @@ public:
// called, the cpu time used by the benchmark will be used.
Benchmark
*
UseRealTime
();
// If a benchmark must measure time manually (e.g. if GPU execution time is being
// measured), call this method. If called, each benchmark iteration should call
// If a benchmark must measure time manually (e.g. if GPU execution time is
// being
// measured), call this method. If called, each benchmark iteration should
// call
// SetIterationTime(seconds) to report the measured time, which will be used
// to control how many iterations are run, and in the printing of items/second
// or MB/second values.
Benchmark
*
UseManualTime
();
// Set the asymptotic computational complexity for the benchmark. If called
// the asymptotic computational complexity will be shown on the output.
// the asymptotic computational complexity will be shown on the output.
Benchmark
*
Complexity
(
BigO
complexity
=
benchmark
::
oAuto
);
// Set the asymptotic computational complexity for the benchmark. If called
...
...
@@ -607,13 +588,13 @@ public:
// Foo in 4 threads
// Foo in 8 threads
// Foo in 16 threads
Benchmark
*
ThreadRange
(
int
min_threads
,
int
max_threads
);
Benchmark
*
ThreadRange
(
int
min_threads
,
int
max_threads
);
// For each value n in the range, run this benchmark once using n threads.
// min_threads and max_threads are always included in the range.
// stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
// a benchmark with 1, 4, 7 and 8 threads.
Benchmark
*
DenseThreadRange
(
int
min_threads
,
int
max_threads
,
int
stride
=
1
);
Benchmark
*
DenseThreadRange
(
int
min_threads
,
int
max_threads
,
int
stride
=
1
);
// Equivalent to ThreadRange(NumCPUs(), NumCPUs())
Benchmark
*
ThreadPerCpu
();
...
...
@@ -623,7 +604,7 @@ public:
// Used inside the benchmark implementation
struct
Instance
;
protected
:
protected
:
explicit
Benchmark
(
const
char
*
name
);
Benchmark
(
Benchmark
const
&
);
void
SetName
(
const
char
*
name
);
...
...
@@ -632,12 +613,12 @@ protected:
static
void
AddRange
(
std
::
vector
<
int
>*
dst
,
int
lo
,
int
hi
,
int
mult
);
private
:
private
:
friend
class
BenchmarkFamilies
;
std
::
string
name_
;
ReportMode
report_mode_
;
std
::
vector
<
std
::
vector
<
int
>
>
args_
;
// Args for all benchmark runs
std
::
vector
<
std
::
vector
<
int
>
>
args_
;
// Args for all benchmark runs
TimeUnit
time_unit_
;
int
range_multiplier_
;
double
min_time_
;
...
...
@@ -651,13 +632,14 @@ private:
Benchmark
&
operator
=
(
Benchmark
const
&
);
};
}
// namespace internal
}
// namespace internal
// Create and register a benchmark with the specified 'name' that invokes
// the specified functor 'fn'.
//
// RETURNS: A pointer to the registered benchmark.
internal
::
Benchmark
*
RegisterBenchmark
(
const
char
*
name
,
internal
::
Function
*
fn
);
internal
::
Benchmark
*
RegisterBenchmark
(
const
char
*
name
,
internal
::
Function
*
fn
);
#if defined(BENCHMARK_HAS_CXX11)
template
<
class
Lambda
>
...
...
@@ -668,30 +650,30 @@ namespace internal {
// The class used to hold all Benchmarks created from static function.
// (ie those created using the BENCHMARK(...) macros.
class
FunctionBenchmark
:
public
Benchmark
{
public
:
FunctionBenchmark
(
const
char
*
name
,
Function
*
func
)
:
Benchmark
(
name
),
func_
(
func
)
{}
virtual
void
Run
(
State
&
st
);
private
:
Function
*
func_
;
public
:
FunctionBenchmark
(
const
char
*
name
,
Function
*
func
)
:
Benchmark
(
name
),
func_
(
func
)
{}
virtual
void
Run
(
State
&
st
);
private
:
Function
*
func_
;
};
#ifdef BENCHMARK_HAS_CXX11
template
<
class
Lambda
>
class
LambdaBenchmark
:
public
Benchmark
{
public
:
virtual
void
Run
(
State
&
st
)
{
lambda_
(
st
);
}
public
:
virtual
void
Run
(
State
&
st
)
{
lambda_
(
st
);
}
private
:
private
:
template
<
class
OLambda
>
LambdaBenchmark
(
const
char
*
name
,
OLambda
&&
lam
)
:
Benchmark
(
name
),
lambda_
(
std
::
forward
<
OLambda
>
(
lam
))
{}
LambdaBenchmark
(
LambdaBenchmark
const
&
)
=
delete
;
private
:
private
:
template
<
class
Lam
>
friend
Benchmark
*
::
benchmark
::
RegisterBenchmark
(
const
char
*
,
Lam
&&
);
...
...
@@ -701,59 +683,58 @@ private:
}
// end namespace internal
inline
internal
::
Benchmark
*
RegisterBenchmark
(
const
char
*
name
,
internal
::
Function
*
fn
)
{
return
internal
::
RegisterBenchmarkInternal
(
::
new
internal
::
FunctionBenchmark
(
name
,
fn
));
inline
internal
::
Benchmark
*
RegisterBenchmark
(
const
char
*
name
,
internal
::
Function
*
fn
)
{
return
internal
::
RegisterBenchmarkInternal
(
::
new
internal
::
FunctionBenchmark
(
name
,
fn
));
}
#ifdef BENCHMARK_HAS_CXX11
template
<
class
Lambda
>
internal
::
Benchmark
*
RegisterBenchmark
(
const
char
*
name
,
Lambda
&&
fn
)
{
using
BenchType
=
internal
::
LambdaBenchmark
<
typename
std
::
decay
<
Lambda
>::
type
>
;
return
internal
::
RegisterBenchmarkInternal
(
::
new
BenchType
(
name
,
std
::
forward
<
Lambda
>
(
fn
)));
using
BenchType
=
internal
::
LambdaBenchmark
<
typename
std
::
decay
<
Lambda
>::
type
>
;
return
internal
::
RegisterBenchmarkInternal
(
::
new
BenchType
(
name
,
std
::
forward
<
Lambda
>
(
fn
)));
}
#endif
#if defined(BENCHMARK_HAS_CXX11) && \
(!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
template
<
class
Lambda
,
class
...
Args
>
(!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
template
<
class
Lambda
,
class
...
Args
>
internal
::
Benchmark
*
RegisterBenchmark
(
const
char
*
name
,
Lambda
&&
fn
,
Args
&&
...
args
)
{
return
benchmark
::
RegisterBenchmark
(
name
,
[
=
](
benchmark
::
State
&
st
)
{
fn
(
st
,
args
...);
});
return
benchmark
::
RegisterBenchmark
(
name
,
[
=
](
benchmark
::
State
&
st
)
{
fn
(
st
,
args
...);
});
}
#else
#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
#endif
// The base class for all fixture tests.
class
Fixture
:
public
internal
::
Benchmark
{
public
:
Fixture
()
:
internal
::
Benchmark
(
""
)
{}
virtual
void
Run
(
State
&
st
)
{
this
->
SetUp
(
st
);
this
->
BenchmarkCase
(
st
);
this
->
TearDown
(
st
);
}
class
Fixture
:
public
internal
::
Benchmark
{
public
:
Fixture
()
:
internal
::
Benchmark
(
""
)
{}
virtual
void
Run
(
State
&
st
)
{
this
->
SetUp
(
st
);
this
->
BenchmarkCase
(
st
);
this
->
TearDown
(
st
);
}
// These will be deprecated ...
virtual
void
SetUp
(
const
State
&
)
{}
virtual
void
TearDown
(
const
State
&
)
{}
// ... In favor of these.
virtual
void
SetUp
(
State
&
st
)
{
SetUp
(
const_cast
<
const
State
&>
(
st
));
}
virtual
void
TearDown
(
State
&
st
)
{
TearDown
(
const_cast
<
const
State
&>
(
st
));
}
// These will be deprecated ...
virtual
void
SetUp
(
const
State
&
)
{}
virtual
void
TearDown
(
const
State
&
)
{}
// ... In favor of these.
virtual
void
SetUp
(
State
&
st
)
{
SetUp
(
const_cast
<
const
State
&>
(
st
));
}
virtual
void
TearDown
(
State
&
st
)
{
TearDown
(
const_cast
<
const
State
&>
(
st
));
}
protected
:
virtual
void
BenchmarkCase
(
State
&
)
=
0
;
protected
:
virtual
void
BenchmarkCase
(
State
&
)
=
0
;
};
}
// end namespace benchmark
// ------------------------------------------------------
// Macro to register benchmarks
...
...
@@ -768,18 +749,18 @@ protected:
// Helpers for generating unique variable names
#define BENCHMARK_PRIVATE_NAME(n) \
BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, 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_PRIVATE_DECLARE(n)
\
static ::benchmark::internal::Benchmark*
BENCHMARK_PRIVATE_NAME(n)
\
BENCHMARK_UNUSED
#define BENCHMARK(n) \
BENCHMARK_PRIVATE_DECLARE(n) =
\
(::benchmark::internal::RegisterBenchmarkInternal(
\
new ::benchmark::internal::FunctionBenchmark(#n, n)))
#define BENCHMARK(n)
\
BENCHMARK_PRIVATE_DECLARE(n) =
\
(::benchmark::internal::RegisterBenchmarkInternal(
\
new ::benchmark::internal::FunctionBenchmark(#n, n)))
// Old-style macros
#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
...
...
@@ -802,14 +783,14 @@ protected:
//}
// /* Registers a benchmark named "BM_takes_args/int_string_test` */
// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
#define BENCHMARK_CAPTURE(func, test_case_name, ...)
\
BENCHMARK_PRIVATE_DECLARE(func) =
\
(::benchmark::internal::RegisterBenchmarkInternal(
\
new ::benchmark::internal::FunctionBenchmark(
\
#func "/" #test_case_name,
\
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
BENCHMARK_PRIVATE_DECLARE(func) =
\
(::benchmark::internal::RegisterBenchmarkInternal(
\
new ::benchmark::internal::FunctionBenchmark(
\
#func "/" #test_case_name,
\
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
#endif // __cplusplus >= 11
#endif
// __cplusplus >= 11
// This will register a benchmark for a templatized function. For example:
//
...
...
@@ -819,54 +800,54 @@ protected:
// BENCHMARK_TEMPLATE(BM_Foo, 1);
//
// will register BM_Foo<1> as a benchmark.
#define BENCHMARK_TEMPLATE1(n, a) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
#define BENCHMARK_TEMPLATE2(n, a, b) \
#define BENCHMARK_TEMPLATE1(n, a) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark( \
#n "<" #a "," #b ">", n<a, b>)))
new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
#define BENCHMARK_TEMPLATE2(n, a, b) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark(#n "<" #a "," #b ">", \
n<a, b>)))
#if __cplusplus >= 201103L
#define BENCHMARK_TEMPLATE(n, ...) \
BENCHMARK_PRIVATE_DECLARE(n) = \
#define BENCHMARK_TEMPLATE(n, ...)
\
BENCHMARK_PRIVATE_DECLARE(n) =
\
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark(
\
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
new ::benchmark::internal::FunctionBenchmark(
\
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
#else
#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
#endif
#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
class BaseClass##_##Method##_Benchmark : public BaseClass { \
public: \
BaseClass##_##Method##_Benchmark() : BaseClass() { \
this->SetName(#BaseClass "/" #Method);} \
protected: \
virtual void BenchmarkCase(::benchmark::State&); \
};
#define BENCHMARK_DEFINE_F(BaseClass, Method) \
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
void BaseClass##_##Method##_Benchmark::BenchmarkCase
#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
class BaseClass##_##Method##_Benchmark : public BaseClass { \
public: \
BaseClass##_##Method##_Benchmark() : BaseClass() { \
this->SetName(#BaseClass "/" #Method); \
} \
\
protected: \
virtual void BenchmarkCase(::benchmark::State&); \
};
#define BENCHMARK_DEFINE_F(BaseClass, Method) \
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
void BaseClass##_##Method##_Benchmark::BenchmarkCase
#define BENCHMARK_REGISTER_F(BaseClass, Method) \
BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark)
BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark)
#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
BENCHMARK_PRIVATE_DECLARE(TestName) =
\
(::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
BENCHMARK_PRIVATE_DECLARE(TestName) =
\
(::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
// This macro will define and register a benchmark within a fixture class.
#define BENCHMARK_F(BaseClass, Method) \
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
BENCHMARK_REGISTER_F(BaseClass, Method); \
void BaseClass##_##Method##_Benchmark::BenchmarkCase
#define BENCHMARK_F(BaseClass, Method) \
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
BENCHMARK_REGISTER_F(BaseClass, Method); \
void BaseClass##_##Method##_Benchmark::BenchmarkCase
// Helper macro to create a main routine in a test that runs the benchmarks
#define BENCHMARK_MAIN() \
...
...
include/benchmark/macros.h
View file @
332f677b
...
...
@@ -19,44 +19,44 @@
#endif
#ifndef BENCHMARK_HAS_CXX11
#
define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName)
\
TypeName(const TypeName&); \
TypeName& operator=(const TypeName&)
#
define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName)
\
TypeName(const TypeName&); \
TypeName& operator=(const TypeName&)
#else
#
define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName)
\
TypeName(const TypeName&) = delete; \
TypeName& operator=(const TypeName&) = delete
#
define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName)
\
TypeName(const TypeName&) = delete; \
TypeName& operator=(const TypeName&) = delete
#endif
#if defined(__GNUC__)
#
define BENCHMARK_UNUSED __attribute__((unused))
#
define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
#
define BENCHMARK_NOEXCEPT noexcept
#
define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
#define BENCHMARK_UNUSED __attribute__((unused))
#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
#define BENCHMARK_NOEXCEPT noexcept
#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
#elif defined(_MSC_VER) && !defined(__clang__)
# define BENCHMARK_UNUSED
# define BENCHMARK_ALWAYS_INLINE __forceinline
# if _MSC_VER >= 1900
# define BENCHMARK_NOEXCEPT noexcept
# define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
# else
# define BENCHMARK_NOEXCEPT
# define BENCHMARK_NOEXCEPT_OP(x)
# endif
# define __func__ __FUNCTION__
#define BENCHMARK_UNUSED
#define BENCHMARK_ALWAYS_INLINE __forceinline
#if _MSC_VER >= 1900
#define BENCHMARK_NOEXCEPT noexcept
#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
#else
# define BENCHMARK_UNUSED
# define BENCHMARK_ALWAYS_INLINE
# define BENCHMARK_NOEXCEPT
# define BENCHMARK_NOEXCEPT_OP(x)
#define BENCHMARK_NOEXCEPT
#define BENCHMARK_NOEXCEPT_OP(x)
#endif
#define __func__ __FUNCTION__
#else
#define BENCHMARK_UNUSED
#define BENCHMARK_ALWAYS_INLINE
#define BENCHMARK_NOEXCEPT
#define BENCHMARK_NOEXCEPT_OP(x)
#endif
#if defined(__GNUC__)
#
define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
#
define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
#else
#
define BENCHMARK_BUILTIN_EXPECT(x, y) x
#
define BENCHMARK_DEPRECATED_MSG(msg)
#define BENCHMARK_BUILTIN_EXPECT(x, y) x
#define BENCHMARK_DEPRECATED_MSG(msg)
#endif
#if defined(__GNUC__) && !defined(__clang__)
...
...
include/benchmark/reporter.h
View file @
332f677b
...
...
@@ -41,20 +41,20 @@ class BenchmarkReporter {
};
struct
Run
{
Run
()
:
error_occurred
(
false
),
iterations
(
1
),
time_unit
(
kNanosecond
),
real_accumulated_time
(
0
),
cpu_accumulated_time
(
0
),
bytes_per_second
(
0
),
items_per_second
(
0
),
max_heapbytes_used
(
0
),
complexity
(
oNone
),
complexity_lambda
(),
complexity_n
(
0
),
report_big_o
(
false
),
report_rms
(
false
)
{}
Run
()
:
error_occurred
(
false
),
iterations
(
1
),
time_unit
(
kNanosecond
),
real_accumulated_time
(
0
),
cpu_accumulated_time
(
0
),
bytes_per_second
(
0
),
items_per_second
(
0
),
max_heapbytes_used
(
0
),
complexity
(
oNone
),
complexity_lambda
(),
complexity_n
(
0
),
report_big_o
(
false
),
report_rms
(
false
)
{}
std
::
string
benchmark_name
;
std
::
string
report_label
;
// Empty if not set by benchmark.
...
...
@@ -134,13 +134,9 @@ class BenchmarkReporter {
error_stream_
=
err
;
}
std
::
ostream
&
GetOutputStream
()
const
{
return
*
output_stream_
;
}
std
::
ostream
&
GetOutputStream
()
const
{
return
*
output_stream_
;
}
std
::
ostream
&
GetErrorStream
()
const
{
return
*
error_stream_
;
}
std
::
ostream
&
GetErrorStream
()
const
{
return
*
error_stream_
;
}
virtual
~
BenchmarkReporter
();
...
...
@@ -157,22 +153,19 @@ class BenchmarkReporter {
// Simple reporter that outputs benchmark data to the console. This is the
// default reporter used by RunSpecifiedBenchmarks().
class
ConsoleReporter
:
public
BenchmarkReporter
{
public
:
enum
OutputOptions
{
OO_None
,
OO_Color
};
public
:
enum
OutputOptions
{
OO_None
,
OO_Color
};
explicit
ConsoleReporter
(
OutputOptions
color_output
=
OO_Color
)
:
name_field_width_
(
0
),
color_output_
(
color_output
==
OO_Color
)
{}
virtual
bool
ReportContext
(
const
Context
&
context
);
virtual
void
ReportRuns
(
const
std
::
vector
<
Run
>&
reports
);
protected
:
protected
:
virtual
void
PrintRunData
(
const
Run
&
report
);
size_t
name_field_width_
;
private
:
private
:
bool
color_output_
;
};
...
...
src/arraysize.h
View file @
332f677b
...
...
@@ -11,7 +11,6 @@ namespace internal {
// a pointer by mistake, you will get a compile-time error.
//
// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
...
...
@@ -28,7 +27,7 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
#define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array)))
}
// end namespace internal
}
// end namespace benchmark
}
// end namespace internal
}
// end namespace benchmark
#endif // BENCHMARK_ARRAYSIZE_H_
#endif
// BENCHMARK_ARRAYSIZE_H_
src/benchmark.cc
View file @
332f677b
...
...
@@ -13,23 +13,23 @@
// limitations under the License.
#include "benchmark/benchmark.h"
#include "internal_macros.h"
#include "benchmark_api_internal.h"
#include "internal_macros.h"
#ifndef BENCHMARK_OS_WINDOWS
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
#endif
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <thread>
...
...
@@ -92,7 +92,6 @@ DEFINE_string(benchmark_color, "auto",
DEFINE_int32
(
v
,
0
,
"The level of verbose logging to output"
);
namespace
benchmark
{
namespace
internal
{
...
...
@@ -108,7 +107,6 @@ static const size_t kMaxIterations = 1000000000;
namespace
internal
{
class
ThreadManager
{
public
:
ThreadManager
(
int
num_threads
)
...
...
@@ -202,25 +200,23 @@ class ThreadTimer {
}
private
:
bool
running_
=
false
;
// Is the timer running
double
start_real_time_
=
0
;
// If running_
double
start_cpu_time_
=
0
;
// If running_
bool
running_
=
false
;
// Is the timer running
double
start_real_time_
=
0
;
// If running_
double
start_cpu_time_
=
0
;
// If running_
// Accumulated time so far (does not contain current slice if running_)
double
real_time_used_
=
0
;
double
cpu_time_used_
=
0
;
// Manually set iteration time. User sets this with SetIterationTime(seconds).
double
manual_time_used_
=
0
;
};
namespace
{
BenchmarkReporter
::
Run
CreateRunReport
(
const
benchmark
::
internal
::
Benchmark
::
Instance
&
b
,
const
internal
::
ThreadManager
::
Result
&
results
,
size_t
iters
,
double
seconds
)
{
BenchmarkReporter
::
Run
CreateRunReport
(
const
benchmark
::
internal
::
Benchmark
::
Instance
&
b
,
const
internal
::
ThreadManager
::
Result
&
results
,
size_t
iters
,
double
seconds
)
{
// Create report about this benchmark run.
BenchmarkReporter
::
Run
report
;
...
...
@@ -265,8 +261,8 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b,
internal
::
ThreadTimer
timer
;
State
st
(
iters
,
b
->
arg
,
thread_id
,
b
->
threads
,
&
timer
,
manager
);
b
->
benchmark
->
Run
(
st
);
CHECK
(
st
.
iterations
()
==
st
.
max_iterations
)
<<
"Benchmark returned before State::KeepRunning() returned false!"
;
CHECK
(
st
.
iterations
()
==
st
.
max_iterations
)
<<
"Benchmark returned before State::KeepRunning() returned false!"
;
{
MutexLock
l
(
manager
->
GetBenchmarkMutex
());
internal
::
ThreadManager
::
Result
&
results
=
manager
->
results
;
...
...
@@ -283,17 +279,18 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b,
std
::
vector
<
BenchmarkReporter
::
Run
>
RunBenchmark
(
const
benchmark
::
internal
::
Benchmark
::
Instance
&
b
,
std
::
vector
<
BenchmarkReporter
::
Run
>*
complexity_reports
)
{
std
::
vector
<
BenchmarkReporter
::
Run
>
reports
;
// return value
std
::
vector
<
BenchmarkReporter
::
Run
>
reports
;
// return value
size_t
iters
=
1
;
std
::
unique_ptr
<
internal
::
ThreadManager
>
manager
;
std
::
vector
<
std
::
thread
>
pool
(
b
.
threads
-
1
);
const
int
repeats
=
b
.
repetitions
!=
0
?
b
.
repetitions
:
FLAGS_benchmark_repetitions
;
const
bool
report_aggregates_only
=
repeats
!=
1
&&
const
int
repeats
=
b
.
repetitions
!=
0
?
b
.
repetitions
:
FLAGS_benchmark_repetitions
;
const
bool
report_aggregates_only
=
repeats
!=
1
&&
(
b
.
report_mode
==
internal
::
RM_Unspecified
?
FLAGS_benchmark_report_aggregates_only
:
b
.
report_mode
==
internal
::
RM_ReportAggregatesOnly
);
?
FLAGS_benchmark_report_aggregates_only
:
b
.
report_mode
==
internal
::
RM_ReportAggregatesOnly
);
for
(
int
i
=
0
;
i
<
repeats
;
i
++
)
{
for
(;;)
{
// Try benchmark
...
...
@@ -306,8 +303,7 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
}
RunInThread
(
&
b
,
iters
,
0
,
manager
.
get
());
manager
->
WaitForAllThreads
();
for
(
std
::
thread
&
thread
:
pool
)
thread
.
join
();
for
(
std
::
thread
&
thread
:
pool
)
thread
.
join
();
internal
::
ThreadManager
::
Result
results
;
{
MutexLock
l
(
manager
->
GetBenchmarkMutex
());
...
...
@@ -319,23 +315,24 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
results
.
manual_time_used
/=
b
.
threads
;
VLOG
(
2
)
<<
"Ran in "
<<
results
.
cpu_time_used
<<
"/"
<<
results
.
real_time_used
<<
"
\n
"
;
<<
results
.
real_time_used
<<
"
\n
"
;
// Base decisions off of real time if requested by this benchmark.
double
seconds
=
results
.
cpu_time_used
;
if
(
b
.
use_manual_time
)
{
seconds
=
results
.
manual_time_used
;
seconds
=
results
.
manual_time_used
;
}
else
if
(
b
.
use_real_time
)
{
seconds
=
results
.
real_time_used
;
seconds
=
results
.
real_time_used
;
}
const
double
min_time
=
!
IsZero
(
b
.
min_time
)
?
b
.
min_time
:
FLAGS_benchmark_min_time
;
const
double
min_time
=
!
IsZero
(
b
.
min_time
)
?
b
.
min_time
:
FLAGS_benchmark_min_time
;
// If this was the first run, was elapsed time or cpu time large enough?
// If this is not the first run, go with the current value of iter.
if
((
i
>
0
)
||
results
.
has_error_
||
(
iters
>=
kMaxIterations
)
||
(
seconds
>=
min_time
)
||
(
results
.
real_time_used
>=
5
*
min_time
))
{
BenchmarkReporter
::
Run
report
=
CreateRunReport
(
b
,
results
,
iters
,
seconds
);
BenchmarkReporter
::
Run
report
=
CreateRunReport
(
b
,
results
,
iters
,
seconds
);
if
(
!
report
.
error_occurred
&&
b
.
complexity
!=
oNone
)
complexity_reports
->
push_back
(
report
);
reports
.
push_back
(
report
);
...
...
@@ -363,10 +360,10 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
}
// Calculate additional statistics
auto
stat_reports
=
ComputeStats
(
reports
);
if
((
b
.
complexity
!=
oNone
)
&&
b
.
last_benchmark_instance
)
{
if
((
b
.
complexity
!=
oNone
)
&&
b
.
last_benchmark_instance
)
{
auto
additional_run_stats
=
ComputeBigO
(
*
complexity_reports
);
stat_reports
.
insert
(
stat_reports
.
end
(),
additional_run_stats
.
begin
(),
additional_run_stats
.
end
());
additional_run_stats
.
end
());
complexity_reports
->
clear
();
}
...
...
@@ -375,8 +372,8 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
return
reports
;
}
}
// namespace
}
// namespace internal
}
// namespace
}
// namespace internal
State
::
State
(
size_t
max_iters
,
const
std
::
vector
<
int
>&
ranges
,
int
thread_i
,
int
n_threads
,
internal
::
ThreadTimer
*
timer
,
...
...
@@ -423,8 +420,7 @@ void State::SkipWithError(const char* msg) {
if
(
timer_
->
running
())
timer_
->
StopTimer
();
}
void
State
::
SetIterationTime
(
double
seconds
)
{
void
State
::
SetIterationTime
(
double
seconds
)
{
timer_
->
SetIterationTime
(
seconds
);
}
...
...
@@ -468,8 +464,7 @@ void RunMatchingBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
std
::
max
<
size_t
>
(
name_field_width
,
benchmark
.
name
.
size
());
has_repetitions
|=
benchmark
.
repetitions
>
1
;
}
if
(
has_repetitions
)
name_field_width
+=
std
::
strlen
(
"_stddev"
);
if
(
has_repetitions
)
name_field_width
+=
std
::
strlen
(
"_stddev"
);
// Print header here
BenchmarkReporter
::
Context
context
;
...
...
@@ -490,8 +485,8 @@ void RunMatchingBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
std
::
flush
(
reporter
->
GetErrorStream
());
};
if
(
console_reporter
->
ReportContext
(
context
)
&&
(
!
file_reporter
||
file_reporter
->
ReportContext
(
context
)))
{
if
(
console_reporter
->
ReportContext
(
context
)
&&
(
!
file_reporter
||
file_reporter
->
ReportContext
(
context
)))
{
flushStreams
(
console_reporter
);
flushStreams
(
file_reporter
);
for
(
const
auto
&
benchmark
:
benchmarks
)
{
...
...
@@ -509,8 +504,8 @@ void RunMatchingBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
flushStreams
(
file_reporter
);
}
std
::
unique_ptr
<
BenchmarkReporter
>
CreateReporter
(
std
::
string
const
&
name
,
ConsoleReporter
::
OutputOptions
allow_color
)
{
std
::
unique_ptr
<
BenchmarkReporter
>
CreateReporter
(
std
::
string
const
&
name
,
ConsoleReporter
::
OutputOptions
allow_color
)
{
typedef
std
::
unique_ptr
<
BenchmarkReporter
>
PtrType
;
if
(
name
==
"console"
)
{
return
PtrType
(
new
ConsoleReporter
(
allow_color
));
...
...
@@ -524,19 +519,17 @@ CreateReporter(std::string const& name, ConsoleReporter::OutputOptions allow_col
}
}
}
// end namespace
}
// end namespace internal
}
// end namespace
}
// end namespace internal
size_t
RunSpecifiedBenchmarks
()
{
return
RunSpecifiedBenchmarks
(
nullptr
,
nullptr
);
}
size_t
RunSpecifiedBenchmarks
(
BenchmarkReporter
*
console_reporter
)
{
return
RunSpecifiedBenchmarks
(
console_reporter
,
nullptr
);
}
size_t
RunSpecifiedBenchmarks
(
BenchmarkReporter
*
console_reporter
,
BenchmarkReporter
*
file_reporter
)
{
std
::
string
spec
=
FLAGS_benchmark_filter
;
...
...
@@ -556,8 +549,8 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
output_opts
=
IsTruthyFlagValue
(
FLAGS_benchmark_color
)
?
ConsoleReporter
::
OO_Color
:
ConsoleReporter
::
OO_None
;
default_console_reporter
=
internal
::
CreateReporter
(
FLAGS_benchmark_format
,
output_opts
);
default_console_reporter
=
internal
::
CreateReporter
(
FLAGS_benchmark_format
,
output_opts
);
console_reporter
=
default_console_reporter
.
get
();
}
auto
&
Out
=
console_reporter
->
GetOutputStream
();
...
...
@@ -566,7 +559,8 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
std
::
string
const
&
fname
=
FLAGS_benchmark_out
;
if
(
fname
==
""
&&
file_reporter
)
{
Err
<<
"A custom file reporter was provided but "
"--benchmark_out=<file> was not specified."
<<
std
::
endl
;
"--benchmark_out=<file> was not specified."
<<
std
::
endl
;
std
::
exit
(
1
);
}
if
(
fname
!=
""
)
{
...
...
@@ -577,7 +571,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
}
if
(
!
file_reporter
)
{
default_file_reporter
=
internal
::
CreateReporter
(
FLAGS_benchmark_out_format
,
ConsoleReporter
::
OO_None
);
FLAGS_benchmark_out_format
,
ConsoleReporter
::
OO_None
);
file_reporter
=
default_file_reporter
.
get
();
}
file_reporter
->
SetOutputStream
(
&
output_file
);
...
...
@@ -588,10 +582,10 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
if
(
!
FindBenchmarksInternal
(
spec
,
&
benchmarks
,
&
Err
))
return
0
;
if
(
FLAGS_benchmark_list_tests
)
{
for
(
auto
const
&
benchmark
:
benchmarks
)
Out
<<
benchmark
.
name
<<
"
\n
"
;
for
(
auto
const
&
benchmark
:
benchmarks
)
Out
<<
benchmark
.
name
<<
"
\n
"
;
}
else
{
internal
::
RunMatchingBenchmarks
(
benchmarks
,
console_reporter
,
file_reporter
);
internal
::
RunMatchingBenchmarks
(
benchmarks
,
console_reporter
,
file_reporter
);
}
return
benchmarks
.
size
();
...
...
@@ -618,29 +612,23 @@ void PrintUsageAndExit() {
void
ParseCommandLineFlags
(
int
*
argc
,
char
**
argv
)
{
using
namespace
benchmark
;
for
(
int
i
=
1
;
i
<
*
argc
;
++
i
)
{
if
(
ParseBoolFlag
(
argv
[
i
],
"benchmark_list_tests"
,
if
(
ParseBoolFlag
(
argv
[
i
],
"benchmark_list_tests"
,
&
FLAGS_benchmark_list_tests
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_filter"
,
&
FLAGS_benchmark_filter
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_filter"
,
&
FLAGS_benchmark_filter
)
||
ParseDoubleFlag
(
argv
[
i
],
"benchmark_min_time"
,
&
FLAGS_benchmark_min_time
)
||
ParseInt32Flag
(
argv
[
i
],
"benchmark_repetitions"
,
&
FLAGS_benchmark_repetitions
)
||
ParseBoolFlag
(
argv
[
i
],
"benchmark_report_aggregates_only"
,
&
FLAGS_benchmark_report_aggregates_only
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_format"
,
&
FLAGS_benchmark_format
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_out"
,
&
FLAGS_benchmark_out
)
||
&
FLAGS_benchmark_report_aggregates_only
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_format"
,
&
FLAGS_benchmark_format
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_out"
,
&
FLAGS_benchmark_out
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_out_format"
,
&
FLAGS_benchmark_out_format
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_color"
,
&
FLAGS_benchmark_color
)
||
ParseStringFlag
(
argv
[
i
],
"benchmark_color"
,
&
FLAGS_benchmark_color
)
||
// "color_print" is the deprecated name for "benchmark_color".
// TODO: Remove this.
ParseStringFlag
(
argv
[
i
],
"color_print"
,
&
FLAGS_benchmark_color
)
||
ParseStringFlag
(
argv
[
i
],
"color_print"
,
&
FLAGS_benchmark_color
)
||
ParseInt32Flag
(
argv
[
i
],
"v"
,
&
FLAGS_v
))
{
for
(
int
j
=
i
;
j
!=
*
argc
;
++
j
)
argv
[
j
]
=
argv
[
j
+
1
];
...
...
@@ -650,26 +638,26 @@ void ParseCommandLineFlags(int* argc, char** argv) {
PrintUsageAndExit
();
}
}
for
(
auto
const
*
flag
:
{
&
FLAGS_benchmark_format
,
&
FLAGS_benchmark_out_format
})
if
(
*
flag
!=
"console"
&&
*
flag
!=
"json"
&&
*
flag
!=
"csv"
)
{
PrintUsageAndExit
();
}
for
(
auto
const
*
flag
:
{
&
FLAGS_benchmark_format
,
&
FLAGS_benchmark_out_format
})
if
(
*
flag
!=
"console"
&&
*
flag
!=
"json"
&&
*
flag
!=
"csv"
)
{
PrintUsageAndExit
();
}
if
(
FLAGS_benchmark_color
.
empty
())
{
PrintUsageAndExit
();
}
}
int
InitializeStreams
()
{
static
std
::
ios_base
::
Init
init
;
return
0
;
static
std
::
ios_base
::
Init
init
;
return
0
;
}
}
// end namespace internal
}
// end namespace internal
void
Initialize
(
int
*
argc
,
char
**
argv
)
{
internal
::
ParseCommandLineFlags
(
argc
,
argv
);
internal
::
LogLevel
()
=
FLAGS_v
;
}
}
// end namespace benchmark
}
// end namespace benchmark
src/benchmark_api_internal.h
View file @
332f677b
...
...
@@ -3,44 +3,45 @@
#include "benchmark/benchmark_api.h"
#include <string>
#include <vector>
#include <limits>
#include <cmath>
#include <iosfwd>
#include <limits>
#include <string>
#include <vector>
namespace
benchmark
{
namespace
internal
{
// Information kept per benchmark we may want to run
struct
Benchmark
::
Instance
{
std
::
string
name
;
Benchmark
*
benchmark
;
ReportMode
report_mode
;
std
::
string
name
;
Benchmark
*
benchmark
;
ReportMode
report_mode
;
std
::
vector
<
int
>
arg
;
TimeUnit
time_unit
;
int
range_multiplier
;
bool
use_real_time
;
bool
use_manual_time
;
BigO
complexity
;
BigOFunc
*
complexity_lambda
;
bool
last_benchmark_instance
;
int
repetitions
;
double
min_time
;
int
threads
;
// Number of concurrent threads to us
TimeUnit
time_unit
;
int
range_multiplier
;
bool
use_real_time
;
bool
use_manual_time
;
BigO
complexity
;
BigOFunc
*
complexity_lambda
;
bool
last_benchmark_instance
;
int
repetitions
;
double
min_time
;
int
threads
;
// Number of concurrent threads to us
};
bool
FindBenchmarksInternal
(
const
std
::
string
&
re
,
std
::
vector
<
Benchmark
::
Instance
>*
benchmarks
,
std
::
ostream
*
Err
);
std
::
vector
<
Benchmark
::
Instance
>*
benchmarks
,
std
::
ostream
*
Err
);
namespace
{
bool
IsZero
(
double
n
)
{
return
std
::
abs
(
n
)
<
std
::
numeric_limits
<
double
>::
epsilon
();
return
std
::
abs
(
n
)
<
std
::
numeric_limits
<
double
>::
epsilon
();
}
}
// end namespace
}
// end namespace internal
}
// end namespace benchmark
}
// end namespace
}
// end namespace internal
}
// end namespace benchmark
#endif // BENCHMARK_API_INTERNAL_H
#endif
// BENCHMARK_API_INTERNAL_H
src/benchmark_register.cc
View file @
332f677b
...
...
@@ -13,23 +13,23 @@
// limitations under the License.
#include "benchmark/benchmark.h"
#include "internal_macros.h"
#include "benchmark_api_internal.h"
#include "internal_macros.h"
#ifndef BENCHMARK_OS_WINDOWS
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
#endif
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <thread>
...
...
@@ -74,6 +74,7 @@ class BenchmarkFamilies {
bool
FindBenchmarks
(
const
std
::
string
&
re
,
std
::
vector
<
Benchmark
::
Instance
>*
benchmarks
,
std
::
ostream
*
Err
);
private
:
BenchmarkFamilies
()
{}
...
...
@@ -94,8 +95,7 @@ size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr<Benchmark> family) {
}
bool
BenchmarkFamilies
::
FindBenchmarks
(
const
std
::
string
&
spec
,
std
::
vector
<
Benchmark
::
Instance
>*
benchmarks
,
const
std
::
string
&
spec
,
std
::
vector
<
Benchmark
::
Instance
>*
benchmarks
,
std
::
ostream
*
ErrStream
)
{
CHECK
(
ErrStream
);
auto
&
Err
=
*
ErrStream
;
...
...
@@ -120,23 +120,21 @@ bool BenchmarkFamilies::FindBenchmarks(
}
const
std
::
vector
<
int
>*
thread_counts
=
(
family
->
thread_counts_
.
empty
()
?
&
one_thread
:
&
static_cast
<
const
std
::
vector
<
int
>&>
(
family
->
thread_counts_
));
?
&
one_thread
:
&
static_cast
<
const
std
::
vector
<
int
>&>
(
family
->
thread_counts_
));
const
size_t
family_size
=
family
->
args_
.
size
()
*
thread_counts
->
size
();
// The benchmark will be run at least 'family_size' different inputs.
// If 'family_size' is very large warn the user.
if
(
family_size
>
kMaxFamilySize
)
{
Err
<<
"The number of inputs is very large. "
<<
family
->
name_
Err
<<
"The number of inputs is very large. "
<<
family
->
name_
<<
" will be repeated at least "
<<
family_size
<<
" times.
\n
"
;
}
// reserve in the special case the regex ".", since we know the final
// family size.
if
(
spec
==
"."
)
benchmarks
->
reserve
(
family_size
);
if
(
spec
==
"."
)
benchmarks
->
reserve
(
family_size
);
for
(
auto
const
&
args
:
family
->
args_
)
{
for
(
int
num_threads
:
*
thread_counts
)
{
Benchmark
::
Instance
instance
;
instance
.
name
=
family
->
name_
;
instance
.
benchmark
=
family
.
get
();
...
...
@@ -158,15 +156,15 @@ bool BenchmarkFamilies::FindBenchmarks(
}
if
(
!
IsZero
(
family
->
min_time_
))
{
instance
.
name
+=
StringPrintF
(
"/min_time:%0.3f"
,
family
->
min_time_
);
instance
.
name
+=
StringPrintF
(
"/min_time:%0.3f"
,
family
->
min_time_
);
}
if
(
family
->
repetitions_
!=
0
)
{
instance
.
name
+=
StringPrintF
(
"/repeats:%d"
,
family
->
repetitions_
);
instance
.
name
+=
StringPrintF
(
"/repeats:%d"
,
family
->
repetitions_
);
}
if
(
family
->
use_manual_time_
)
{
instance
.
name
+=
"/manual_time"
;
instance
.
name
+=
"/manual_time"
;
}
else
if
(
family
->
use_real_time_
)
{
instance
.
name
+=
"/real_time"
;
instance
.
name
+=
"/real_time"
;
}
// Add the number of threads used to the name
...
...
@@ -185,37 +183,37 @@ bool BenchmarkFamilies::FindBenchmarks(
}
Benchmark
*
RegisterBenchmarkInternal
(
Benchmark
*
bench
)
{
std
::
unique_ptr
<
Benchmark
>
bench_ptr
(
bench
);
BenchmarkFamilies
*
families
=
BenchmarkFamilies
::
GetInstance
();
families
->
AddBenchmark
(
std
::
move
(
bench_ptr
));
return
bench
;
std
::
unique_ptr
<
Benchmark
>
bench_ptr
(
bench
);
BenchmarkFamilies
*
families
=
BenchmarkFamilies
::
GetInstance
();
families
->
AddBenchmark
(
std
::
move
(
bench_ptr
));
return
bench
;
}
// FIXME: This function is a hack so that benchmark.cc can access
// `BenchmarkFamilies`
bool
FindBenchmarksInternal
(
const
std
::
string
&
re
,
std
::
vector
<
Benchmark
::
Instance
>*
benchmarks
,
std
::
ostream
*
Err
)
{
std
::
ostream
*
Err
)
{
return
BenchmarkFamilies
::
GetInstance
()
->
FindBenchmarks
(
re
,
benchmarks
,
Err
);
}
//=============================================================================//
// Benchmark
//=============================================================================//
Benchmark
::
Benchmark
(
const
char
*
name
)
:
name_
(
name
),
report_mode_
(
RM_Unspecified
),
time_unit_
(
kNanosecond
),
range_multiplier_
(
kRangeMultiplier
),
min_time_
(
0
),
repetitions_
(
0
),
use_real_time_
(
false
),
use_manual_time_
(
false
),
complexity_
(
oNone
),
complexity_lambda_
(
nullptr
)
{
}
Benchmark
::~
Benchmark
()
{
}
:
name_
(
name
),
report_mode_
(
RM_Unspecified
),
time_unit_
(
kNanosecond
),
range_multiplier_
(
kRangeMultiplier
),
min_time_
(
0
),
repetitions_
(
0
),
use_real_time_
(
false
),
use_manual_time_
(
false
),
complexity_
(
oNone
),
complexity_lambda_
(
nullptr
)
{}
Benchmark
::~
Benchmark
()
{}
void
Benchmark
::
AddRange
(
std
::
vector
<
int
>*
dst
,
int
lo
,
int
hi
,
int
mult
)
{
CHECK_GE
(
lo
,
0
);
...
...
@@ -228,7 +226,7 @@ void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
static
const
int
kint32max
=
std
::
numeric_limits
<
int32_t
>::
max
();
// Now space out the benchmarks in multiples of "mult"
for
(
int32_t
i
=
1
;
i
<
kint32max
/
mult
;
i
*=
mult
)
{
for
(
int32_t
i
=
1
;
i
<
kint32max
/
mult
;
i
*=
mult
)
{
if
(
i
>=
hi
)
break
;
if
(
i
>
lo
)
{
dst
->
push_back
(
i
);
...
...
@@ -262,13 +260,13 @@ Benchmark* Benchmark::Range(int start, int limit) {
return
this
;
}
Benchmark
*
Benchmark
::
Ranges
(
const
std
::
vector
<
std
::
pair
<
int
,
int
>>&
ranges
)
{
Benchmark
*
Benchmark
::
Ranges
(
const
std
::
vector
<
std
::
pair
<
int
,
int
>>&
ranges
)
{
CHECK
(
ArgsCnt
()
==
-
1
||
ArgsCnt
()
==
static_cast
<
int
>
(
ranges
.
size
()));
std
::
vector
<
std
::
vector
<
int
>>
arglists
(
ranges
.
size
());
std
::
size_t
total
=
1
;
for
(
std
::
size_t
i
=
0
;
i
<
ranges
.
size
();
i
++
)
{
AddRange
(
&
arglists
[
i
],
ranges
[
i
].
first
,
ranges
[
i
].
second
,
range_multiplier_
);
AddRange
(
&
arglists
[
i
],
ranges
[
i
].
first
,
ranges
[
i
].
second
,
range_multiplier_
);
total
*=
arglists
[
i
].
size
();
}
...
...
@@ -299,7 +297,7 @@ Benchmark* Benchmark::DenseRange(int start, int limit, int step) {
CHECK
(
ArgsCnt
()
==
-
1
||
ArgsCnt
()
==
1
);
CHECK_GE
(
start
,
0
);
CHECK_LE
(
start
,
limit
);
for
(
int
arg
=
start
;
arg
<=
limit
;
arg
+=
step
)
{
for
(
int
arg
=
start
;
arg
<=
limit
;
arg
+=
step
)
{
args_
.
push_back
({
arg
});
}
return
this
;
...
...
@@ -340,13 +338,15 @@ Benchmark* Benchmark::MinTime(double t) {
}
Benchmark
*
Benchmark
::
UseRealTime
()
{
CHECK
(
!
use_manual_time_
)
<<
"Cannot set UseRealTime and UseManualTime simultaneously."
;
CHECK
(
!
use_manual_time_
)
<<
"Cannot set UseRealTime and UseManualTime simultaneously."
;
use_real_time_
=
true
;
return
this
;
}
Benchmark
*
Benchmark
::
UseManualTime
()
{
CHECK
(
!
use_real_time_
)
<<
"Cannot set UseRealTime and UseManualTime simultaneously."
;
CHECK
(
!
use_real_time_
)
<<
"Cannot set UseRealTime and UseManualTime simultaneously."
;
use_manual_time_
=
true
;
return
this
;
}
...
...
@@ -376,7 +376,7 @@ Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
return
this
;
}
Benchmark
*
Benchmark
::
DenseThreadRange
(
int
min_threads
,
int
max_threads
,
Benchmark
*
Benchmark
::
DenseThreadRange
(
int
min_threads
,
int
max_threads
,
int
stride
)
{
CHECK_GT
(
min_threads
,
0
);
CHECK_GE
(
max_threads
,
min_threads
);
...
...
@@ -395,21 +395,17 @@ Benchmark* Benchmark::ThreadPerCpu() {
return
this
;
}
void
Benchmark
::
SetName
(
const
char
*
name
)
{
name_
=
name
;
}
int
Benchmark
::
ArgsCnt
()
const
{
return
args_
.
empty
()
?
-
1
:
static_cast
<
int
>
(
args_
.
front
().
size
());
}
void
Benchmark
::
SetName
(
const
char
*
name
)
{
name_
=
name
;
}
int
Benchmark
::
ArgsCnt
()
const
{
return
args_
.
empty
()
?
-
1
:
static_cast
<
int
>
(
args_
.
front
().
size
());
}
//=============================================================================//
// FunctionBenchmark
//=============================================================================//
void
FunctionBenchmark
::
Run
(
State
&
st
)
{
func_
(
st
);
}
void
FunctionBenchmark
::
Run
(
State
&
st
)
{
func_
(
st
);
}
}
// end namespace internal
}
// end namespace benchmark
}
// end namespace internal
}
// end namespace benchmark
src/check.h
View file @
332f677b
...
...
@@ -13,51 +13,52 @@ namespace internal {
typedef
void
(
AbortHandlerT
)();
inline
AbortHandlerT
*&
GetAbortHandler
()
{
static
AbortHandlerT
*
handler
=
&
std
::
abort
;
return
handler
;
static
AbortHandlerT
*
handler
=
&
std
::
abort
;
return
handler
;
}
BENCHMARK_NORETURN
inline
void
CallAbortHandler
()
{
GetAbortHandler
()();
std
::
abort
();
// fallback to enforce noreturn
GetAbortHandler
()();
std
::
abort
();
// fallback to enforce noreturn
}
// CheckHandler is the class constructed by failing CHECK macros. CheckHandler
// will log information about the failures and abort when it is destructed.
class
CheckHandler
{
public
:
public
:
CheckHandler
(
const
char
*
check
,
const
char
*
file
,
const
char
*
func
,
int
line
)
:
log_
(
GetErrorLogInstance
())
{
log_
<<
file
<<
":"
<<
line
<<
": "
<<
func
<<
": Check `"
<<
check
<<
"' failed. "
;
:
log_
(
GetErrorLogInstance
())
{
log_
<<
file
<<
":"
<<
line
<<
": "
<<
func
<<
": Check `"
<<
check
<<
"' failed. "
;
}
LogType
&
GetLog
()
{
return
log_
;
}
BENCHMARK_NORETURN
~
CheckHandler
()
BENCHMARK_NOEXCEPT_OP
(
false
)
{
log_
<<
std
::
endl
;
CallAbortHandler
();
log_
<<
std
::
endl
;
CallAbortHandler
();
}
CheckHandler
&
operator
=
(
const
CheckHandler
&
)
=
delete
;
CheckHandler
&
operator
=
(
const
CheckHandler
&
)
=
delete
;
CheckHandler
(
const
CheckHandler
&
)
=
delete
;
CheckHandler
()
=
delete
;
private
:
LogType
&
log_
;
private
:
LogType
&
log_
;
};
}
// end namespace internal
}
// end namespace benchmark
}
// end namespace internal
}
// end namespace benchmark
// The CHECK macro returns a std::ostream object that can have extra information
// written to it.
#ifndef NDEBUG
# define CHECK(b) (b ? ::benchmark::internal::GetNullLogInstance() \
: ::benchmark::internal::CheckHandler( \
#b, __FILE__, __func__, __LINE__).GetLog())
#define CHECK(b) \
(b ? ::benchmark::internal::GetNullLogInstance() \
: ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
.GetLog())
#else
#
define CHECK(b) ::benchmark::internal::GetNullLogInstance()
#define CHECK(b) ::benchmark::internal::GetNullLogInstance()
#endif
#define CHECK_EQ(a, b) CHECK((a) == (b))
...
...
src/colorprint.cc
View file @
332f677b
...
...
@@ -25,11 +25,11 @@
#include "internal_macros.h"
#ifdef BENCHMARK_OS_WINDOWS
#include <io.h>
#include <Windows.h>
#include <io.h>
#else
#include <unistd.h>
#endif // BENCHMARK_OS_WINDOWS
#endif
// BENCHMARK_OS_WINDOWS
namespace
benchmark
{
namespace
{
...
...
@@ -82,7 +82,7 @@ PlatformColorCode GetPlatformColorCode(LogColor color) {
}
// end namespace
std
::
string
FormatString
(
const
char
*
msg
,
va_list
args
)
{
std
::
string
FormatString
(
const
char
*
msg
,
va_list
args
)
{
// we might need a second shot at this, so pre-emptivly make a copy
va_list
args_cp
;
va_copy
(
args_cp
,
args
);
...
...
@@ -96,13 +96,13 @@ std::string FormatString(const char *msg, va_list args) {
// currently there is no error handling for failure, so this is hack.
CHECK
(
ret
>=
0
);
if
(
ret
==
0
)
// handle empty expansion
if
(
ret
==
0
)
// handle empty expansion
return
{};
else
if
(
static_cast
<
size_t
>
(
ret
)
<
size
)
return
local_buff
;
else
{
// we did not provide a long enough buffer on our first attempt.
size
=
(
size_t
)
ret
+
1
;
// + 1 for the null byte
size
=
(
size_t
)
ret
+
1
;
// + 1 for the null byte
std
::
unique_ptr
<
char
[]
>
buff
(
new
char
[
size
]);
ret
=
std
::
vsnprintf
(
buff
.
get
(),
size
,
msg
,
args
);
CHECK
(
ret
>
0
&&
((
size_t
)
ret
)
<
size
);
...
...
@@ -110,7 +110,7 @@ std::string FormatString(const char *msg, va_list args) {
}
}
std
::
string
FormatString
(
const
char
*
msg
,
...)
{
std
::
string
FormatString
(
const
char
*
msg
,
...)
{
va_list
args
;
va_start
(
args
,
msg
);
auto
tmp
=
FormatString
(
msg
,
args
);
...
...
@@ -125,9 +125,10 @@ void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) {
va_end
(
args
);
}
void
ColorPrintf
(
std
::
ostream
&
out
,
LogColor
color
,
const
char
*
fmt
,
va_list
args
)
{
void
ColorPrintf
(
std
::
ostream
&
out
,
LogColor
color
,
const
char
*
fmt
,
va_list
args
)
{
#ifdef BENCHMARK_OS_WINDOWS
((
void
)
out
);
// suppress unused warning
((
void
)
out
);
// suppress unused warning
const
HANDLE
stdout_handle
=
GetStdHandle
(
STD_OUTPUT_HANDLE
);
...
...
@@ -152,7 +153,6 @@ void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, va_list arg
if
(
color_code
)
out
<<
FormatString
(
"
\033
[0;3%sm"
,
color_code
);
out
<<
FormatString
(
fmt
,
args
)
<<
"
\033
[m"
;
#endif
}
bool
IsColorTerminal
()
{
...
...
@@ -182,7 +182,7 @@ bool IsColorTerminal() {
}
return
0
!=
isatty
(
fileno
(
stdout
))
&&
term_supports_color
;
#endif // BENCHMARK_OS_WINDOWS
#endif
// BENCHMARK_OS_WINDOWS
}
}
// end namespace benchmark
src/colorprint.h
View file @
332f677b
...
...
@@ -2,8 +2,8 @@
#define BENCHMARK_COLORPRINT_H_
#include <cstdarg>
#include <string>
#include <iostream>
#include <string>
namespace
benchmark
{
enum
LogColor
{
...
...
@@ -20,7 +20,8 @@ enum LogColor {
std
::
string
FormatString
(
const
char
*
msg
,
va_list
args
);
std
::
string
FormatString
(
const
char
*
msg
,
...);
void
ColorPrintf
(
std
::
ostream
&
out
,
LogColor
color
,
const
char
*
fmt
,
va_list
args
);
void
ColorPrintf
(
std
::
ostream
&
out
,
LogColor
color
,
const
char
*
fmt
,
va_list
args
);
void
ColorPrintf
(
std
::
ostream
&
out
,
LogColor
color
,
const
char
*
fmt
,
...);
// Returns true if stdout appears to be a terminal that supports colored
...
...
src/commandlineflags.cc
View file @
332f677b
...
...
@@ -44,7 +44,7 @@ bool ParseInt32(const std::string& src_text, const char* str, int32_t* value) {
// The parsed value overflows as a long. (strtol() returns
// LONG_MAX or LONG_MIN when the input overflows.)
result
!=
long_value
// The parsed value overflows as an Int32.
// The parsed value overflows as an Int32.
)
{
std
::
cerr
<<
src_text
<<
" is expected to be a 32-bit integer, "
<<
"but actually has value
\"
"
<<
str
<<
"
\"
, "
...
...
@@ -95,7 +95,8 @@ static std::string FlagToEnvVar(const char* flag) {
bool
BoolFromEnv
(
const
char
*
flag
,
bool
default_value
)
{
const
std
::
string
env_var
=
FlagToEnvVar
(
flag
);
const
char
*
const
string_value
=
getenv
(
env_var
.
c_str
());
return
string_value
==
nullptr
?
default_value
:
strcmp
(
string_value
,
"0"
)
!=
0
;
return
string_value
==
nullptr
?
default_value
:
strcmp
(
string_value
,
"0"
)
!=
0
;
}
// Reads and returns a 32-bit integer stored in the environment
...
...
@@ -209,8 +210,7 @@ bool IsFlag(const char* str, const char* flag) {
}
bool
IsTruthyFlagValue
(
const
std
::
string
&
str
)
{
if
(
str
.
empty
())
return
true
;
if
(
str
.
empty
())
return
true
;
char
ch
=
str
[
0
];
return
isalnum
(
ch
)
&&
!
(
ch
==
'0'
||
ch
==
'f'
||
ch
==
'F'
||
ch
==
'n'
||
ch
==
'N'
);
...
...
src/complexity.cc
View file @
332f677b
...
...
@@ -119,8 +119,7 @@ LeastSq MinimalLeastSq(const std::vector<int>& n,
// this one. If it is oAuto, it will be calculated the best
// fitting curve.
LeastSq
MinimalLeastSq
(
const
std
::
vector
<
int
>&
n
,
const
std
::
vector
<
double
>&
time
,
const
BigO
complexity
)
{
const
std
::
vector
<
double
>&
time
,
const
BigO
complexity
)
{
CHECK_EQ
(
n
.
size
(),
time
.
size
());
CHECK_GE
(
n
.
size
(),
2
);
// Do not compute fitting curve is less than two
// benchmark runs are given
...
...
src/complexity.h
View file @
332f677b
...
...
@@ -47,10 +47,7 @@ std::vector<BenchmarkReporter::Run> ComputeBigO(
// parameter will return the best fitting curve detected.
struct
LeastSq
{
LeastSq
()
:
coef
(
0
.
0
),
rms
(
0
.
0
),
complexity
(
oNone
)
{}
LeastSq
()
:
coef
(
0
.
0
),
rms
(
0
.
0
),
complexity
(
oNone
)
{}
double
coef
;
double
rms
;
...
...
@@ -60,5 +57,5 @@ struct LeastSq {
// Function to return an string for the calculated complexity
std
::
string
GetBigOString
(
BigO
complexity
);
}
// end namespace benchmark
#endif // COMPLEXITY_H_
}
// end namespace benchmark
#endif
// COMPLEXITY_H_
src/console_reporter.cc
View file @
332f677b
...
...
@@ -39,46 +39,45 @@ bool ConsoleReporter::ReportContext(const Context& context) {
#ifdef BENCHMARK_OS_WINDOWS
if
(
color_output_
&&
&
std
::
cout
!=
&
GetOutputStream
())
{
GetErrorStream
()
<<
"Color printing is only supported for stdout on windows."
" Disabling color printing
\n
"
;
color_output_
=
false
;
GetErrorStream
()
<<
"Color printing is only supported for stdout on windows."
" Disabling color printing
\n
"
;
color_output_
=
false
;
}
#endif
std
::
string
str
=
FormatString
(
"%-*s %13s %13s %10s
\n
"
,
static_cast
<
int
>
(
name_field_width_
),
"Benchmark"
,
"Time"
,
"CPU"
,
"Iterations"
);
std
::
string
str
=
FormatString
(
"%-*s %13s %13s %10s
\n
"
,
static_cast
<
int
>
(
name_field_width_
)
,
"Benchmark"
,
"Time"
,
"CPU"
,
"Iterations"
);
GetOutputStream
()
<<
str
<<
std
::
string
(
str
.
length
()
-
1
,
'-'
)
<<
"
\n
"
;
return
true
;
}
void
ConsoleReporter
::
ReportRuns
(
const
std
::
vector
<
Run
>&
reports
)
{
for
(
const
auto
&
run
:
reports
)
PrintRunData
(
run
);
for
(
const
auto
&
run
:
reports
)
PrintRunData
(
run
);
}
static
void
IgnoreColorPrint
(
std
::
ostream
&
out
,
LogColor
,
const
char
*
fmt
,
...)
{
va_list
args
;
va_start
(
args
,
fmt
);
out
<<
FormatString
(
fmt
,
args
);
va_end
(
args
);
static
void
IgnoreColorPrint
(
std
::
ostream
&
out
,
LogColor
,
const
char
*
fmt
,
...)
{
va_list
args
;
va_start
(
args
,
fmt
);
out
<<
FormatString
(
fmt
,
args
);
va_end
(
args
);
}
void
ConsoleReporter
::
PrintRunData
(
const
Run
&
result
)
{
typedef
void
(
PrinterFn
)(
std
::
ostream
&
,
LogColor
,
const
char
*
,
...);
auto
&
Out
=
GetOutputStream
();
PrinterFn
*
printer
=
color_output_
?
(
PrinterFn
*
)
ColorPrintf
:
IgnoreColorPrint
;
PrinterFn
*
printer
=
color_output_
?
(
PrinterFn
*
)
ColorPrintf
:
IgnoreColorPrint
;
auto
name_color
=
(
result
.
report_big_o
||
result
.
report_rms
)
?
COLOR_BLUE
:
COLOR_GREEN
;
printer
(
Out
,
name_color
,
"%-*s "
,
name_field_width_
,
result
.
benchmark_name
.
c_str
());
result
.
benchmark_name
.
c_str
());
if
(
result
.
error_occurred
)
{
printer
(
Out
,
COLOR_RED
,
"ERROR OCCURRED:
\'
%s
\'
"
,
result
.
error_message
.
c_str
());
result
.
error_message
.
c_str
());
printer
(
Out
,
COLOR_DEFAULT
,
"
\n
"
);
return
;
}
...
...
@@ -91,24 +90,24 @@ void ConsoleReporter::PrintRunData(const Run& result) {
// Format items per second
std
::
string
items
;
if
(
result
.
items_per_second
>
0
)
{
items
=
StrCat
(
" "
,
HumanReadableNumber
(
result
.
items_per_second
),
" items/s"
);
}
items
=
StrCat
(
" "
,
HumanReadableNumber
(
result
.
items_per_second
),
" items/s"
);
}
const
double
real_time
=
result
.
GetAdjustedRealTime
();
const
double
cpu_time
=
result
.
GetAdjustedCPUTime
();
if
(
result
.
report_big_o
)
{
std
::
string
big_o
=
GetBigOString
(
result
.
complexity
);
printer
(
Out
,
COLOR_YELLOW
,
"%10.2f %s %10.2f %s "
,
real_time
,
big_o
.
c_str
(),
cpu_time
,
big_o
.
c_str
());
printer
(
Out
,
COLOR_YELLOW
,
"%10.2f %s %10.2f %s "
,
real_time
,
big_o
.
c_str
(),
cpu_time
,
big_o
.
c_str
());
}
else
if
(
result
.
report_rms
)
{
printer
(
Out
,
COLOR_YELLOW
,
"%10.0f %% %10.0f %% "
,
real_time
*
100
,
cpu_time
*
100
);
cpu_time
*
100
);
}
else
{
const
char
*
timeLabel
=
GetTimeUnitString
(
result
.
time_unit
);
printer
(
Out
,
COLOR_YELLOW
,
"%10.0f %s %10.0f %s "
,
real_time
,
timeLabel
,
cpu_time
,
timeLabel
);
cpu_time
,
timeLabel
);
}
if
(
!
result
.
report_big_o
&&
!
result
.
report_rms
)
{
...
...
src/csv_reporter.cc
View file @
332f677b
...
...
@@ -31,38 +31,28 @@ namespace benchmark {
namespace
{
std
::
vector
<
std
::
string
>
elements
=
{
"name"
,
"iterations"
,
"real_time"
,
"cpu_time"
,
"time_unit"
,
"bytes_per_second"
,
"items_per_second"
,
"label"
,
"error_occurred"
,
"error_message"
};
"name"
,
"iterations"
,
"real_time"
,
"cpu_time"
,
"time_unit"
,
"bytes_per_second"
,
"items_per_second"
,
"label"
,
"error_occurred"
,
"error_message"
};
}
bool
CSVReporter
::
ReportContext
(
const
Context
&
context
)
{
PrintBasicContext
(
&
GetErrorStream
(),
context
);
std
::
ostream
&
Out
=
GetOutputStream
();
for
(
auto
B
=
elements
.
begin
();
B
!=
elements
.
end
();
)
{
for
(
auto
B
=
elements
.
begin
();
B
!=
elements
.
end
();)
{
Out
<<
*
B
++
;
if
(
B
!=
elements
.
end
())
Out
<<
","
;
if
(
B
!=
elements
.
end
())
Out
<<
","
;
}
Out
<<
"
\n
"
;
return
true
;
}
void
CSVReporter
::
ReportRuns
(
const
std
::
vector
<
Run
>
&
reports
)
{
for
(
const
auto
&
run
:
reports
)
PrintRunData
(
run
);
void
CSVReporter
::
ReportRuns
(
const
std
::
vector
<
Run
>&
reports
)
{
for
(
const
auto
&
run
:
reports
)
PrintRunData
(
run
);
}
void
CSVReporter
::
PrintRunData
(
const
Run
&
run
)
{
void
CSVReporter
::
PrintRunData
(
const
Run
&
run
)
{
std
::
ostream
&
Out
=
GetOutputStream
();
// Field with embedded double-quote characters must be doubled and the field
...
...
src/internal_macros.h
View file @
332f677b
...
...
@@ -4,40 +4,39 @@
#include "benchmark/macros.h"
#ifndef __has_feature
#
define __has_feature(x) 0
#define __has_feature(x) 0
#endif
#if defined(__clang__)
#
define COMPILER_CLANG
#define COMPILER_CLANG
#elif defined(_MSC_VER)
#
define COMPILER_MSVC
#define COMPILER_MSVC
#elif defined(__GNUC__)
#
define COMPILER_GCC
#define COMPILER_GCC
#endif
#if __has_feature(cxx_attributes)
#
define BENCHMARK_NORETURN [[noreturn]]
#define BENCHMARK_NORETURN [[noreturn]]
#elif defined(__GNUC__)
#
define BENCHMARK_NORETURN __attribute__((noreturn))
#define BENCHMARK_NORETURN __attribute__((noreturn))
#elif defined(COMPILER_MSVC)
#
define BENCHMARK_NORETURN __declspec(noreturn)
#define BENCHMARK_NORETURN __declspec(noreturn)
#else
#
define BENCHMARK_NORETURN
#define BENCHMARK_NORETURN
#endif
#if defined(__CYGWIN__)
#
define BENCHMARK_OS_CYGWIN 1
#define BENCHMARK_OS_CYGWIN 1
#elif defined(_WIN32)
#
define BENCHMARK_OS_WINDOWS 1
#define BENCHMARK_OS_WINDOWS 1
#elif defined(__APPLE__)
// TODO(ericwf) This doesn't actually check that it is a Mac OSX system. Just
// that it is an apple system.
#
define BENCHMARK_OS_MACOSX 1
#define BENCHMARK_OS_MACOSX 1
#elif defined(__FreeBSD__)
#
define BENCHMARK_OS_FREEBSD 1
#define BENCHMARK_OS_FREEBSD 1
#elif defined(__linux__)
#
define BENCHMARK_OS_LINUX 1
#define BENCHMARK_OS_LINUX 1
#endif
#endif // BENCHMARK_INTERNAL_MACROS_H_
#endif // BENCHMARK_INTERNAL_MACROS_H_
src/json_reporter.cc
View file @
332f677b
...
...
@@ -47,11 +47,9 @@ std::string FormatKV(std::string const& key, int64_t value) {
return
ss
.
str
();
}
int64_t
RoundDouble
(
double
v
)
{
return
static_cast
<
int64_t
>
(
v
+
0.5
);
}
int64_t
RoundDouble
(
double
v
)
{
return
static_cast
<
int64_t
>
(
v
+
0.5
);
}
}
// end namespace
}
// end namespace
bool
JSONReporter
::
ReportContext
(
const
Context
&
context
)
{
std
::
ostream
&
out
=
GetOutputStream
();
...
...
@@ -66,14 +64,11 @@ bool JSONReporter::ReportContext(const Context& context) {
std
::
string
walltime_value
=
LocalDateTimeString
();
out
<<
indent
<<
FormatKV
(
"date"
,
walltime_value
)
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"num_cpus"
,
static_cast
<
int64_t
>
(
context
.
num_cpus
))
out
<<
indent
<<
FormatKV
(
"num_cpus"
,
static_cast
<
int64_t
>
(
context
.
num_cpus
))
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"mhz_per_cpu"
,
RoundDouble
(
context
.
mhz_per_cpu
))
out
<<
indent
<<
FormatKV
(
"mhz_per_cpu"
,
RoundDouble
(
context
.
mhz_per_cpu
))
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"cpu_scaling_enabled"
,
context
.
cpu_scaling_enabled
)
out
<<
indent
<<
FormatKV
(
"cpu_scaling_enabled"
,
context
.
cpu_scaling_enabled
)
<<
",
\n
"
;
#if defined(NDEBUG)
...
...
@@ -118,28 +113,20 @@ void JSONReporter::Finalize() {
void
JSONReporter
::
PrintRunData
(
Run
const
&
run
)
{
std
::
string
indent
(
6
,
' '
);
std
::
ostream
&
out
=
GetOutputStream
();
out
<<
indent
<<
FormatKV
(
"name"
,
run
.
benchmark_name
)
<<
",
\n
"
;
if
(
run
.
error_occurred
)
{
out
<<
indent
<<
FormatKV
(
"error_occurred"
,
run
.
error_occurred
)
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"error_message"
,
run
.
error_message
)
<<
",
\n
"
;
}
if
(
!
run
.
report_big_o
&&
!
run
.
report_rms
)
{
out
<<
indent
<<
FormatKV
(
"iterations"
,
run
.
iterations
)
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"
name"
,
run
.
benchmark_name
)
<<
FormatKV
(
"
real_time"
,
RoundDouble
(
run
.
GetAdjustedRealTime
())
)
<<
",
\n
"
;
if
(
run
.
error_occurred
)
{
out
<<
indent
<<
FormatKV
(
"error_occurred"
,
run
.
error_occurred
)
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"error_message"
,
run
.
error_message
)
<<
",
\n
"
;
}
if
(
!
run
.
report_big_o
&&
!
run
.
report_rms
)
{
out
<<
indent
<<
FormatKV
(
"iterations"
,
run
.
iterations
)
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"real_time"
,
RoundDouble
(
run
.
GetAdjustedRealTime
()))
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"cpu_time"
,
RoundDouble
(
run
.
GetAdjustedCPUTime
()));
out
<<
",
\n
"
<<
indent
<<
FormatKV
(
"time_unit"
,
GetTimeUnitString
(
run
.
time_unit
));
out
<<
indent
<<
FormatKV
(
"cpu_time"
,
RoundDouble
(
run
.
GetAdjustedCPUTime
()));
out
<<
",
\n
"
<<
indent
<<
FormatKV
(
"time_unit"
,
GetTimeUnitString
(
run
.
time_unit
));
}
else
if
(
run
.
report_big_o
)
{
out
<<
indent
<<
FormatKV
(
"cpu_coefficient"
,
RoundDouble
(
run
.
GetAdjustedCPUTime
()))
...
...
@@ -147,15 +134,11 @@ void JSONReporter::PrintRunData(Run const& run) {
out
<<
indent
<<
FormatKV
(
"real_coefficient"
,
RoundDouble
(
run
.
GetAdjustedRealTime
()))
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"big_o"
,
GetBigOString
(
run
.
complexity
))
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"time_unit"
,
GetTimeUnitString
(
run
.
time_unit
));
}
else
if
(
run
.
report_rms
)
{
out
<<
indent
<<
FormatKV
(
"big_o"
,
GetBigOString
(
run
.
complexity
))
<<
",
\n
"
;
out
<<
indent
<<
FormatKV
(
"time_unit"
,
GetTimeUnitString
(
run
.
time_unit
));
}
else
if
(
run
.
report_rms
)
{
out
<<
indent
<<
FormatKV
(
"rms"
,
RoundDouble
(
run
.
GetAdjustedCPUTime
()
*
100
))
<<
'%'
;
<<
FormatKV
(
"rms"
,
RoundDouble
(
run
.
GetAdjustedCPUTime
()
*
100
))
<<
'%'
;
}
if
(
run
.
bytes_per_second
>
0.0
)
{
out
<<
",
\n
"
...
...
@@ -168,9 +151,7 @@ void JSONReporter::PrintRunData(Run const& run) {
<<
FormatKV
(
"items_per_second"
,
RoundDouble
(
run
.
items_per_second
));
}
if
(
!
run
.
report_label
.
empty
())
{
out
<<
",
\n
"
<<
indent
<<
FormatKV
(
"label"
,
run
.
report_label
);
out
<<
",
\n
"
<<
indent
<<
FormatKV
(
"label"
,
run
.
report_label
);
}
out
<<
'\n'
;
}
...
...
src/log.h
View file @
332f677b
...
...
@@ -63,10 +63,11 @@ inline LogType& GetLogInstanceForLevel(int level) {
return
GetNullLogInstance
();
}
}
// end namespace internal
}
// end namespace benchmark
}
// end namespace internal
}
// end namespace benchmark
#define VLOG(x) (::benchmark::internal::GetLogInstanceForLevel(x) \
<< "-- LOG(" << x << "): ")
#define VLOG(x) \
(::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \
" ")
#endif
\ No newline at end of file
src/mutex.h
View file @
332f677b
#ifndef BENCHMARK_MUTEX_H_
#define BENCHMARK_MUTEX_H_
#include <mutex>
#include <condition_variable>
#include <mutex>
#include "check.h"
// Enable thread safety attributes only with clang.
// The attributes can be safely erased when compiling with other compilers.
#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES)
#define THREAD_ANNOTATION_ATTRIBUTE__(x)
__attribute__((x))
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x)
// no-op
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif
#define CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
#define SCOPED_CAPABILITY \
THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
#define GUARDED_BY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
#define PT_GUARDED_BY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
#define ACQUIRED_BEFORE(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
...
...
@@ -56,22 +52,18 @@
#define TRY_ACQUIRE_SHARED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
#define EXCLUDES(...) \
THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
#define ASSERT_CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
#define ASSERT_SHARED_CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
#define RETURN_CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
#define NO_THREAD_SAFETY_ANALYSIS \
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
namespace
benchmark
{
typedef
std
::
condition_variable
Condition
;
...
...
@@ -80,30 +72,27 @@ typedef std::condition_variable Condition;
// we can annotate them with thread safety attributes and use the
// -Wthread-safety warning with clang. The standard library types cannot be
// used directly because they do not provided the required annotations.
class
CAPABILITY
(
"mutex"
)
Mutex
{
public
:
class
CAPABILITY
(
"mutex"
)
Mutex
{
public
:
Mutex
()
{}
void
lock
()
ACQUIRE
()
{
mut_
.
lock
();
}
void
unlock
()
RELEASE
()
{
mut_
.
unlock
();
}
std
::
mutex
&
native_handle
()
{
return
mut_
;
}
private
:
std
::
mutex
&
native_handle
()
{
return
mut_
;
}
private
:
std
::
mutex
mut_
;
};
class
SCOPED_CAPABILITY
MutexLock
{
class
SCOPED_CAPABILITY
MutexLock
{
typedef
std
::
unique_lock
<
std
::
mutex
>
MutexLockImp
;
public
:
MutexLock
(
Mutex
&
m
)
ACQUIRE
(
m
)
:
ml_
(
m
.
native_handle
())
{
}
public
:
MutexLock
(
Mutex
&
m
)
ACQUIRE
(
m
)
:
ml_
(
m
.
native_handle
())
{
}
~
MutexLock
()
RELEASE
()
{}
MutexLockImp
&
native_handle
()
{
return
ml_
;
}
private
:
private
:
MutexLockImp
ml_
;
};
...
...
@@ -161,6 +150,6 @@ class Barrier {
}
};
}
// end namespace benchmark
}
// end namespace benchmark
#endif // BENCHMARK_MUTEX_H_
#endif
// BENCHMARK_MUTEX_H_
src/re.h
View file @
332f677b
...
...
@@ -46,19 +46,19 @@ class Regex {
// Returns whether str matches the compiled regular expression.
bool
Match
(
const
std
::
string
&
str
);
private
:
private
:
bool
init_
;
// Underlying regular expression object
// Underlying regular expression object
#if defined(HAVE_STD_REGEX)
std
::
regex
re_
;
#elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
regex_t
re_
;
#else
#
error No regular expression backend implementation available
#error No regular expression backend implementation available
#endif
};
#if defined(HAVE_STD_REGEX)
inline
bool
Regex
::
Init
(
const
std
::
string
&
spec
,
std
::
string
*
error
)
{
...
...
@@ -74,7 +74,7 @@ inline bool Regex::Init(const std::string& spec, std::string* error) {
return
init_
;
}
inline
Regex
::~
Regex
()
{
}
inline
Regex
::~
Regex
()
{}
inline
bool
Regex
::
Match
(
const
std
::
string
&
str
)
{
if
(
!
init_
)
{
...
...
src/reporter.cc
View file @
332f677b
...
...
@@ -18,8 +18,8 @@
#include <cstdlib>
#include <iostream>
#include <vector>
#include <tuple>
#include <vector>
#include "check.h"
#include "stat.h"
...
...
@@ -27,49 +27,42 @@
namespace
benchmark
{
BenchmarkReporter
::
BenchmarkReporter
()
:
output_stream_
(
&
std
::
cout
),
error_stream_
(
&
std
::
cerr
)
{
}
:
output_stream_
(
&
std
::
cout
),
error_stream_
(
&
std
::
cerr
)
{}
BenchmarkReporter
::~
BenchmarkReporter
()
{
}
BenchmarkReporter
::~
BenchmarkReporter
()
{}
void
BenchmarkReporter
::
PrintBasicContext
(
std
::
ostream
*
out_ptr
,
Context
const
&
context
)
{
CHECK
(
out_ptr
)
<<
"cannot be null"
;
auto
&
Out
=
*
out_ptr
;
auto
&
Out
=
*
out_ptr
;
Out
<<
"Run on ("
<<
context
.
num_cpus
<<
" X "
<<
context
.
mhz_per_cpu
<<
" MHz CPU "
<<
((
context
.
num_cpus
>
1
)
?
"s"
:
""
)
<<
")
\n
"
;
<<
" MHz CPU "
<<
((
context
.
num_cpus
>
1
)
?
"s"
:
""
)
<<
")
\n
"
;
Out
<<
LocalDateTimeString
()
<<
"
\n
"
;
if
(
context
.
cpu_scaling_enabled
)
{
Out
<<
"***WARNING*** CPU scaling is enabled, the benchmark "
"real time measurements may be noisy and will incur extra "
"overhead.
\n
"
;
"real time measurements may be noisy and will incur extra "
"overhead.
\n
"
;
}
#ifndef NDEBUG
Out
<<
"***WARNING*** Library was built as DEBUG. Timings may be "
"affected.
\n
"
;
"affected.
\n
"
;
#endif
}
double
BenchmarkReporter
::
Run
::
GetAdjustedRealTime
()
const
{
double
new_time
=
real_accumulated_time
*
GetTimeUnitMultiplier
(
time_unit
);
if
(
iterations
!=
0
)
new_time
/=
static_cast
<
double
>
(
iterations
);
if
(
iterations
!=
0
)
new_time
/=
static_cast
<
double
>
(
iterations
);
return
new_time
;
}
double
BenchmarkReporter
::
Run
::
GetAdjustedCPUTime
()
const
{
double
new_time
=
cpu_accumulated_time
*
GetTimeUnitMultiplier
(
time_unit
);
if
(
iterations
!=
0
)
new_time
/=
static_cast
<
double
>
(
iterations
);
if
(
iterations
!=
0
)
new_time
/=
static_cast
<
double
>
(
iterations
);
return
new_time
;
}
}
// end namespace benchmark
}
// end namespace benchmark
src/stat.h
View file @
332f677b
...
...
@@ -6,7 +6,6 @@
#include <ostream>
#include <type_traits>
namespace
benchmark
{
template
<
typename
VType
,
typename
NumType
>
...
...
@@ -136,7 +135,7 @@ class Stat1 {
private
:
static_assert
(
std
::
is_integral
<
NumType
>::
value
&&
!
std
::
is_same
<
NumType
,
bool
>::
value
,
!
std
::
is_same
<
NumType
,
bool
>::
value
,
"NumType must be an integral type that is not bool."
);
// Let i be the index of the samples provided (using +=)
// and weight[i],value[i] be the data of sample #i
...
...
src/string_util.cc
View file @
332f677b
#include "string_util.h"
#include <array>
#include <cmath>
#include <cstdarg>
#include <
array
>
#include <
cstdio
>
#include <memory>
#include <sstream>
#include <stdio.h>
#include "arraysize.h"
...
...
@@ -27,7 +27,7 @@ static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
static
const
int64_t
kUnitsSize
=
arraysize
(
kBigSIUnits
);
}
// end anonymous namespace
}
// end anonymous namespace
void
ToExponentAndMantissa
(
double
val
,
double
thresh
,
int
precision
,
double
one_k
,
std
::
string
*
mantissa
,
...
...
@@ -118,8 +118,7 @@ std::string HumanReadableNumber(double n) {
return
ToBinaryStringFullySpecified
(
n
,
1.1
,
1
);
}
std
::
string
StringPrintFImp
(
const
char
*
msg
,
va_list
args
)
{
std
::
string
StringPrintFImp
(
const
char
*
msg
,
va_list
args
)
{
// we might need a second shot at this, so pre-emptivly make a copy
va_list
args_cp
;
va_copy
(
args_cp
,
args
);
...
...
@@ -128,14 +127,14 @@ std::string StringPrintFImp(const char *msg, va_list args)
// allocation guess what the size might be
std
::
array
<
char
,
256
>
local_buff
;
std
::
size_t
size
=
local_buff
.
size
();
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation in the android-ndk
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
// in the android-ndk
auto
ret
=
vsnprintf
(
local_buff
.
data
(),
size
,
msg
,
args_cp
);
va_end
(
args_cp
);
// handle empty expansion
if
(
ret
==
0
)
return
std
::
string
{};
if
(
ret
==
0
)
return
std
::
string
{};
if
(
static_cast
<
std
::
size_t
>
(
ret
)
<
size
)
return
std
::
string
(
local_buff
.
data
());
...
...
@@ -143,13 +142,13 @@ std::string StringPrintFImp(const char *msg, va_list args)
// add 1 to size to account for null-byte in size cast to prevent overflow
size
=
static_cast
<
std
::
size_t
>
(
ret
)
+
1
;
auto
buff_ptr
=
std
::
unique_ptr
<
char
[]
>
(
new
char
[
size
]);
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation in the android-ndk
// 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
// in the android-ndk
ret
=
vsnprintf
(
buff_ptr
.
get
(),
size
,
msg
,
args
);
return
std
::
string
(
buff_ptr
.
get
());
}
std
::
string
StringPrintF
(
const
char
*
format
,
...)
{
std
::
string
StringPrintF
(
const
char
*
format
,
...)
{
va_list
args
;
va_start
(
args
,
format
);
std
::
string
tmp
=
StringPrintFImp
(
format
,
args
);
...
...
@@ -160,10 +159,10 @@ std::string StringPrintF(const char* format, ...)
void
ReplaceAll
(
std
::
string
*
str
,
const
std
::
string
&
from
,
const
std
::
string
&
to
)
{
std
::
size_t
start
=
0
;
while
((
start
=
str
->
find
(
from
,
start
))
!=
std
::
string
::
npos
)
{
while
((
start
=
str
->
find
(
from
,
start
))
!=
std
::
string
::
npos
)
{
str
->
replace
(
start
,
from
.
length
(),
to
);
start
+=
to
.
length
();
}
}
}
// end namespace benchmark
}
// end namespace benchmark
src/string_util.h
View file @
332f677b
#ifndef BENCHMARK_STRING_UTIL_H_
#define BENCHMARK_STRING_UTIL_H_
#include <string>
#include <sstream>
#include <string>
#include <utility>
#include "internal_macros.h"
...
...
@@ -14,23 +14,19 @@ std::string HumanReadableNumber(double n);
std
::
string
StringPrintF
(
const
char
*
format
,
...);
inline
std
::
ostream
&
StringCatImp
(
std
::
ostream
&
out
)
BENCHMARK_NOEXCEPT
{
inline
std
::
ostream
&
StringCatImp
(
std
::
ostream
&
out
)
BENCHMARK_NOEXCEPT
{
return
out
;
}
template
<
class
First
,
class
...
Rest
>
inline
std
::
ostream
&
StringCatImp
(
std
::
ostream
&
out
,
First
&&
f
,
Rest
&&
...
rest
)
{
template
<
class
First
,
class
...
Rest
>
inline
std
::
ostream
&
StringCatImp
(
std
::
ostream
&
out
,
First
&&
f
,
Rest
&&
...
rest
)
{
out
<<
std
::
forward
<
First
>
(
f
);
return
StringCatImp
(
out
,
std
::
forward
<
Rest
>
(
rest
)...);
}
template
<
class
...
Args
>
inline
std
::
string
StrCat
(
Args
&&
...
args
)
{
template
<
class
...
Args
>
inline
std
::
string
StrCat
(
Args
&&
...
args
)
{
std
::
ostringstream
ss
;
StringCatImp
(
ss
,
std
::
forward
<
Args
>
(
args
)...);
return
ss
.
str
();
...
...
@@ -39,6 +35,6 @@ inline std::string StrCat(Args&&... args)
void
ReplaceAll
(
std
::
string
*
str
,
const
std
::
string
&
from
,
const
std
::
string
&
to
);
}
// end namespace benchmark
}
// end namespace benchmark
#endif // BENCHMARK_STRING_UTIL_H_
#endif
// BENCHMARK_STRING_UTIL_H_
src/sysinfo.cc
View file @
332f677b
...
...
@@ -17,13 +17,13 @@
#ifdef BENCHMARK_OS_WINDOWS
#include <Shlwapi.h>
#include <Windows.h>
#include <VersionHelpers.h>
#include <Windows.h>
#else
#include <fcntl.h>
#include <sys/resource.h>
#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
#include <sys/time.h>
#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
#include <unistd.h>
#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
#include <sys/sysctl.h>
...
...
@@ -31,8 +31,8 @@
#endif
#include <cerrno>
#include <cstdio>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
...
...
@@ -126,7 +126,8 @@ void InitializeSystemInfo() {
if
(
fd
==
-
1
)
{
perror
(
pname
);
if
(
!
saw_mhz
)
{
cpuinfo_cycles_per_second
=
static_cast
<
double
>
(
EstimateCyclesPerSecond
());
cpuinfo_cycles_per_second
=
static_cast
<
double
>
(
EstimateCyclesPerSecond
());
}
return
;
}
...
...
@@ -196,7 +197,8 @@ void InitializeSystemInfo() {
cpuinfo_cycles_per_second
=
bogo_clock
;
}
else
{
// If we don't even have bogomips, we'll use the slow estimation.
cpuinfo_cycles_per_second
=
static_cast
<
double
>
(
EstimateCyclesPerSecond
());
cpuinfo_cycles_per_second
=
static_cast
<
double
>
(
EstimateCyclesPerSecond
());
}
}
if
(
num_cpus
==
0
)
{
...
...
@@ -238,7 +240,6 @@ void InitializeSystemInfo() {
}
// TODO: also figure out cpuinfo_num_cpus
#elif defined BENCHMARK_OS_WINDOWS
// In NT, read MHz from the registry. If we fail to do so or we're in win9x
// then make a crude estimate.
...
...
@@ -248,15 +249,19 @@ void InitializeSystemInfo() {
SHGetValueA
(
HKEY_LOCAL_MACHINE
,
"HARDWARE
\\
DESCRIPTION
\\
System
\\
CentralProcessor
\\
0"
,
"~MHz"
,
nullptr
,
&
data
,
&
data_size
)))
cpuinfo_cycles_per_second
=
static_cast
<
double
>
((
int64_t
)
data
*
(
int64_t
)(
1000
*
1000
));
// was mhz
cpuinfo_cycles_per_second
=
static_cast
<
double
>
((
int64_t
)
data
*
(
int64_t
)(
1000
*
1000
));
// was mhz
else
cpuinfo_cycles_per_second
=
static_cast
<
double
>
(
EstimateCyclesPerSecond
());
SYSTEM_INFO
sysinfo
;
// Use memset as opposed to = {} to avoid GCC missing initializer false positives.
// Use memset as opposed to = {} to avoid GCC missing initializer false
// positives.
std
::
memset
(
&
sysinfo
,
0
,
sizeof
(
SYSTEM_INFO
));
GetSystemInfo
(
&
sysinfo
);
cpuinfo_num_cpus
=
sysinfo
.
dwNumberOfProcessors
;
// number of logical processors in the current group
cpuinfo_num_cpus
=
sysinfo
.
dwNumberOfProcessors
;
// number of logical
// processors in the current
// group
#elif defined BENCHMARK_OS_MACOSX
// returning "mach time units" per second. the current number of elapsed
...
...
@@ -277,8 +282,8 @@ void InitializeSystemInfo() {
int
num_cpus
=
0
;
size_t
size
=
sizeof
(
num_cpus
);
int
numcpus_name
[]
=
{
CTL_HW
,
HW_NCPU
};
if
(
::
sysctl
(
numcpus_name
,
arraysize
(
numcpus_name
),
&
num_cpus
,
&
size
,
nullptr
,
0
)
==
0
&&
if
(
::
sysctl
(
numcpus_name
,
arraysize
(
numcpus_name
),
&
num_cpus
,
&
size
,
nullptr
,
0
)
==
0
&&
(
size
==
sizeof
(
num_cpus
)))
cpuinfo_num_cpus
=
num_cpus
;
...
...
@@ -316,8 +321,8 @@ bool CpuScalingEnabled() {
// 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"
);
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
];
...
...
src/timers.cc
View file @
332f677b
...
...
@@ -92,16 +92,16 @@ double MakeTime(struct timespec const& ts) {
}
#endif
BENCHMARK_NORETURN
static
void
DiagnoseAndExit
(
const
char
*
msg
)
{
std
::
cerr
<<
"ERROR: "
<<
msg
<<
std
::
endl
;
std
::
exit
(
EXIT_FAILURE
);
BENCHMARK_NORETURN
static
void
DiagnoseAndExit
(
const
char
*
msg
)
{
std
::
cerr
<<
"ERROR: "
<<
msg
<<
std
::
endl
;
std
::
exit
(
EXIT_FAILURE
);
}
}
// end namespace
double
ProcessCPUUsage
()
{
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See https://github.com/google/benchmark/pull/292
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
// https://github.com/google/benchmark/pull/292
#if defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
struct
timespec
spec
;
if
(
clock_gettime
(
CLOCK_PROCESS_CPUTIME_ID
,
&
spec
)
==
0
)
...
...
@@ -113,23 +113,23 @@ double ProcessCPUUsage() {
FILETIME
exit_time
;
FILETIME
kernel_time
;
FILETIME
user_time
;
if
(
GetProcessTimes
(
proc
,
&
creation_time
,
&
exit_time
,
&
kernel_time
,
&
user_time
))
if
(
GetProcessTimes
(
proc
,
&
creation_time
,
&
exit_time
,
&
kernel_time
,
&
user_time
))
return
MakeTime
(
kernel_time
,
user_time
);
DiagnoseAndExit
(
"GetProccessTimes() failed"
);
#else
struct
rusage
ru
;
if
(
getrusage
(
RUSAGE_SELF
,
&
ru
)
==
0
)
return
MakeTime
(
ru
);
if
(
getrusage
(
RUSAGE_SELF
,
&
ru
)
==
0
)
return
MakeTime
(
ru
);
DiagnoseAndExit
(
"clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed"
);
#endif
}
double
ThreadCPUUsage
()
{
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See https://github.com/google/benchmark/pull/292
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
// https://github.com/google/benchmark/pull/292
#if defined(CLOCK_THREAD_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
struct
timespec
ts
;
if
(
clock_gettime
(
CLOCK_THREAD_CPUTIME_ID
,
&
ts
)
==
0
)
return
MakeTime
(
ts
);
if
(
clock_gettime
(
CLOCK_THREAD_CPUTIME_ID
,
&
ts
)
==
0
)
return
MakeTime
(
ts
);
DiagnoseAndExit
(
"clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed"
);
#elif defined(BENCHMARK_OS_WINDOWS)
HANDLE
this_thread
=
GetCurrentThread
();
...
...
@@ -144,8 +144,8 @@ double ThreadCPUUsage() {
mach_msg_type_number_t
count
=
THREAD_BASIC_INFO_COUNT
;
thread_basic_info_data_t
info
;
mach_port_t
thread
=
pthread_mach_thread_np
(
pthread_self
());
if
(
thread_info
(
thread
,
THREAD_BASIC_INFO
,
(
thread_info_t
)
&
info
,
&
count
)
==
KERN_SUCCESS
)
{
if
(
thread_info
(
thread
,
THREAD_BASIC_INFO
,
(
thread_info_t
)
&
info
,
&
count
)
==
KERN_SUCCESS
)
{
return
MakeTime
(
info
);
}
DiagnoseAndExit
(
"ThreadCPUUsage() failed when evaluating thread_info"
);
...
...
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