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