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
4ce184d8
Commit
4ce184d8
authored
Jan 09, 2014
by
Dominic Hamon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code reformat
parent
80093519
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
292 additions
and
311 deletions
+292
-311
benchmark.h
include/benchmark/benchmark.h
+14
-15
macros.h
include/benchmark/macros.h
+7
-4
benchmark.cc
src/benchmark.cc
+99
-115
colorprint.cc
src/colorprint.cc
+31
-17
commandlineflags.cc
src/commandlineflags.cc
+9
-13
commandlineflags.h
src/commandlineflags.h
+0
-0
cycleclock.h
src/cycleclock.h
+14
-14
mutex_lock.h
src/mutex_lock.h
+1
-3
sleep.cc
src/sleep.cc
+1
-3
stat.h
src/stat.h
+74
-83
sysinfo.cc
src/sysinfo.cc
+37
-38
walltime.cc
src/walltime.cc
+5
-6
No files found.
include/benchmark/benchmark.h
View file @
4ce184d8
...
@@ -414,8 +414,8 @@ class Benchmark {
...
@@ -414,8 +414,8 @@ class Benchmark {
static
void
RunInstance
(
const
Instance
&
b
,
BenchmarkReporter
*
br
);
static
void
RunInstance
(
const
Instance
&
b
,
BenchmarkReporter
*
br
);
friend
class
::
benchmark
::
State
;
friend
class
::
benchmark
::
State
;
friend
struct
::
benchmark
::
internal
::
Benchmark
::
Instance
;
friend
struct
::
benchmark
::
internal
::
Benchmark
::
Instance
;
friend
void
::
benchmark
::
internal
::
RunMatchingBenchmarks
(
friend
void
::
benchmark
::
internal
::
RunMatchingBenchmarks
(
const
std
::
string
&
,
const
std
::
string
&
,
BenchmarkReporter
*
);
BenchmarkReporter
*
);
DISALLOW_COPY_AND_ASSIGN
(
Benchmark
);
DISALLOW_COPY_AND_ASSIGN
(
Benchmark
);
};
};
...
@@ -425,7 +425,7 @@ class Benchmark {
...
@@ -425,7 +425,7 @@ class Benchmark {
struct
BenchmarkContextData
{
struct
BenchmarkContextData
{
int
num_cpus
;
int
num_cpus
;
double
mhz_per_cpu
;
double
mhz_per_cpu
;
//std::string cpu_info;
//
std::string cpu_info;
bool
cpu_scaling_enabled
;
bool
cpu_scaling_enabled
;
// The number of chars in the longest benchmark name.
// The number of chars in the longest benchmark name.
...
@@ -433,8 +433,8 @@ struct BenchmarkContextData {
...
@@ -433,8 +433,8 @@ struct BenchmarkContextData {
};
};
struct
BenchmarkRunData
{
struct
BenchmarkRunData
{
BenchmarkRunData
()
:
BenchmarkRunData
()
thread_index
(
-
1
),
:
thread_index
(
-
1
),
iterations
(
1
),
iterations
(
1
),
real_accumulated_time
(
0
),
real_accumulated_time
(
0
),
cpu_accumulated_time
(
0
),
cpu_accumulated_time
(
0
),
...
@@ -481,15 +481,13 @@ class BenchmarkReporter {
...
@@ -481,15 +481,13 @@ class BenchmarkReporter {
virtual
~
BenchmarkReporter
();
virtual
~
BenchmarkReporter
();
};
};
// ------------------------------------------------------
// ------------------------------------------------------
// Internal implementation details follow; please ignore
// Internal implementation details follow; please ignore
// Given a collection of reports, computes their mean and stddev.
// Given a collection of reports, computes their mean and stddev.
// REQUIRES: all runs in "reports" must be from the same benchmark.
// REQUIRES: all runs in "reports" must be from the same benchmark.
void
ComputeStats
(
const
std
::
vector
<
BenchmarkRunData
>&
reports
,
void
ComputeStats
(
const
std
::
vector
<
BenchmarkRunData
>&
reports
,
BenchmarkRunData
*
mean_data
,
BenchmarkRunData
*
mean_data
,
BenchmarkRunData
*
stddev_data
);
BenchmarkRunData
*
stddev_data
);
// 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().
...
@@ -497,6 +495,7 @@ class ConsoleReporter : public BenchmarkReporter {
...
@@ -497,6 +495,7 @@ class ConsoleReporter : public BenchmarkReporter {
public
:
public
:
virtual
bool
ReportContext
(
const
BenchmarkContextData
&
context
);
virtual
bool
ReportContext
(
const
BenchmarkContextData
&
context
);
virtual
void
ReportRuns
(
const
std
::
vector
<
BenchmarkRunData
>&
reports
);
virtual
void
ReportRuns
(
const
std
::
vector
<
BenchmarkRunData
>&
reports
);
private
:
private
:
std
::
string
PrintMemoryUsage
(
double
bytes
);
std
::
string
PrintMemoryUsage
(
double
bytes
);
virtual
void
PrintRunData
(
const
BenchmarkRunData
&
report
);
virtual
void
PrintRunData
(
const
BenchmarkRunData
&
report
);
...
@@ -513,11 +512,11 @@ void Initialize(int* argc, const char** argv);
...
@@ -513,11 +512,11 @@ void Initialize(int* argc, const char** argv);
// Helpers for generating unique variable names
// Helpers for generating unique variable names
#define BENCHMARK_CONCAT(a, b, c) BENCHMARK_CONCAT2(a, b, c)
#define BENCHMARK_CONCAT(a, b, c) BENCHMARK_CONCAT2(a, b, c)
#define BENCHMARK_CONCAT2(a, b, c) a
## b ##
c
#define BENCHMARK_CONCAT2(a, b, c) a
##b##
c
#define BENCHMARK(n) \
#define BENCHMARK(n) \
static ::benchmark::internal::Benchmark*
\
static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT(
\
BENCHMARK_CONCAT(__benchmark_, n, __LINE__) ATTRIBUTE_UNUSED =
\
__benchmark_, n, __LINE__) ATTRIBUTE_UNUSED =
\
(new ::benchmark::internal::Benchmark(#n, n))
(new ::benchmark::internal::Benchmark(#n, n))
// Old-style macros
// Old-style macros
...
@@ -536,13 +535,13 @@ void Initialize(int* argc, const char** argv);
...
@@ -536,13 +535,13 @@ void Initialize(int* argc, const char** argv);
//
//
// will register BM_Foo<1> as a benchmark.
// will register BM_Foo<1> as a benchmark.
#define BENCHMARK_TEMPLATE(n, a) \
#define BENCHMARK_TEMPLATE(n, a) \
static ::benchmark::internal::Benchmark*
\
static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT(
\
BENCHMARK_CONCAT(__benchmark_, n, __LINE__) ATTRIBUTE_UNUSED =
\
__benchmark_, n, __LINE__) ATTRIBUTE_UNUSED =
\
(new ::benchmark::internal::Benchmark(#n "<" #a ">", n<a>))
(new ::benchmark::internal::Benchmark(#n "<" #a ">", n<a>))
#define BENCHMARK_TEMPLATE2(n, a, b) \
#define BENCHMARK_TEMPLATE2(n, a, b) \
static ::benchmark::internal::Benchmark*
\
static ::benchmark::internal::Benchmark*
BENCHMARK_CONCAT(
\
BENCHMARK_CONCAT(__benchmark_, n, __LINE__) ATTRIBUTE_UNUSED =
\
__benchmark_, n, __LINE__) ATTRIBUTE_UNUSED =
\
(new ::benchmark::internal::Benchmark(#n "<" #a "," #b ">", n<a, b>))
(new ::benchmark::internal::Benchmark(#n "<" #a "," #b ">", n<a, b>))
#endif // BENCHMARK_BENCHMARK_H_
#endif // BENCHMARK_BENCHMARK_H_
...
...
include/benchmark/macros.h
View file @
4ce184d8
...
@@ -34,7 +34,10 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
...
@@ -34,7 +34,10 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
#define CHECK(b) do { if (!(b)) assert(false); } while(0)
#define CHECK(b) \
do { \
if (!(b)) assert(false); \
} while (0)
#define CHECK_EQ(a, b) CHECK((a) == (b))
#define CHECK_EQ(a, b) CHECK((a) == (b))
#define CHECK_NE(a, b) CHECK((a) != (b))
#define CHECK_NE(a, b) CHECK((a) != (b))
#define CHECK_GE(a, b) CHECK((a) >= (b))
#define CHECK_GE(a, b) CHECK((a) >= (b))
...
@@ -45,14 +48,14 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
...
@@ -45,14 +48,14 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
//
//
// Prevent the compiler from complaining about or optimizing away variables
// Prevent the compiler from complaining about or optimizing away variables
// that appear unused.
// that appear unused.
#define ATTRIBUTE_UNUSED __attribute__
((unused))
#define ATTRIBUTE_UNUSED __attribute__((unused))
//
//
// For functions we want to force inline or not inline.
// For functions we want to force inline or not inline.
// Introduced in gcc 3.1.
// Introduced in gcc 3.1.
#define ATTRIBUTE_ALWAYS_INLINE
__attribute__
((always_inline))
#define ATTRIBUTE_ALWAYS_INLINE
__attribute__
((always_inline))
#define HAVE_ATTRIBUTE_ALWAYS_INLINE 1
#define HAVE_ATTRIBUTE_ALWAYS_INLINE 1
#define ATTRIBUTE_NOINLINE __attribute__
((noinline))
#define ATTRIBUTE_NOINLINE __attribute__((noinline))
#define HAVE_ATTRIBUTE_NOINLINE 1
#define HAVE_ATTRIBUTE_NOINLINE 1
#endif // BENCHMARK_MACROS_H_
#endif // BENCHMARK_MACROS_H_
src/benchmark.cc
View file @
4ce184d8
...
@@ -58,14 +58,14 @@ DEFINE_bool(color_print, true, "Enables colorized logging.");
...
@@ -58,14 +58,14 @@ DEFINE_bool(color_print, true, "Enables colorized logging.");
DECLARE_string
(
heap_check
);
DECLARE_string
(
heap_check
);
// The ""'s catch people who don't pass in a literal for "str"
// The ""'s catch people who don't pass in a literal for "str"
#define strliterallen(str) (sizeof("" str "")
-
1)
#define strliterallen(str) (sizeof("" str "")
-
1)
// Must use a string literal for prefix.
// Must use a string literal for prefix.
#define memprefix(str, len, prefix) \
#define memprefix(str, len, prefix) \
(
(((len) >= strliterallen(prefix))
\
(
(((len) >= strliterallen(prefix)) &&
\
&& memcmp(str, prefix, strliterallen(prefix)) == 0)
\
memcmp(str, prefix, strliterallen(prefix)) == 0)
\
? str + strliterallen(prefix) \
? str + strliterallen(prefix) \
: NULL
)
: NULL
)
namespace
benchmark
{
namespace
benchmark
{
namespace
{
namespace
{
...
@@ -83,9 +83,8 @@ static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
...
@@ -83,9 +83,8 @@ static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
"Small SI and Big SI unit arrays must be the same size"
);
"Small SI and Big SI unit arrays must be the same size"
);
static
const
int
kUnitsSize
=
arraysize
(
kBigSIUnits
);
static
const
int
kUnitsSize
=
arraysize
(
kBigSIUnits
);
void
ToExponentAndMantissa
(
double
val
,
double
thresh
,
void
ToExponentAndMantissa
(
double
val
,
double
thresh
,
int
precision
,
int
precision
,
double
one_k
,
double
one_k
,
std
::
string
*
mantissa
,
int
*
exponent
)
{
std
::
string
*
mantissa
,
int
*
exponent
)
{
std
::
stringstream
mantissa_stream
;
std
::
stringstream
mantissa_stream
;
if
(
val
<
0
)
{
if
(
val
<
0
)
{
...
@@ -136,15 +135,13 @@ void ToExponentAndMantissa(double val, double thresh,
...
@@ -136,15 +135,13 @@ void ToExponentAndMantissa(double val, double thresh,
}
}
std
::
string
ExponentToPrefix
(
int
exponent
,
bool
iec
)
{
std
::
string
ExponentToPrefix
(
int
exponent
,
bool
iec
)
{
if
(
exponent
==
0
)
if
(
exponent
==
0
)
return
""
;
return
""
;
const
int
index
=
(
exponent
>
0
?
exponent
-
1
:
-
exponent
-
1
);
const
int
index
=
(
exponent
>
0
?
exponent
-
1
:
-
exponent
-
1
);
if
(
index
>=
kUnitsSize
)
if
(
index
>=
kUnitsSize
)
return
""
;
return
""
;
const
char
*
array
=
(
exponent
>
0
?
(
iec
?
kBigIECUnits
:
kBigSIUnits
)
:
const
char
*
array
=
kSmallSIUnits
);
(
exponent
>
0
?
(
iec
?
kBigIECUnits
:
kBigSIUnits
)
:
kSmallSIUnits
);
if
(
iec
)
if
(
iec
)
return
array
[
index
]
+
std
::
string
(
"i"
);
return
array
[
index
]
+
std
::
string
(
"i"
);
else
else
...
@@ -207,7 +204,7 @@ const char* Prefix() {
...
@@ -207,7 +204,7 @@ const char* Prefix() {
}
}
// TODO
// TODO
//static internal::MallocCounter *benchmark_mc;
//
static internal::MallocCounter *benchmark_mc;
bool
CpuScalingEnabled
()
{
bool
CpuScalingEnabled
()
{
// On Linux, the CPUfreq subsystem exposes CPU information as files on the
// On Linux, the CPUfreq subsystem exposes CPU information as files on the
...
@@ -218,13 +215,11 @@ bool CpuScalingEnabled() {
...
@@ -218,13 +215,11 @@ bool CpuScalingEnabled() {
ss
<<
"/sys/devices/system/cpu/cpu"
<<
cpu
<<
"/cpufreq/scaling_governor"
;
ss
<<
"/sys/devices/system/cpu/cpu"
<<
cpu
<<
"/cpufreq/scaling_governor"
;
std
::
string
governor_file
=
ss
.
str
();
std
::
string
governor_file
=
ss
.
str
();
FILE
*
file
=
fopen
(
governor_file
.
c_str
(),
"r"
);
FILE
*
file
=
fopen
(
governor_file
.
c_str
(),
"r"
);
if
(
!
file
)
if
(
!
file
)
break
;
break
;
char
buff
[
16
];
char
buff
[
16
];
size_t
bytes_read
=
fread
(
buff
,
1
,
sizeof
(
buff
),
file
);
size_t
bytes_read
=
fread
(
buff
,
1
,
sizeof
(
buff
),
file
);
fclose
(
file
);
fclose
(
file
);
if
(
memprefix
(
buff
,
bytes_read
,
"performance"
)
==
NULL
)
if
(
memprefix
(
buff
,
bytes_read
,
"performance"
)
==
NULL
)
return
true
;
return
true
;
}
}
return
false
;
return
false
;
}
}
...
@@ -236,8 +231,7 @@ namespace internal {
...
@@ -236,8 +231,7 @@ namespace internal {
BenchmarkReporter
::~
BenchmarkReporter
()
{}
BenchmarkReporter
::~
BenchmarkReporter
()
{}
void
ComputeStats
(
const
std
::
vector
<
BenchmarkRunData
>&
reports
,
void
ComputeStats
(
const
std
::
vector
<
BenchmarkRunData
>&
reports
,
BenchmarkRunData
*
mean_data
,
BenchmarkRunData
*
mean_data
,
BenchmarkRunData
*
stddev_data
)
{
BenchmarkRunData
*
stddev_data
)
{
// Accumulators.
// Accumulators.
Stat1_d
real_accumulated_time_stat
;
Stat1_d
real_accumulated_time_stat
;
Stat1_d
cpu_accumulated_time_stat
;
Stat1_d
cpu_accumulated_time_stat
;
...
@@ -257,8 +251,8 @@ void ComputeStats(const std::vector<BenchmarkRunData>& reports,
...
@@ -257,8 +251,8 @@ void ComputeStats(const std::vector<BenchmarkRunData>& reports,
items_per_second_stat
+=
Stat1_d
(
it
->
items_per_second
,
it
->
iterations
);
items_per_second_stat
+=
Stat1_d
(
it
->
items_per_second
,
it
->
iterations
);
bytes_per_second_stat
+=
Stat1_d
(
it
->
bytes_per_second
,
it
->
iterations
);
bytes_per_second_stat
+=
Stat1_d
(
it
->
bytes_per_second
,
it
->
iterations
);
iterations_stat
+=
Stat1_d
(
it
->
iterations
,
it
->
iterations
);
iterations_stat
+=
Stat1_d
(
it
->
iterations
,
it
->
iterations
);
max_heapbytes_used_stat
+=
Stat1MinMax_d
(
it
->
max_heapbytes_used
,
max_heapbytes_used_stat
+=
it
->
iterations
);
Stat1MinMax_d
(
it
->
max_heapbytes_used
,
it
->
iterations
);
}
}
// Get the data from the accumulator to BenchmarkRunData's.
// Get the data from the accumulator to BenchmarkRunData's.
...
@@ -268,7 +262,7 @@ void ComputeStats(const std::vector<BenchmarkRunData>& reports,
...
@@ -268,7 +262,7 @@ void ComputeStats(const std::vector<BenchmarkRunData>& reports,
mean_data
->
cpu_accumulated_time
=
cpu_accumulated_time_stat
.
Mean
();
mean_data
->
cpu_accumulated_time
=
cpu_accumulated_time_stat
.
Mean
();
mean_data
->
bytes_per_second
=
bytes_per_second_stat
.
Mean
();
mean_data
->
bytes_per_second
=
bytes_per_second_stat
.
Mean
();
mean_data
->
items_per_second
=
items_per_second_stat
.
Mean
();
mean_data
->
items_per_second
=
items_per_second_stat
.
Mean
();
mean_data
->
max_heapbytes_used
=
max_heapbytes_used_stat
.
M
ax
();
mean_data
->
max_heapbytes_used
=
max_heapbytes_used_stat
.
m
ax
();
// Only add label to mean/stddev if it is same for all runs
// Only add label to mean/stddev if it is same for all runs
mean_data
->
report_label
=
reports
[
0
].
report_label
;
mean_data
->
report_label
=
reports
[
0
].
report_label
;
...
@@ -290,8 +284,7 @@ void ComputeStats(const std::vector<BenchmarkRunData>& reports,
...
@@ -290,8 +284,7 @@ void ComputeStats(const std::vector<BenchmarkRunData>& reports,
}
}
std
::
string
ConsoleReporter
::
PrintMemoryUsage
(
double
bytes
)
{
std
::
string
ConsoleReporter
::
PrintMemoryUsage
(
double
bytes
)
{
if
(
!
get_memory_usage
||
bytes
<
0.0
)
if
(
!
get_memory_usage
||
bytes
<
0.0
)
return
""
;
return
""
;
std
::
stringstream
ss
;
std
::
stringstream
ss
;
ss
<<
" "
<<
HumanReadableNumber
(
bytes
)
<<
"B peak-mem"
;
ss
<<
" "
<<
HumanReadableNumber
(
bytes
)
<<
"B peak-mem"
;
...
@@ -311,8 +304,8 @@ bool ConsoleReporter::ReportContext(const BenchmarkContextData& context) {
...
@@ -311,8 +304,8 @@ bool ConsoleReporter::ReportContext(const BenchmarkContextData& context) {
&
remainder_ms
)
<<
"
\n
"
;
&
remainder_ms
)
<<
"
\n
"
;
// Show details of CPU model, caches, TLBs etc.
// Show details of CPU model, caches, TLBs etc.
// if (!context.cpu_info.empty())
// if (!context.cpu_info.empty())
// std::cout << "CPU: " << context.cpu_info.c_str();
// std::cout << "CPU: " << context.cpu_info.c_str();
if
(
context
.
cpu_scaling_enabled
)
{
if
(
context
.
cpu_scaling_enabled
)
{
std
::
cerr
<<
"CPU scaling is enabled: Benchmark timings may be noisy.
\n
"
;
std
::
cerr
<<
"CPU scaling is enabled: Benchmark timings may be noisy.
\n
"
;
...
@@ -334,8 +327,7 @@ void ConsoleReporter::ReportRuns(const std::vector<BenchmarkRunData>& reports) {
...
@@ -334,8 +327,7 @@ void ConsoleReporter::ReportRuns(const std::vector<BenchmarkRunData>& reports) {
}
}
// We don't report aggregated data if there was a single run.
// We don't report aggregated data if there was a single run.
if
(
reports
.
size
()
<
2
)
if
(
reports
.
size
()
<
2
)
return
;
return
;
BenchmarkRunData
mean_data
;
BenchmarkRunData
mean_data
;
BenchmarkRunData
stddev_data
;
BenchmarkRunData
stddev_data
;
...
@@ -379,22 +371,21 @@ void ConsoleReporter::PrintRunData(const BenchmarkRunData& result) {
...
@@ -379,22 +371,21 @@ void ConsoleReporter::PrintRunData(const BenchmarkRunData& result) {
}
}
void
MemoryUsage
()
{
void
MemoryUsage
()
{
//if (benchmark_mc) {
//
if (benchmark_mc) {
// benchmark_mc->Reset();
// benchmark_mc->Reset();
//} else {
//} else {
get_memory_usage
=
true
;
get_memory_usage
=
true
;
//}
//}
}
}
void
UseRealTime
()
{
void
UseRealTime
()
{
use_real_time
=
true
;
}
use_real_time
=
true
;
}
void
PrintUsageAndExit
()
{
void
PrintUsageAndExit
()
{
fprintf
(
stdout
,
"benchmark [--benchmark_filter=<regex>]
\n
"
fprintf
(
stdout
,
"benchmark [--benchmark_filter=<regex>]
\n
"
" [--benchmark_iterations=<iterations>]
\n
"
" [--benchmark_iterations=<iterations>]
\n
"
" [--benchmark_min_time=<min_time>]
\n
"
" [--benchmark_min_time=<min_time>]
\n
"
//
" [--benchmark_memory_usage]\n"
//
" [--benchmark_memory_usage]\n"
" [--benchmark_repetitions=<num_repetitions>]
\n
"
" [--benchmark_repetitions=<num_repetitions>]
\n
"
" [--color_print={true|false}]
\n
"
" [--color_print={true|false}]
\n
"
" [--v=<verbosity>]
\n
"
);
" [--v=<verbosity>]
\n
"
);
...
@@ -403,21 +394,19 @@ void PrintUsageAndExit() {
...
@@ -403,21 +394,19 @@ void PrintUsageAndExit() {
void
ParseCommandLineFlags
(
int
*
argc
,
const
char
**
argv
)
{
void
ParseCommandLineFlags
(
int
*
argc
,
const
char
**
argv
)
{
for
(
int
i
=
1
;
i
<
*
argc
;
++
i
)
{
for
(
int
i
=
1
;
i
<
*
argc
;
++
i
)
{
if
(
ParseStringFlag
(
argv
[
i
],
"benchmark_filter"
,
if
(
ParseStringFlag
(
argv
[
i
],
"benchmark_filter"
,
&
FLAGS_benchmark_filter
)
||
&
FLAGS_benchmark_filter
)
||
ParseInt32Flag
(
argv
[
i
],
"benchmark_iterations"
,
ParseInt32Flag
(
argv
[
i
],
"benchmark_iterations"
,
&
FLAGS_benchmark_iterations
)
||
&
FLAGS_benchmark_iterations
)
||
ParseDoubleFlag
(
argv
[
i
],
"benchmark_min_time"
,
ParseDoubleFlag
(
argv
[
i
],
"benchmark_min_time"
,
&
FLAGS_benchmark_min_time
)
||
&
FLAGS_benchmark_min_time
)
||
// TODO(dominic)
// TODO(dominic)
// ParseBoolFlag(argv[i], "gbenchmark_memory_usage",
// ParseBoolFlag(argv[i], "gbenchmark_memory_usage",
// &FLAGS_gbenchmark_memory_usage) ||
// &FLAGS_gbenchmark_memory_usage) ||
ParseInt32Flag
(
argv
[
i
],
"benchmark_repetitions"
,
ParseInt32Flag
(
argv
[
i
],
"benchmark_repetitions"
,
&
FLAGS_benchmark_repetitions
)
||
&
FLAGS_benchmark_repetitions
)
||
ParseBoolFlag
(
argv
[
i
],
"color_print"
,
&
FLAGS_color_print
)
||
ParseBoolFlag
(
argv
[
i
],
"color_print"
,
&
FLAGS_color_print
)
||
ParseInt32Flag
(
argv
[
i
],
"v"
,
&
FLAGS_v
))
{
ParseInt32Flag
(
argv
[
i
],
"v"
,
&
FLAGS_v
))
{
for
(
int
j
=
i
;
j
!=
*
argc
;
++
j
)
for
(
int
j
=
i
;
j
!=
*
argc
;
++
j
)
argv
[
j
]
=
argv
[
j
+
1
];
argv
[
j
]
=
argv
[
j
+
1
];
--
(
*
argc
);
--
(
*
argc
);
--
i
;
--
i
;
...
@@ -431,9 +420,11 @@ void ParseCommandLineFlags(int* argc, const char** argv) {
...
@@ -431,9 +420,11 @@ void ParseCommandLineFlags(int* argc, const char** argv) {
// A clock that provides a fast mechanism to check if we're nearly done.
// A clock that provides a fast mechanism to check if we're nearly done.
class
State
::
FastClock
{
class
State
::
FastClock
{
public
:
public
:
enum
Type
{
REAL_TIME
,
CPU_TIME
};
enum
Type
{
explicit
FastClock
(
Type
type
)
REAL_TIME
,
:
type_
(
type
),
approx_time_
(
NowMicros
())
{
CPU_TIME
};
explicit
FastClock
(
Type
type
)
:
type_
(
type
),
approx_time_
(
NowMicros
())
{
sem_init
(
&
bg_done_
,
0
,
0
);
sem_init
(
&
bg_done_
,
0
,
0
);
pthread_create
(
&
bg_
,
NULL
,
&
BGThreadWrapper
,
this
);
pthread_create
(
&
bg_
,
NULL
,
&
BGThreadWrapper
,
this
);
}
}
...
@@ -449,7 +440,7 @@ class State::FastClock {
...
@@ -449,7 +440,7 @@ class State::FastClock {
inline
bool
HasReached
(
int64_t
when_micros
)
{
inline
bool
HasReached
(
int64_t
when_micros
)
{
return
std
::
atomic_load
(
&
approx_time_
)
>=
when_micros
;
return
std
::
atomic_load
(
&
approx_time_
)
>=
when_micros
;
// NOTE: this is the same as we're dealing with an int64_t
// NOTE: this is the same as we're dealing with an int64_t
//return (base::subtle::NoBarrier_Load(&approx_time_) >= when_micros);
//
return (base::subtle::NoBarrier_Load(&approx_time_) >= when_micros);
}
}
// Returns the current time in microseconds past the epoch.
// Returns the current time in microseconds past the epoch.
...
@@ -493,7 +484,7 @@ class State::FastClock {
...
@@ -493,7 +484,7 @@ class State::FastClock {
SleepForMicroseconds
(
1000
);
SleepForMicroseconds
(
1000
);
std
::
atomic_store
(
&
approx_time_
,
NowMicros
());
std
::
atomic_store
(
&
approx_time_
,
NowMicros
());
// NOTE: same code but no memory barrier. think on it.
// NOTE: same code but no memory barrier. think on it.
//base::subtle::Release_Store(&approx_time_, NowMicros());
//
base::subtle::Release_Store(&approx_time_, NowMicros());
sem_getvalue
(
&
bg_done_
,
&
done
);
sem_getvalue
(
&
bg_done_
,
&
done
);
}
while
(
done
==
0
);
}
while
(
done
==
0
);
}
}
...
@@ -523,8 +514,12 @@ namespace internal {
...
@@ -523,8 +514,12 @@ 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
{
Instance
()
Instance
()
:
bm
(
nullptr
),
threads
(
1
),
rangeXset
(
false
),
rangeX
(
kNoRange
),
:
bm
(
nullptr
),
rangeYset
(
false
),
rangeY
(
kNoRange
)
{}
threads
(
1
),
rangeXset
(
false
),
rangeX
(
kNoRange
),
rangeYset
(
false
),
rangeY
(
kNoRange
)
{}
std
::
string
name
;
std
::
string
name
;
Benchmark
*
bm
;
Benchmark
*
bm
;
...
@@ -551,14 +546,14 @@ struct State::SharedState {
...
@@ -551,14 +546,14 @@ struct State::SharedState {
std
::
string
label
;
std
::
string
label
;
explicit
SharedState
(
const
internal
::
Benchmark
::
Instance
*
b
)
explicit
SharedState
(
const
internal
::
Benchmark
::
Instance
*
b
)
:
instance
(
b
),
starting
(
0
),
stopping
(
0
),
:
instance
(
b
),
starting
(
0
),
stopping
(
0
),
threads
(
b
==
nullptr
?
1
:
b
->
threads
)
{
threads
(
b
==
nullptr
?
1
:
b
->
threads
)
{
pthread_mutex_init
(
&
mu
,
nullptr
);
pthread_mutex_init
(
&
mu
,
nullptr
);
}
}
~
SharedState
()
{
~
SharedState
()
{
pthread_mutex_destroy
(
&
mu
);
}
pthread_mutex_destroy
(
&
mu
);
}
DISALLOW_COPY_AND_ASSIGN
(
SharedState
);
DISALLOW_COPY_AND_ASSIGN
(
SharedState
);
};
};
...
@@ -567,8 +562,7 @@ namespace internal {
...
@@ -567,8 +562,7 @@ namespace internal {
Benchmark
::
Benchmark
(
const
char
*
name
,
BenchmarkFunction
f
)
Benchmark
::
Benchmark
(
const
char
*
name
,
BenchmarkFunction
f
)
:
name_
(
name
),
function_
(
f
)
{
:
name_
(
name
),
function_
(
f
)
{
mutex_lock
l
(
&
benchmark_mutex
);
mutex_lock
l
(
&
benchmark_mutex
);
if
(
families
==
nullptr
)
if
(
families
==
nullptr
)
families
=
new
std
::
vector
<
Benchmark
*>
();
families
=
new
std
::
vector
<
Benchmark
*>
();
registration_index_
=
families
->
size
();
registration_index_
=
families
->
size
();
families
->
push_back
(
this
);
families
->
push_back
(
this
);
}
}
...
@@ -578,8 +572,7 @@ Benchmark::~Benchmark() {
...
@@ -578,8 +572,7 @@ Benchmark::~Benchmark() {
CHECK
((
*
families
)[
registration_index_
]
==
this
);
CHECK
((
*
families
)[
registration_index_
]
==
this
);
(
*
families
)[
registration_index_
]
=
NULL
;
(
*
families
)[
registration_index_
]
=
NULL
;
// Shrink the vector if convenient.
// Shrink the vector if convenient.
while
(
!
families
->
empty
()
&&
families
->
back
()
==
NULL
)
while
(
!
families
->
empty
()
&&
families
->
back
()
==
NULL
)
families
->
pop_back
();
families
->
pop_back
();
}
}
Benchmark
*
Benchmark
::
Arg
(
int
x
)
{
Benchmark
*
Benchmark
::
Arg
(
int
x
)
{
...
@@ -593,8 +586,7 @@ Benchmark* Benchmark::Range(int start, int limit) {
...
@@ -593,8 +586,7 @@ Benchmark* Benchmark::Range(int start, int limit) {
AddRange
(
&
arglist
,
start
,
limit
,
kRangeMultiplier
);
AddRange
(
&
arglist
,
start
,
limit
,
kRangeMultiplier
);
mutex_lock
l
(
&
benchmark_mutex
);
mutex_lock
l
(
&
benchmark_mutex
);
for
(
size_t
i
=
0
;
i
<
arglist
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
arglist
.
size
();
++
i
)
rangeX_
.
push_back
(
arglist
[
i
]);
rangeX_
.
push_back
(
arglist
[
i
]);
return
this
;
return
this
;
}
}
...
@@ -602,8 +594,7 @@ Benchmark* Benchmark::DenseRange(int start, int limit) {
...
@@ -602,8 +594,7 @@ Benchmark* Benchmark::DenseRange(int start, int limit) {
CHECK_GE
(
start
,
0
);
CHECK_GE
(
start
,
0
);
CHECK_LE
(
start
,
limit
);
CHECK_LE
(
start
,
limit
);
mutex_lock
l
(
&
benchmark_mutex
);
mutex_lock
l
(
&
benchmark_mutex
);
for
(
int
arg
=
start
;
arg
<=
limit
;
++
arg
)
for
(
int
arg
=
start
;
arg
<=
limit
;
++
arg
)
rangeX_
.
push_back
(
arg
);
rangeX_
.
push_back
(
arg
);
return
this
;
return
this
;
}
}
...
@@ -662,14 +653,13 @@ void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
...
@@ -662,14 +653,13 @@ void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
dst
->
push_back
(
lo
);
dst
->
push_back
(
lo
);
// Now space out the benchmarks in multiples of "mult"
// Now space out the benchmarks in multiples of "mult"
for
(
int32_t
i
=
1
;
i
<
std
::
numeric_limits
<
int32_t
>::
max
()
/
mult
;
i
*=
mult
)
{
for
(
int32_t
i
=
1
;
i
<
std
::
numeric_limits
<
int32_t
>::
max
()
/
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
);
}
}
// Add "hi" (if different from "lo")
// Add "hi" (if different from "lo")
if
(
hi
!=
lo
)
if
(
hi
!=
lo
)
dst
->
push_back
(
hi
);
dst
->
push_back
(
hi
);
}
}
std
::
vector
<
Benchmark
::
Instance
>
Benchmark
::
CreateBenchmarkInstances
(
std
::
vector
<
Benchmark
::
Instance
>
Benchmark
::
CreateBenchmarkInstances
(
...
@@ -767,7 +757,8 @@ void Benchmark::MeasureOverhead() {
...
@@ -767,7 +757,8 @@ void Benchmark::MeasureOverhead() {
State
::
FastClock
clock
(
State
::
FastClock
::
CPU_TIME
);
State
::
FastClock
clock
(
State
::
FastClock
::
CPU_TIME
);
State
::
SharedState
state
(
nullptr
);
State
::
SharedState
state
(
nullptr
);
State
runner
(
&
clock
,
&
state
,
0
);
State
runner
(
&
clock
,
&
state
,
0
);
while
(
runner
.
KeepRunning
())
{}
while
(
runner
.
KeepRunning
())
{
}
overhead
=
state
.
runs
[
0
].
real_accumulated_time
/
overhead
=
state
.
runs
[
0
].
real_accumulated_time
/
static_cast
<
double
>
(
state
.
runs
[
0
].
iterations
);
static_cast
<
double
>
(
state
.
runs
[
0
].
iterations
);
#ifdef DEBUG
#ifdef DEBUG
...
@@ -796,11 +787,10 @@ void Benchmark::RunInstance(const Instance& b, BenchmarkReporter* br) {
...
@@ -796,11 +787,10 @@ void Benchmark::RunInstance(const Instance& b, BenchmarkReporter* br) {
runners
[
i
]
->
Run
();
runners
[
i
]
->
Run
();
}
}
if
(
b
.
multithreaded
())
{
if
(
b
.
multithreaded
())
{
for
(
int
i
=
0
;
i
<
b
.
threads
;
++
i
)
for
(
int
i
=
0
;
i
<
b
.
threads
;
++
i
)
runners
[
i
]
->
Wait
();
runners
[
i
]
->
Wait
();
}
}
}
}
/*
/*
double mem_usage = 0;
double mem_usage = 0;
if (get_memory_usage) {
if (get_memory_usage) {
// Measure memory usage
// Measure memory usage
...
@@ -817,12 +807,12 @@ void Benchmark::RunInstance(const Instance& b, BenchmarkReporter* br) {
...
@@ -817,12 +807,12 @@ void Benchmark::RunInstance(const Instance& b, BenchmarkReporter* br) {
mem_usage = mc.PeakHeapGrowth();
mem_usage = mc.PeakHeapGrowth();
}
}
}
}
*/
*/
running_benchmark
=
false
;
running_benchmark
=
false
;
for
(
internal
::
BenchmarkRunData
&
report
:
state
.
runs
)
{
for
(
internal
::
BenchmarkRunData
&
report
:
state
.
runs
)
{
double
seconds
=
(
use_real_time
?
report
.
real_accumulated_time
:
double
seconds
=
(
use_real_time
?
report
.
real_accumulated_time
report
.
cpu_accumulated_time
);
:
report
.
cpu_accumulated_time
);
report
.
benchmark_name
=
b
.
name
;
report
.
benchmark_name
=
b
.
name
;
report
.
report_label
=
state
.
label
;
report
.
report_label
=
state
.
label
;
report
.
bytes_per_second
=
state
.
stats
.
bytes_processed
/
seconds
;
report
.
bytes_per_second
=
state
.
stats
.
bytes_processed
/
seconds
;
...
@@ -836,18 +826,17 @@ void Benchmark::RunInstance(const Instance& b, BenchmarkReporter* br) {
...
@@ -836,18 +826,17 @@ void Benchmark::RunInstance(const Instance& b, BenchmarkReporter* br) {
// Run the specified benchmark, measure its peak memory usage, and
// Run the specified benchmark, measure its peak memory usage, and
// return the peak memory usage.
// return the peak memory usage.
double
Benchmark
::
MeasurePeakHeapMemory
(
const
Instance
&
b
)
{
double
Benchmark
::
MeasurePeakHeapMemory
(
const
Instance
&
b
)
{
if
(
!
get_memory_usage
)
if
(
!
get_memory_usage
)
return
0.0
;
return
0.0
;
double
bytes
=
0.0
;
double
bytes
=
0.0
;
/* TODO(dominich)
/* TODO(dominich)
// Should we do multi-threaded runs?
// Should we do multi-threaded runs?
const int num_threads = 1;
const int num_threads = 1;
const int num_iters = 1;
const int num_iters = 1;
{
{
// internal::MallocCounter mc(internal::MallocCounter::THIS_THREAD_ONLY);
// internal::MallocCounter mc(internal::MallocCounter::THIS_THREAD_ONLY);
running_benchmark = true;
running_benchmark = true;
timer_manager = new TimerManager(1, NULL);
timer_manager = new TimerManager(1, NULL);
// benchmark_mc = &mc;
// benchmark_mc = &mc;
timer_manager->StartTimer();
timer_manager->StartTimer();
b.Run(num_iters);
b.Run(num_iters);
...
@@ -855,8 +844,8 @@ double Benchmark::MeasurePeakHeapMemory(const Instance& b) {
...
@@ -855,8 +844,8 @@ double Benchmark::MeasurePeakHeapMemory(const Instance& b) {
running_benchmark = false;
running_benchmark = false;
delete timer_manager;
delete timer_manager;
timer_manager = NULL;
timer_manager = NULL;
// benchmark_mc = NULL;
// benchmark_mc = NULL;
// bytes = mc.PeakHeapGrowth();
// bytes = mc.PeakHeapGrowth();
}
}
*/
*/
return
bytes
;
return
bytes
;
...
@@ -876,14 +865,13 @@ State::State(FastClock* clock, SharedState* s, int t)
...
@@ -876,14 +865,13 @@ State::State(FastClock* clock, SharedState* s, int t)
start_pause_
(
0.0
),
start_pause_
(
0.0
),
pause_time_
(
0.0
),
pause_time_
(
0.0
),
total_iterations_
(
0
),
total_iterations_
(
0
),
interval_micros_
(
interval_micros_
(
static_cast
<
int64_t
>
(
kNumMicrosPerSecond
*
static_cast
<
int64_t
>
(
kNumMicrosPerSecond
*
FLAGS_benchmark_min_time
/
FLAGS_benchmark_min_time
/
FLAGS_benchmark_repetitions
)),
FLAGS_benchmark_repetitions
)),
is_continuation_
(
false
),
is_continuation_
(
false
),
stats_
(
new
ThreadStats
())
{
stats_
(
new
ThreadStats
())
{
CHECK
(
clock
!=
nullptr
);
CHECK
(
clock
!=
nullptr
);
CHECK
(
s
!=
nullptr
);
CHECK
(
s
!=
nullptr
);
}
}
bool
State
::
KeepRunning
()
{
bool
State
::
KeepRunning
()
{
...
@@ -895,24 +883,27 @@ bool State::KeepRunning() {
...
@@ -895,24 +883,27 @@ bool State::KeepRunning() {
return
true
;
return
true
;
}
}
switch
(
state_
)
{
switch
(
state_
)
{
case
STATE_INITIAL
:
return
StartRunning
();
case
STATE_INITIAL
:
case
STATE_STARTING
:
CHECK
(
false
);
return
true
;
return
StartRunning
();
case
STATE_RUNNING
:
return
FinishInterval
();
case
STATE_STARTING
:
case
STATE_STOPPING
:
return
MaybeStop
();
CHECK
(
false
);
case
STATE_STOPPED
:
CHECK
(
false
);
return
true
;
return
true
;
case
STATE_RUNNING
:
return
FinishInterval
();
case
STATE_STOPPING
:
return
MaybeStop
();
case
STATE_STOPPED
:
CHECK
(
false
);
return
true
;
}
}
CHECK
(
false
);
CHECK
(
false
);
return
false
;
return
false
;
}
}
void
State
::
PauseTiming
()
{
void
State
::
PauseTiming
()
{
start_pause_
=
walltime
::
Now
();
}
start_pause_
=
walltime
::
Now
();
}
void
State
::
ResumeTiming
()
{
void
State
::
ResumeTiming
()
{
pause_time_
+=
walltime
::
Now
()
-
start_pause_
;
}
pause_time_
+=
walltime
::
Now
()
-
start_pause_
;
}
void
State
::
SetBytesProcessed
(
int64_t
bytes
)
{
void
State
::
SetBytesProcessed
(
int64_t
bytes
)
{
CHECK_EQ
(
STATE_STOPPED
,
state_
);
CHECK_EQ
(
STATE_STOPPED
,
state_
);
...
@@ -964,8 +955,8 @@ bool State::StartRunning() {
...
@@ -964,8 +955,8 @@ bool State::StartRunning() {
}
}
if
(
last_thread
)
{
if
(
last_thread
)
{
clock_
->
InitType
(
clock_
->
InitType
(
use_real_time
?
FastClock
::
REAL_TIME
use_real_time
?
FastClock
::
REAL_TIME
:
FastClock
::
CPU_TIME
);
:
FastClock
::
CPU_TIME
);
{
{
mutex_lock
l
(
&
starting_mutex
);
mutex_lock
l
(
&
starting_mutex
);
pthread_cond_broadcast
(
&
starting_cv
);
pthread_cond_broadcast
(
&
starting_cv
);
...
@@ -1022,7 +1013,6 @@ bool State::FinishInterval() {
...
@@ -1022,7 +1013,6 @@ bool State::FinishInterval() {
const
double
accumulated_time
=
walltime
::
Now
()
-
start_time_
;
const
double
accumulated_time
=
walltime
::
Now
()
-
start_time_
;
const
double
total_overhead
=
overhead
*
iterations_
;
const
double
total_overhead
=
overhead
*
iterations_
;
//const double total_overhead = 0.0;
CHECK_LT
(
pause_time_
,
accumulated_time
);
CHECK_LT
(
pause_time_
,
accumulated_time
);
CHECK_LT
(
pause_time_
+
total_overhead
,
accumulated_time
);
CHECK_LT
(
pause_time_
+
total_overhead
,
accumulated_time
);
data
.
real_accumulated_time
=
data
.
real_accumulated_time
=
...
@@ -1046,8 +1036,7 @@ bool State::FinishInterval() {
...
@@ -1046,8 +1036,7 @@ bool State::FinishInterval() {
is_continuation_
=
keep_going
;
is_continuation_
=
keep_going
;
}
else
{
}
else
{
// If this is a repetition, run another interval as a new data point.
// If this is a repetition, run another interval as a new data point.
keep_going
=
keep_going
=
shared_
->
runs
.
size
()
<
shared_
->
runs
.
size
()
<
static_cast
<
size_t
>
(
FLAGS_benchmark_repetitions
);
static_cast
<
size_t
>
(
FLAGS_benchmark_repetitions
);
is_continuation_
=
!
keep_going
;
is_continuation_
=
!
keep_going
;
}
}
...
@@ -1065,8 +1054,7 @@ bool State::FinishInterval() {
...
@@ -1065,8 +1054,7 @@ bool State::FinishInterval() {
}
}
}
}
if
(
state_
==
STATE_RUNNING
)
if
(
state_
==
STATE_RUNNING
)
NewInterval
();
NewInterval
();
return
keep_going
;
return
keep_going
;
}
}
...
@@ -1093,9 +1081,7 @@ void State::RunAsThread() {
...
@@ -1093,9 +1081,7 @@ void State::RunAsThread() {
CHECK_EQ
(
0
,
pthread_create
(
&
thread_
,
nullptr
,
&
State
::
RunWrapper
,
this
));
CHECK_EQ
(
0
,
pthread_create
(
&
thread_
,
nullptr
,
&
State
::
RunWrapper
,
this
));
}
}
void
State
::
Wait
()
{
void
State
::
Wait
()
{
CHECK_EQ
(
0
,
pthread_join
(
thread_
,
nullptr
));
}
CHECK_EQ
(
0
,
pthread_join
(
thread_
,
nullptr
));
}
// static
// static
void
*
State
::
RunWrapper
(
void
*
arg
)
{
void
*
State
::
RunWrapper
(
void
*
arg
)
{
...
@@ -1121,17 +1107,16 @@ void RunMatchingBenchmarks(const std::string& spec,
...
@@ -1121,17 +1107,16 @@ void RunMatchingBenchmarks(const std::string& spec,
for
(
const
internal
::
Benchmark
::
Instance
&
benchmark
:
benchmarks
)
{
for
(
const
internal
::
Benchmark
::
Instance
&
benchmark
:
benchmarks
)
{
// Add width for _stddev and threads:XX
// Add width for _stddev and threads:XX
if
(
benchmark
.
threads
>
1
&&
FLAGS_benchmark_repetitions
>
1
)
{
if
(
benchmark
.
threads
>
1
&&
FLAGS_benchmark_repetitions
>
1
)
{
name_field_width
=
std
::
max
<
int
>
(
name_field_width
,
name_field_width
=
benchmark
.
name
.
size
()
+
17
);
std
::
max
<
int
>
(
name_field_width
,
benchmark
.
name
.
size
()
+
17
);
}
else
if
(
benchmark
.
threads
>
1
)
{
}
else
if
(
benchmark
.
threads
>
1
)
{
name_field_width
=
std
::
max
<
int
>
(
name_field_width
,
name_field_width
=
benchmark
.
name
.
size
()
+
10
);
std
::
max
<
int
>
(
name_field_width
,
benchmark
.
name
.
size
()
+
10
);
}
else
if
(
FLAGS_benchmark_repetitions
>
1
)
{
}
else
if
(
FLAGS_benchmark_repetitions
>
1
)
{
name_field_width
=
std
::
max
<
int
>
(
name_field_width
,
name_field_width
=
benchmark
.
name
.
size
()
+
7
);
std
::
max
<
int
>
(
name_field_width
,
benchmark
.
name
.
size
()
+
7
);
}
else
{
}
else
{
name_field_width
=
std
::
max
<
int
>
(
name_field_width
,
name_field_width
=
std
::
max
<
int
>
(
name_field_width
,
benchmark
.
name
.
size
());
benchmark
.
name
.
size
());
}
}
}
}
...
@@ -1139,7 +1124,7 @@ void RunMatchingBenchmarks(const std::string& spec,
...
@@ -1139,7 +1124,7 @@ void RunMatchingBenchmarks(const std::string& spec,
BenchmarkContextData
context
;
BenchmarkContextData
context
;
context
.
num_cpus
=
NumCPUs
();
context
.
num_cpus
=
NumCPUs
();
context
.
mhz_per_cpu
=
CyclesPerSecond
()
/
1000000.0
f
;
context
.
mhz_per_cpu
=
CyclesPerSecond
()
/
1000000.0
f
;
// context.cpu_info = base::CompactCPUIDInfoString();
// context.cpu_info = base::CompactCPUIDInfoString();
context
.
cpu_scaling_enabled
=
CpuScalingEnabled
();
context
.
cpu_scaling_enabled
=
CpuScalingEnabled
();
context
.
name_field_width
=
name_field_width
;
context
.
name_field_width
=
name_field_width
;
...
@@ -1155,7 +1140,7 @@ void FindMatchingBenchmarkNames(const std::string& spec,
...
@@ -1155,7 +1140,7 @@ void FindMatchingBenchmarkNames(const std::string& spec,
std
::
vector
<
internal
::
Benchmark
::
Instance
>
benchmarks
;
std
::
vector
<
internal
::
Benchmark
::
Instance
>
benchmarks
;
internal
::
Benchmark
::
FindBenchmarks
(
spec
,
&
benchmarks
);
internal
::
Benchmark
::
FindBenchmarks
(
spec
,
&
benchmarks
);
std
::
transform
(
benchmarks
.
begin
(),
benchmarks
.
end
(),
benchmark_names
->
begin
(),
std
::
transform
(
benchmarks
.
begin
(),
benchmarks
.
end
(),
benchmark_names
->
begin
(),
[]
(
const
internal
::
Benchmark
::
Instance
&
b
)
{
return
b
.
name
;
}
);
[]
(
const
internal
::
Benchmark
::
Instance
&
b
)
{
return
b
.
name
;
}
);
}
}
}
// end namespace internal
}
// end namespace internal
...
@@ -1172,7 +1157,6 @@ void RunSpecifiedBenchmarks() {
...
@@ -1172,7 +1157,6 @@ void RunSpecifiedBenchmarks() {
}
}
void
Initialize
(
int
*
argc
,
const
char
**
argv
)
{
void
Initialize
(
int
*
argc
,
const
char
**
argv
)
{
//AtomicOps_Internalx86CPUFeaturesInit();
pthread_mutex_init
(
&
benchmark_mutex
,
nullptr
);
pthread_mutex_init
(
&
benchmark_mutex
,
nullptr
);
pthread_mutex_init
(
&
starting_mutex
,
nullptr
);
pthread_mutex_init
(
&
starting_mutex
,
nullptr
);
pthread_cond_init
(
&
starting_cv
,
nullptr
);
pthread_cond_init
(
&
starting_cv
,
nullptr
);
...
...
src/colorprint.cc
View file @
4ce184d8
...
@@ -17,25 +17,40 @@ typedef const char* PlatformColorCode;
...
@@ -17,25 +17,40 @@ typedef const char* PlatformColorCode;
PlatformColorCode
GetPlatformColorCode
(
LogColor
color
)
{
PlatformColorCode
GetPlatformColorCode
(
LogColor
color
)
{
#ifdef OS_WINDOWS
#ifdef OS_WINDOWS
switch
(
color
)
{
switch
(
color
)
{
case
COLOR_RED
:
return
FOREGROUND_RED
;
case
COLOR_RED
:
case
COLOR_GREEN
:
return
FOREGROUND_GREEN
;
return
FOREGROUND_RED
;
case
COLOR_YELLOW
:
return
FOREGROUND_RED
|
FOREGROUND_GREEN
;
case
COLOR_GREEN
:
case
COLOR_BLUE
:
return
FOREGROUND_BLUE
;
return
FOREGROUND_GREEN
;
case
COLOR_MAGENTA
:
return
FOREGROUND_BLUE
|
FOREGROUND_RED
;
case
COLOR_YELLOW
:
case
COLOR_CYAN
:
return
FOREGROUND_BLUE
|
FOREGROUND_GREEN
;
return
FOREGROUND_RED
|
FOREGROUND_GREEN
;
case
COLOR_BLUE
:
return
FOREGROUND_BLUE
;
case
COLOR_MAGENTA
:
return
FOREGROUND_BLUE
|
FOREGROUND_RED
;
case
COLOR_CYAN
:
return
FOREGROUND_BLUE
|
FOREGROUND_GREEN
;
case
COLOR_WHITE
:
// fall through to default
case
COLOR_WHITE
:
// fall through to default
default:
return
0
;
default:
return
0
;
}
}
#else
#else
switch
(
color
)
{
switch
(
color
)
{
case
COLOR_RED
:
return
"1"
;
case
COLOR_RED
:
case
COLOR_GREEN
:
return
"2"
;
return
"1"
;
case
COLOR_YELLOW
:
return
"3"
;
case
COLOR_GREEN
:
case
COLOR_BLUE
:
return
"4"
;
return
"2"
;
case
COLOR_MAGENTA
:
return
"5"
;
case
COLOR_YELLOW
:
case
COLOR_CYAN
:
return
"6"
;
return
"3"
;
case
COLOR_WHITE
:
return
"7"
;
case
COLOR_BLUE
:
default:
return
NULL
;
return
"4"
;
case
COLOR_MAGENTA
:
return
"5"
;
case
COLOR_CYAN
:
return
"6"
;
case
COLOR_WHITE
:
return
"7"
;
default:
return
NULL
;
};
};
#endif
#endif
}
}
...
@@ -72,8 +87,7 @@ void ColorPrintf(LogColor color, const char* fmt, ...) {
...
@@ -72,8 +87,7 @@ void ColorPrintf(LogColor color, const char* fmt, ...) {
SetConsoleTextAttribute
(
stdout_handle
,
old_color_attrs
);
SetConsoleTextAttribute
(
stdout_handle
,
old_color_attrs
);
#else
#else
const
char
*
color_code
=
GetPlatformColorCode
(
color
);
const
char
*
color_code
=
GetPlatformColorCode
(
color
);
if
(
color_code
)
if
(
color_code
)
fprintf
(
stdout
,
"
\033
[0;3%sm"
,
color_code
);
fprintf
(
stdout
,
"
\033
[0;3%sm"
,
color_code
);
vprintf
(
fmt
,
args
);
vprintf
(
fmt
,
args
);
printf
(
"
\033
[m"
);
// Resets the terminal to default.
printf
(
"
\033
[m"
);
// Resets the terminal to default.
#endif
#endif
...
...
src/commandlineflags.cc
View file @
4ce184d8
...
@@ -60,7 +60,6 @@ bool ParseDouble(const std::string& src_text, const char* str, double* value) {
...
@@ -60,7 +60,6 @@ bool ParseDouble(const std::string& src_text, const char* str, double* value) {
return
true
;
return
true
;
}
}
inline
const
char
*
GetEnv
(
const
char
*
name
)
{
inline
const
char
*
GetEnv
(
const
char
*
name
)
{
#if GTEST_OS_WINDOWS_MOBILE
#if GTEST_OS_WINDOWS_MOBILE
// We are on Windows CE, which has no environment variables.
// We are on Windows CE, which has no environment variables.
...
@@ -95,8 +94,7 @@ static std::string FlagToEnvVar(const char* flag) {
...
@@ -95,8 +94,7 @@ 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
==
NULL
?
return
string_value
==
NULL
?
default_value
:
strcmp
(
string_value
,
"0"
)
!=
0
;
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
...
@@ -111,8 +109,8 @@ int32_t Int32FromEnv(const char* flag, int32_t default_value) {
...
@@ -111,8 +109,8 @@ int32_t Int32FromEnv(const char* flag, int32_t default_value) {
}
}
int32_t
result
=
default_value
;
int32_t
result
=
default_value
;
if
(
!
ParseInt32
(
std
::
string
(
"Environment variable "
)
+
env_var
,
if
(
!
ParseInt32
(
std
::
string
(
"Environment variable "
)
+
env_var
,
string_value
,
string_value
,
&
result
))
{
&
result
))
{
std
::
cout
<<
"The default value "
<<
default_value
<<
" is used.
\n
"
;
std
::
cout
<<
"The default value "
<<
default_value
<<
" is used.
\n
"
;
return
default_value
;
return
default_value
;
}
}
...
@@ -133,8 +131,7 @@ const char* StringFromEnv(const char* flag, const char* default_value) {
...
@@ -133,8 +131,7 @@ const char* StringFromEnv(const char* flag, const char* default_value) {
// part can be omitted.
// part can be omitted.
//
//
// Returns the value of the flag, or NULL if the parsing failed.
// Returns the value of the flag, or NULL if the parsing failed.
const
char
*
ParseFlagValue
(
const
char
*
str
,
const
char
*
ParseFlagValue
(
const
char
*
str
,
const
char
*
flag
,
const
char
*
flag
,
bool
def_optional
)
{
bool
def_optional
)
{
// str and flag must not be NULL.
// str and flag must not be NULL.
if
(
str
==
NULL
||
flag
==
NULL
)
return
NULL
;
if
(
str
==
NULL
||
flag
==
NULL
)
return
NULL
;
...
@@ -148,8 +145,7 @@ const char* ParseFlagValue(const char* str,
...
@@ -148,8 +145,7 @@ const char* ParseFlagValue(const char* str,
const
char
*
flag_end
=
str
+
flag_len
;
const
char
*
flag_end
=
str
+
flag_len
;
// When def_optional is true, it's OK to not have a "=value" part.
// When def_optional is true, it's OK to not have a "=value" part.
if
(
def_optional
&&
(
flag_end
[
0
]
==
'\0'
))
if
(
def_optional
&&
(
flag_end
[
0
]
==
'\0'
))
return
flag_end
;
return
flag_end
;
// If def_optional is true and there are more characters after the
// If def_optional is true and there are more characters after the
// flag name, or if def_optional is false, there must be a '=' after
// flag name, or if def_optional is false, there must be a '=' after
...
@@ -180,8 +176,8 @@ bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) {
...
@@ -180,8 +176,8 @@ bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) {
if
(
value_str
==
NULL
)
return
false
;
if
(
value_str
==
NULL
)
return
false
;
// Sets *value to the value of the flag.
// Sets *value to the value of the flag.
return
ParseInt32
(
std
::
string
(
"The value of flag --"
)
+
flag
,
return
ParseInt32
(
std
::
string
(
"The value of flag --"
)
+
flag
,
value_str
,
value
_str
,
value
);
value
);
}
}
bool
ParseDoubleFlag
(
const
char
*
str
,
const
char
*
flag
,
double
*
value
)
{
bool
ParseDoubleFlag
(
const
char
*
str
,
const
char
*
flag
,
double
*
value
)
{
...
@@ -192,8 +188,8 @@ bool ParseDoubleFlag(const char* str, const char* flag, double* value) {
...
@@ -192,8 +188,8 @@ bool ParseDoubleFlag(const char* str, const char* flag, double* value) {
if
(
value_str
==
NULL
)
return
false
;
if
(
value_str
==
NULL
)
return
false
;
// Sets *value to the value of the flag.
// Sets *value to the value of the flag.
return
ParseDouble
(
std
::
string
(
"The value of flag --"
)
+
flag
,
return
ParseDouble
(
std
::
string
(
"The value of flag --"
)
+
flag
,
value_str
,
value
_str
,
value
);
value
);
}
}
bool
ParseStringFlag
(
const
char
*
str
,
const
char
*
flag
,
std
::
string
*
value
)
{
bool
ParseStringFlag
(
const
char
*
str
,
const
char
*
flag
,
std
::
string
*
value
)
{
...
...
src/commandlineflags.h
View file @
4ce184d8
src/cycleclock.h
View file @
4ce184d8
...
@@ -24,7 +24,7 @@
...
@@ -24,7 +24,7 @@
#include <stdint.h>
#include <stdint.h>
#if defined(OS_MACOSX)
#if defined(OS_MACOSX)
#
include <mach/mach_time.h>
#include <mach/mach_time.h>
#endif
#endif
// For MSVC, we want to use '_asm rdtsc' when possible (since it works
// For MSVC, we want to use '_asm rdtsc' when possible (since it works
// with even ancient MSVC compilers), and when not possible the
// with even ancient MSVC compilers), and when not possible the
...
@@ -48,8 +48,8 @@ namespace benchmark {
...
@@ -48,8 +48,8 @@ namespace benchmark {
// with modifications by m3b. See also
// with modifications by m3b. See also
// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h
// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h
namespace
cycleclock
{
namespace
cycleclock
{
// This should return the number of cycles since power-on. Thread-safe.
// This should return the number of cycles since power-on. Thread-safe.
inline
ATTRIBUTE_ALWAYS_INLINE
int64_t
Now
()
{
inline
ATTRIBUTE_ALWAYS_INLINE
int64_t
Now
()
{
#if defined(OS_MACOSX)
#if defined(OS_MACOSX)
// this goes at the top because we need ALL Macs, regardless of
// this goes at the top because we need ALL Macs, regardless of
// architecture, to return the number of "mach time units" that
// architecture, to return the number of "mach time units" that
...
@@ -63,29 +63,29 @@ namespace cycleclock {
...
@@ -63,29 +63,29 @@ namespace cycleclock {
return
mach_absolute_time
();
return
mach_absolute_time
();
#elif defined(__i386__)
#elif defined(__i386__)
int64_t
ret
;
int64_t
ret
;
__asm__
volatile
(
"rdtsc"
:
"=A"
(
ret
)
);
__asm__
volatile
(
"rdtsc"
:
"=A"
(
ret
)
);
return
ret
;
return
ret
;
#elif defined(__x86_64__) || defined(__amd64__)
#elif defined(__x86_64__) || defined(__amd64__)
uint64_t
low
,
high
;
uint64_t
low
,
high
;
__asm__
volatile
(
"rdtsc"
:
"=a"
(
low
),
"=d"
(
high
));
__asm__
volatile
(
"rdtsc"
:
"=a"
(
low
),
"=d"
(
high
));
return
(
high
<<
32
)
|
low
;
return
(
high
<<
32
)
|
low
;
#elif defined(__powerpc__) || defined(__ppc__)
#elif defined(__powerpc__) || defined(__ppc__)
// This returns a time-base, which is not always precisely a cycle-count.
// This returns a time-base, which is not always precisely a cycle-count.
int64_t
tbl
,
tbu0
,
tbu1
;
int64_t
tbl
,
tbu0
,
tbu1
;
asm
(
"mftbu %0"
:
"=r"
(
tbu0
));
asm
(
"mftbu %0"
:
"=r"
(
tbu0
));
asm
(
"mftb %0"
:
"=r"
(
tbl
));
asm
(
"mftb %0"
:
"=r"
(
tbl
));
asm
(
"mftbu %0"
:
"=r"
(
tbu1
));
asm
(
"mftbu %0"
:
"=r"
(
tbu1
));
tbl
&=
-
static_cast
<
int64
>
(
tbu0
==
tbu1
);
tbl
&=
-
static_cast
<
int64
>
(
tbu0
==
tbu1
);
// high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage)
// high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage)
return
(
tbu1
<<
32
)
|
tbl
;
return
(
tbu1
<<
32
)
|
tbl
;
#elif defined(__sparc__)
#elif defined(__sparc__)
int64_t
tick
;
int64_t
tick
;
asm
(
".byte 0x83, 0x41, 0x00, 0x00"
);
asm
(
".byte 0x83, 0x41, 0x00, 0x00"
);
asm
(
"mov %%g1, %0"
:
"=r"
(
tick
));
asm
(
"mov %%g1, %0"
:
"=r"
(
tick
));
return
tick
;
return
tick
;
#elif defined(__ia64__)
#elif defined(__ia64__)
int64_t
itc
;
int64_t
itc
;
asm
(
"mov %0 = ar.itc"
:
"=r"
(
itc
));
asm
(
"mov %0 = ar.itc"
:
"=r"
(
itc
));
return
itc
;
return
itc
;
#elif defined(COMPILER_MSVC) && defined(_M_IX86)
#elif defined(COMPILER_MSVC) && defined(_M_IX86)
// Older MSVC compilers (like 7.x) don't seem to support the
// Older MSVC compilers (like 7.x) don't seem to support the
...
@@ -101,11 +101,11 @@ namespace cycleclock {
...
@@ -101,11 +101,11 @@ namespace cycleclock {
uint32_t
pmuseren
;
uint32_t
pmuseren
;
uint32_t
pmcntenset
;
uint32_t
pmcntenset
;
// Read the user mode perf monitor counter access permissions.
// Read the user mode perf monitor counter access permissions.
asm
(
"mrc p15, 0, %0, c9, c14, 0"
:
"=r"
(
pmuseren
));
asm
(
"mrc p15, 0, %0, c9, c14, 0"
:
"=r"
(
pmuseren
));
if
(
pmuseren
&
1
)
{
// Allows reading perfmon counters for user mode code.
if
(
pmuseren
&
1
)
{
// Allows reading perfmon counters for user mode code.
asm
(
"mrc p15, 0, %0, c9, c12, 1"
:
"=r"
(
pmcntenset
));
asm
(
"mrc p15, 0, %0, c9, c12, 1"
:
"=r"
(
pmcntenset
));
if
(
pmcntenset
&
0x80000000ul
)
{
// Is it counting?
if
(
pmcntenset
&
0x80000000ul
)
{
// Is it counting?
asm
(
"mrc p15, 0, %0, c9, c13, 0"
:
"=r"
(
pmccntr
));
asm
(
"mrc p15, 0, %0, c9, c13, 0"
:
"=r"
(
pmccntr
));
// The counter is set up to count every 64th cycle
// The counter is set up to count every 64th cycle
return
static_cast
<
int64
>
(
pmccntr
)
*
64
;
// Should optimize to << 6
return
static_cast
<
int64
>
(
pmccntr
)
*
64
;
// Should optimize to << 6
}
}
...
@@ -126,7 +126,7 @@ namespace cycleclock {
...
@@ -126,7 +126,7 @@ namespace cycleclock {
// a fast implementation and use generic version if nothing better is available.
// a fast implementation and use generic version if nothing better is available.
#error You need to define CycleTimer for your OS and CPU
#error You need to define CycleTimer for your OS and CPU
#endif
#endif
}
}
}
// end namespace cycleclock
}
// end namespace cycleclock
}
// end namespace benchmark
}
// end namespace benchmark
...
...
src/mutex_lock.h
View file @
4ce184d8
...
@@ -10,9 +10,7 @@ class mutex_lock {
...
@@ -10,9 +10,7 @@ class mutex_lock {
pthread_mutex_lock
(
mu_
);
pthread_mutex_lock
(
mu_
);
}
}
~
mutex_lock
()
{
~
mutex_lock
()
{
pthread_mutex_unlock
(
mu_
);
}
pthread_mutex_unlock
(
mu_
);
}
private
:
private
:
pthread_mutex_t
*
mu_
;
pthread_mutex_t
*
mu_
;
...
...
src/sleep.cc
View file @
4ce184d8
...
@@ -6,9 +6,7 @@
...
@@ -6,9 +6,7 @@
namespace
benchmark
{
namespace
benchmark
{
#ifdef OS_WINDOWS
#ifdef OS_WINDOWS
// Window's _sleep takes milliseconds argument.
// Window's _sleep takes milliseconds argument.
void
SleepForMilliseconds
(
int
milliseconds
)
{
void
SleepForMilliseconds
(
int
milliseconds
)
{
_sleep
(
milliseconds
);
}
_sleep
(
milliseconds
);
}
void
SleepForSeconds
(
double
seconds
)
{
void
SleepForSeconds
(
double
seconds
)
{
SleepForMilliseconds
(
static_cast
<
int
>
(
kNumMillisPerSecond
*
seconds
));
SleepForMilliseconds
(
static_cast
<
int
>
(
kNumMillisPerSecond
*
seconds
));
}
}
...
...
src/stat.h
View file @
4ce184d8
...
@@ -17,22 +17,19 @@ typedef Stat1<double, double> Stat1_d;
...
@@ -17,22 +17,19 @@ typedef Stat1<double, double> Stat1_d;
typedef
Stat1MinMax
<
float
,
float
>
Stat1MinMax_f
;
typedef
Stat1MinMax
<
float
,
float
>
Stat1MinMax_f
;
typedef
Stat1MinMax
<
double
,
double
>
Stat1MinMax_d
;
typedef
Stat1MinMax
<
double
,
double
>
Stat1MinMax_d
;
template
<
typename
VType
>
class
Vector2
;
template
<
typename
VType
>
template
<
typename
VType
>
class
Vector3
;
class
Vector2
;
template
<
typename
VType
>
class
Vector4
;
template
<
typename
VType
>
class
Vector3
;
template
<
typename
VType
>
class
Vector4
;
template
<
typename
VType
,
typename
NumType
>
template
<
typename
VType
,
typename
NumType
>
class
Stat1
{
class
Stat1
{
public
:
public
:
typedef
Stat1
<
VType
,
NumType
>
Self
;
typedef
Stat1
<
VType
,
NumType
>
Self
;
Stat1
()
{
Stat1
()
{
Clear
();
}
Clear
();
}
void
Clear
()
{
numsamples_
=
NumType
();
sum_squares_
=
sum_
=
VType
();
}
// Create a sample of value dat and weight 1
// Create a sample of value dat and weight 1
explicit
Stat1
(
const
VType
&
dat
)
{
explicit
Stat1
(
const
VType
&
dat
)
{
sum_
=
dat
;
sum_
=
dat
;
...
@@ -43,7 +40,7 @@ class Stat1 {
...
@@ -43,7 +40,7 @@ class Stat1 {
// and end(excluded)
// and end(excluded)
explicit
Stat1
(
const
VType
*
begin
,
const
VType
*
end
)
{
explicit
Stat1
(
const
VType
*
begin
,
const
VType
*
end
)
{
Clear
();
Clear
();
for
(
const
VType
*
item
=
begin
;
item
<
end
;
++
item
)
{
for
(
const
VType
*
item
=
begin
;
item
<
end
;
++
item
)
{
(
*
this
)
+=
Stat1
(
*
item
);
(
*
this
)
+=
Stat1
(
*
item
);
}
}
}
}
...
@@ -60,58 +57,60 @@ class Stat1 {
...
@@ -60,58 +57,60 @@ class Stat1 {
numsamples_
=
stat
.
numsamples_
;
numsamples_
=
stat
.
numsamples_
;
}
}
inline
Self
&
operator
=
(
const
Self
&
stat
)
{
void
Clear
()
{
numsamples_
=
NumType
();
sum_squares_
=
sum_
=
VType
();
}
Self
&
operator
=
(
const
Self
&
stat
)
{
sum_
=
stat
.
sum_
;
sum_
=
stat
.
sum_
;
sum_squares_
=
stat
.
sum_squares_
;
sum_squares_
=
stat
.
sum_squares_
;
numsamples_
=
stat
.
numsamples_
;
numsamples_
=
stat
.
numsamples_
;
return
(
*
this
);
return
(
*
this
);
}
}
// Merge statistics from two sample sets.
// Merge statistics from two sample sets.
inline
Self
&
operator
+=
(
const
Self
&
stat
)
{
Self
&
operator
+=
(
const
Self
&
stat
)
{
sum_
+=
stat
.
sum_
;
sum_
+=
stat
.
sum_
;
sum_squares_
+=
stat
.
sum_squares_
;
sum_squares_
+=
stat
.
sum_squares_
;
numsamples_
+=
stat
.
numsamples_
;
numsamples_
+=
stat
.
numsamples_
;
return
(
*
this
);
return
(
*
this
);
}
}
// The operation opposite to +=
// The operation opposite to +=
inline
Self
&
operator
-=
(
const
Self
&
stat
)
{
Self
&
operator
-=
(
const
Self
&
stat
)
{
sum_
-=
stat
.
sum_
;
sum_
-=
stat
.
sum_
;
sum_squares_
-=
stat
.
sum_squares_
;
sum_squares_
-=
stat
.
sum_squares_
;
numsamples_
-=
stat
.
numsamples_
;
numsamples_
-=
stat
.
numsamples_
;
return
(
*
this
);
return
(
*
this
);
}
}
// Multiply the weight of the set of samples by a factor k
// Multiply the weight of the set of samples by a factor k
inline
Self
&
operator
*=
(
const
VType
&
k
)
{
Self
&
operator
*=
(
const
VType
&
k
)
{
sum_
*=
k
;
sum_
*=
k
;
sum_squares_
*=
k
;
sum_squares_
*=
k
;
numsamples_
*=
k
;
numsamples_
*=
k
;
return
(
*
this
);
return
(
*
this
);
}
}
// Merge statistics from two sample sets.
// Merge statistics from two sample sets.
inline
Self
operator
+
(
const
Self
&
stat
)
const
{
Self
operator
+
(
const
Self
&
stat
)
const
{
return
Self
(
*
this
)
+=
stat
;
}
return
Self
(
*
this
)
+=
stat
;
}
// The operation opposite to +
// The operation opposite to +
inline
Self
operator
-
(
const
Self
&
stat
)
const
{
Self
operator
-
(
const
Self
&
stat
)
const
{
return
Self
(
*
this
)
-=
stat
;
}
return
Self
(
*
this
)
-=
stat
;
}
// Multiply the weight of the set of samples by a factor k
// Multiply the weight of the set of samples by a factor k
inline
Self
operator
*
(
const
VType
&
k
)
const
{
Self
operator
*
(
const
VType
&
k
)
const
{
return
Self
(
*
this
)
*=
k
;
}
return
Self
(
*
this
)
*=
k
;
}
// Return the total weight of this sample set
// Return the total weight of this sample set
NumType
NumSamples
()
const
{
NumType
numSamples
()
const
{
return
numsamples_
;
}
return
numsamples_
;
}
// Return the sum of this sample set
// Return the sum of this sample set
VType
Sum
()
const
{
VType
sum
()
const
{
return
sum_
;
}
return
sum_
;
}
// Return the mean of this sample set
// Return the mean of this sample set
VType
Mean
()
const
{
VType
Mean
()
const
{
if
(
numsamples_
==
0
)
return
VType
();
if
(
numsamples_
==
0
)
return
VType
();
return
sum_
*
(
1
.
0
/
numsamples_
);
return
sum_
*
(
1
.
0
/
numsamples_
);
}
}
// Return the mean of this sample set and compute the standard deviation at
// Return the mean of this sample set and compute the standard deviation at
// the same time.
// the same time.
VType
Mean
(
VType
*
stddev
)
const
{
VType
Mean
(
VType
*
stddev
)
const
{
...
@@ -123,6 +122,7 @@ class Stat1 {
...
@@ -123,6 +122,7 @@ class Stat1 {
}
}
return
mean
;
return
mean
;
}
}
// Return the standard deviation of the sample set
// Return the standard deviation of the sample set
VType
StdDev
()
const
{
VType
StdDev
()
const
{
if
(
numsamples_
==
0
)
return
VType
();
if
(
numsamples_
==
0
)
return
VType
();
...
@@ -130,6 +130,7 @@ class Stat1 {
...
@@ -130,6 +130,7 @@ class Stat1 {
VType
avg_squares
=
sum_squares_
*
(
1
.
0
/
numsamples_
);
VType
avg_squares
=
sum_squares_
*
(
1
.
0
/
numsamples_
);
return
Sqrt
(
avg_squares
-
Sqr
(
mean
));
return
Sqrt
(
avg_squares
-
Sqr
(
mean
));
}
}
private
:
private
:
// 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
...
@@ -141,17 +142,18 @@ class Stat1 {
...
@@ -141,17 +142,18 @@ class Stat1 {
// Template function used to square a number.
// Template function used to square a number.
// For a vector we square all components
// For a vector we square all components
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
SType
Sqr
(
const
SType
&
dat
)
{
static
inline
SType
Sqr
(
const
SType
&
dat
)
{
return
dat
*
dat
;
}
return
dat
*
dat
;
}
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
Vector2
<
SType
>
Sqr
(
const
Vector2
<
SType
>
&
dat
)
{
static
inline
Vector2
<
SType
>
Sqr
(
const
Vector2
<
SType
>
&
dat
)
{
return
dat
.
MulComponents
(
dat
);
return
dat
.
MulComponents
(
dat
);
}
}
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
Vector3
<
SType
>
Sqr
(
const
Vector3
<
SType
>
&
dat
)
{
static
inline
Vector3
<
SType
>
Sqr
(
const
Vector3
<
SType
>
&
dat
)
{
return
dat
.
MulComponents
(
dat
);
return
dat
.
MulComponents
(
dat
);
}
}
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
Vector4
<
SType
>
Sqr
(
const
Vector4
<
SType
>
&
dat
)
{
static
inline
Vector4
<
SType
>
Sqr
(
const
Vector4
<
SType
>
&
dat
)
{
return
dat
.
MulComponents
(
dat
);
return
dat
.
MulComponents
(
dat
);
...
@@ -162,20 +164,22 @@ class Stat1 {
...
@@ -162,20 +164,22 @@ class Stat1 {
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
SType
Sqrt
(
const
SType
&
dat
)
{
static
inline
SType
Sqrt
(
const
SType
&
dat
)
{
// Avoid NaN due to imprecision in the calculations
// Avoid NaN due to imprecision in the calculations
if
(
dat
<
0
)
if
(
dat
<
0
)
return
0
;
return
0
;
return
sqrt
(
dat
);
return
sqrt
(
dat
);
}
}
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
Vector2
<
SType
>
Sqrt
(
const
Vector2
<
SType
>
&
dat
)
{
static
inline
Vector2
<
SType
>
Sqrt
(
const
Vector2
<
SType
>
&
dat
)
{
// Avoid NaN due to imprecision in the calculations
// Avoid NaN due to imprecision in the calculations
return
Max
(
dat
,
Vector2
<
SType
>
()).
Sqrt
();
return
Max
(
dat
,
Vector2
<
SType
>
()).
Sqrt
();
}
}
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
Vector3
<
SType
>
Sqrt
(
const
Vector3
<
SType
>
&
dat
)
{
static
inline
Vector3
<
SType
>
Sqrt
(
const
Vector3
<
SType
>
&
dat
)
{
// Avoid NaN due to imprecision in the calculations
// Avoid NaN due to imprecision in the calculations
return
Max
(
dat
,
Vector3
<
SType
>
()).
Sqrt
();
return
Max
(
dat
,
Vector3
<
SType
>
()).
Sqrt
();
}
}
template
<
typename
SType
>
template
<
typename
SType
>
static
inline
Vector4
<
SType
>
Sqrt
(
const
Vector4
<
SType
>
&
dat
)
{
static
inline
Vector4
<
SType
>
Sqrt
(
const
Vector4
<
SType
>
&
dat
)
{
// Avoid NaN due to imprecision in the calculations
// Avoid NaN due to imprecision in the calculations
...
@@ -185,15 +189,12 @@ class Stat1 {
...
@@ -185,15 +189,12 @@ class Stat1 {
// Useful printing function
// Useful printing function
template
<
typename
VType
,
typename
NumType
>
template
<
typename
VType
,
typename
NumType
>
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
const
Stat1
<
VType
,
NumType
>&
s
)
{
const
Stat1
<
VType
,
NumType
>&
s
)
{
out
<<
"{ avg = "
<<
s
.
Mean
()
<<
" std = "
<<
s
.
StdDev
()
out
<<
"{ avg = "
<<
s
.
Mean
()
<<
" std = "
<<
s
.
StdDev
()
<<
" nsamples = "
<<
s
.
NumSamples
()
<<
"}"
;
<<
" nsamples = "
<<
s
.
NumSamples
()
<<
"}"
;
return
out
;
return
out
;
}
}
// Stat1MinMax: same as Stat1, but it also
// Stat1MinMax: same as Stat1, but it also
// keeps the Min and Max values; the "-"
// keeps the Min and Max values; the "-"
// operator is disabled because it cannot be implemented
// operator is disabled because it cannot be implemented
...
@@ -203,19 +204,7 @@ class Stat1MinMax : public Stat1<VType, NumType> {
...
@@ -203,19 +204,7 @@ class Stat1MinMax : public Stat1<VType, NumType> {
public
:
public
:
typedef
Stat1MinMax
<
VType
,
NumType
>
Self
;
typedef
Stat1MinMax
<
VType
,
NumType
>
Self
;
Stat1MinMax
()
{
Stat1MinMax
()
{
Clear
();
}
Clear
();
}
void
Clear
()
{
Stat1
<
VType
,
NumType
>::
Clear
();
if
(
std
::
numeric_limits
<
VType
>::
has_infinity
)
{
min_
=
std
::
numeric_limits
<
VType
>::
infinity
();
max_
=
-
std
::
numeric_limits
<
VType
>::
infinity
();
}
else
{
min_
=
std
::
numeric_limits
<
VType
>::
max
();
max_
=
std
::
numeric_limits
<
VType
>::
min
();
}
}
// Create a sample of value dat and weight 1
// Create a sample of value dat and weight 1
explicit
Stat1MinMax
(
const
VType
&
dat
)
:
Stat1
<
VType
,
NumType
>
(
dat
)
{
explicit
Stat1MinMax
(
const
VType
&
dat
)
:
Stat1
<
VType
,
NumType
>
(
dat
)
{
max_
=
dat
;
max_
=
dat
;
...
@@ -225,7 +214,7 @@ class Stat1MinMax : public Stat1<VType, NumType> {
...
@@ -225,7 +214,7 @@ class Stat1MinMax : public Stat1<VType, NumType> {
// and end(excluded)
// and end(excluded)
explicit
Stat1MinMax
(
const
VType
*
begin
,
const
VType
*
end
)
{
explicit
Stat1MinMax
(
const
VType
*
begin
,
const
VType
*
end
)
{
Clear
();
Clear
();
for
(
const
VType
*
item
=
begin
;
item
<
end
;
++
item
)
{
for
(
const
VType
*
item
=
begin
;
item
<
end
;
++
item
)
{
(
*
this
)
+=
Stat1MinMax
(
*
item
);
(
*
this
)
+=
Stat1MinMax
(
*
item
);
}
}
}
}
...
@@ -240,51 +229,55 @@ class Stat1MinMax : public Stat1<VType, NumType> {
...
@@ -240,51 +229,55 @@ class Stat1MinMax : public Stat1<VType, NumType> {
max_
=
stat
.
max_
;
max_
=
stat
.
max_
;
min_
=
stat
.
min_
;
min_
=
stat
.
min_
;
}
}
inline
Self
&
operator
=
(
const
Self
&
stat
)
{
void
Clear
()
{
Stat1
<
VType
,
NumType
>::
Clear
();
if
(
std
::
numeric_limits
<
VType
>::
has_infinity
)
{
min_
=
std
::
numeric_limits
<
VType
>::
infinity
();
max_
=
-
std
::
numeric_limits
<
VType
>::
infinity
();
}
else
{
min_
=
std
::
numeric_limits
<
VType
>::
max
();
max_
=
std
::
numeric_limits
<
VType
>::
min
();
}
}
Self
&
operator
=
(
const
Self
&
stat
)
{
this
->
Stat1
<
VType
,
NumType
>::
operator
=
(
stat
);
this
->
Stat1
<
VType
,
NumType
>::
operator
=
(
stat
);
max_
=
stat
.
max_
;
max_
=
stat
.
max_
;
min_
=
stat
.
min_
;
min_
=
stat
.
min_
;
return
(
*
this
);
return
(
*
this
);
}
}
// Merge statistics from two sample sets.
// Merge statistics from two sample sets.
inline
Self
&
operator
+=
(
const
Self
&
stat
)
{
Self
&
operator
+=
(
const
Self
&
stat
)
{
this
->
Stat1
<
VType
,
NumType
>::
operator
+=
(
stat
);
this
->
Stat1
<
VType
,
NumType
>::
operator
+=
(
stat
);
if
(
stat
.
max_
>
max_
)
max_
=
stat
.
max_
;
if
(
stat
.
max_
>
max_
)
max_
=
stat
.
max_
;
if
(
stat
.
min_
<
min_
)
min_
=
stat
.
min_
;
if
(
stat
.
min_
<
min_
)
min_
=
stat
.
min_
;
return
(
*
this
);
return
(
*
this
);
}
}
// Multiply the weight of the set of samples by a factor k
// Multiply the weight of the set of samples by a factor k
inline
Self
&
operator
*=
(
const
VType
&
stat
)
{
Self
&
operator
*=
(
const
VType
&
stat
)
{
this
->
Stat1
<
VType
,
NumType
>::
operator
*=
(
stat
);
this
->
Stat1
<
VType
,
NumType
>::
operator
*=
(
stat
);
return
(
*
this
);
return
(
*
this
);
}
}
// Merge statistics from two sample sets.
// Merge statistics from two sample sets.
inline
Self
operator
+
(
const
Self
&
stat
)
const
{
Self
operator
+
(
const
Self
&
stat
)
const
{
return
Self
(
*
this
)
+=
stat
;
}
return
Self
(
*
this
)
+=
stat
;
}
// Multiply the weight of the set of samples by a factor k
// Multiply the weight of the set of samples by a factor k
inline
Self
operator
*
(
const
VType
&
k
)
const
{
Self
operator
*
(
const
VType
&
k
)
const
{
return
Self
(
*
this
)
*=
k
;
}
return
Self
(
*
this
)
*=
k
;
}
// Return the maximal value in this sample set
VType
max
()
const
{
return
max_
;
}
// Return the minimal value in this sample set
VType
min
()
const
{
return
min_
;
}
private
:
private
:
// The - operation makes no sense with Min/Max
// The - operation makes no sense with Min/Max
// unless we keep the full list of values (but we don't)
// unless we keep the full list of values (but we don't)
// make it private, and let it undefined so nobody can call it
// make it private, and let it undefined so nobody can call it
Self
&
operator
-=
(
const
Self
&
stat
);
// senseless. let it undefined.
Self
&
operator
-=
(
const
Self
&
stat
);
// senseless. let it undefined.
// The operation opposite to -
// The operation opposite to -
Self
operator
-
(
const
Self
&
stat
)
const
;
// senseless. let it undefined.
Self
operator
-
(
const
Self
&
stat
)
const
;
// senseless. let it undefined.
public
:
// Return the maximal value in this sample set
VType
Max
()
const
{
return
max_
;
}
// Return the minimal value in this sample set
VType
Min
()
const
{
return
min_
;
}
private
:
// 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
// then the variables have the following meaning:
// then the variables have the following meaning:
...
@@ -294,12 +287,10 @@ class Stat1MinMax : public Stat1<VType, NumType> {
...
@@ -294,12 +287,10 @@ class Stat1MinMax : public Stat1<VType, NumType> {
// Useful printing function
// Useful printing function
template
<
typename
VType
,
typename
NumType
>
template
<
typename
VType
,
typename
NumType
>
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
const
Stat1MinMax
<
VType
,
NumType
>&
s
)
{
const
Stat1MinMax
<
VType
,
NumType
>&
s
)
{
out
<<
"{ avg = "
<<
s
.
Mean
()
out
<<
"{ avg = "
<<
s
.
Mean
()
<<
" std = "
<<
s
.
StdDev
()
<<
" std = "
<<
s
.
StdDev
()
<<
" nsamples = "
<<
s
.
NumSamples
()
<<
" min = "
<<
s
.
Min
()
<<
" nsamples = "
<<
s
.
NumSamples
()
<<
" min = "
<<
s
.
Min
()
<<
" max = "
<<
s
.
Max
()
<<
"}"
;
<<
" max = "
<<
s
.
Max
()
<<
"}"
;
return
out
;
return
out
;
}
}
...
...
src/sysinfo.cc
View file @
4ce184d8
...
@@ -39,7 +39,7 @@ int64_t EstimateCyclesPerSecond(const int estimate_time_ms) {
...
@@ -39,7 +39,7 @@ int64_t EstimateCyclesPerSecond(const int estimate_time_ms) {
// Helper function for reading an int from a file. Returns true if successful
// Helper function for reading an int from a file. Returns true if successful
// and the memory location pointed to by value is set to the value read.
// and the memory location pointed to by value is set to the value read.
bool
ReadIntFromFile
(
const
char
*
file
,
int
*
value
)
{
bool
ReadIntFromFile
(
const
char
*
file
,
int
*
value
)
{
bool
ret
=
false
;
bool
ret
=
false
;
int
fd
=
open
(
file
,
O_RDONLY
);
int
fd
=
open
(
file
,
O_RDONLY
);
if
(
fd
!=
-
1
)
{
if
(
fd
!=
-
1
)
{
...
@@ -116,42 +116,41 @@ void InitializeSystemInfo() {
...
@@ -116,42 +116,41 @@ void InitializeSystemInfo() {
if
(
sizeof
(
line
)
==
oldlinelen
+
1
)
// oldlinelen took up entire line
if
(
sizeof
(
line
)
==
oldlinelen
+
1
)
// oldlinelen took up entire line
line
[
0
]
=
'\0'
;
line
[
0
]
=
'\0'
;
else
// still other lines left to save
else
// still other lines left to save
memmove
(
line
,
line
+
oldlinelen
+
1
,
sizeof
(
line
)
-
(
oldlinelen
+
1
));
memmove
(
line
,
line
+
oldlinelen
+
1
,
sizeof
(
line
)
-
(
oldlinelen
+
1
));
// Terminate the new line, reading more if we can't find the newline
// Terminate the new line, reading more if we can't find the newline
char
*
newline
=
strchr
(
line
,
'\n'
);
char
*
newline
=
strchr
(
line
,
'\n'
);
if
(
newline
==
NULL
)
{
if
(
newline
==
NULL
)
{
const
int
linelen
=
strlen
(
line
);
const
int
linelen
=
strlen
(
line
);
const
int
bytes_to_read
=
sizeof
(
line
)
-
1
-
linelen
;
const
int
bytes_to_read
=
sizeof
(
line
)
-
1
-
linelen
;
CHECK
(
bytes_to_read
>
0
);
// because the memmove recovered >=1 bytes
CHECK
(
bytes_to_read
>
0
);
// because the memmove recovered >=1 bytes
chars_read
=
read
(
fd
,
line
+
linelen
,
bytes_to_read
);
chars_read
=
read
(
fd
,
line
+
linelen
,
bytes_to_read
);
line
[
linelen
+
chars_read
]
=
'\0'
;
line
[
linelen
+
chars_read
]
=
'\0'
;
newline
=
strchr
(
line
,
'\n'
);
newline
=
strchr
(
line
,
'\n'
);
}
}
if
(
newline
!=
NULL
)
if
(
newline
!=
NULL
)
*
newline
=
'\0'
;
*
newline
=
'\0'
;
// When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
// When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
// accept postive values. Some environments (virtual machines) report zero,
// accept postive values. Some environments (virtual machines) report zero,
// which would cause infinite looping in WallTime_Init.
// which would cause infinite looping in WallTime_Init.
if
(
!
saw_mhz
&&
strncasecmp
(
line
,
"cpu MHz"
,
sizeof
(
"cpu MHz"
)
-
1
)
==
0
)
{
if
(
!
saw_mhz
&&
strncasecmp
(
line
,
"cpu MHz"
,
sizeof
(
"cpu MHz"
)
-
1
)
==
0
)
{
const
char
*
freqstr
=
strchr
(
line
,
':'
);
const
char
*
freqstr
=
strchr
(
line
,
':'
);
if
(
freqstr
)
{
if
(
freqstr
)
{
cpuinfo_cycles_per_second
=
strtod
(
freqstr
+
1
,
&
err
)
*
1000000.0
;
cpuinfo_cycles_per_second
=
strtod
(
freqstr
+
1
,
&
err
)
*
1000000.0
;
if
(
freqstr
[
1
]
!=
'\0'
&&
*
err
==
'\0'
&&
cpuinfo_cycles_per_second
>
0
)
if
(
freqstr
[
1
]
!=
'\0'
&&
*
err
==
'\0'
&&
cpuinfo_cycles_per_second
>
0
)
saw_mhz
=
true
;
saw_mhz
=
true
;
}
}
}
else
if
(
strncasecmp
(
line
,
"bogomips"
,
sizeof
(
"bogomips"
)
-
1
)
==
0
)
{
}
else
if
(
strncasecmp
(
line
,
"bogomips"
,
sizeof
(
"bogomips"
)
-
1
)
==
0
)
{
const
char
*
freqstr
=
strchr
(
line
,
':'
);
const
char
*
freqstr
=
strchr
(
line
,
':'
);
if
(
freqstr
)
{
if
(
freqstr
)
{
bogo_clock
=
strtod
(
freqstr
+
1
,
&
err
)
*
1000000.0
;
bogo_clock
=
strtod
(
freqstr
+
1
,
&
err
)
*
1000000.0
;
if
(
freqstr
[
1
]
!=
'\0'
&&
*
err
==
'\0'
&&
bogo_clock
>
0
)
if
(
freqstr
[
1
]
!=
'\0'
&&
*
err
==
'\0'
&&
bogo_clock
>
0
)
saw_bogo
=
true
;
saw_bogo
=
true
;
}
}
}
else
if
(
strncasecmp
(
line
,
"processor"
,
sizeof
(
"processor"
)
-
1
)
==
0
)
{
}
else
if
(
strncasecmp
(
line
,
"processor"
,
sizeof
(
"processor"
)
-
1
)
==
0
)
{
num_cpus
++
;
// count up every time we see an "processor :" entry
num_cpus
++
;
// count up every time we see an "processor :" entry
const
char
*
freqstr
=
strchr
(
line
,
':'
);
const
char
*
freqstr
=
strchr
(
line
,
':'
);
if
(
freqstr
)
{
if
(
freqstr
)
{
const
int
cpu_id
=
strtol
(
freqstr
+
1
,
&
err
,
10
);
const
int
cpu_id
=
strtol
(
freqstr
+
1
,
&
err
,
10
);
if
(
freqstr
[
1
]
!=
'\0'
&&
*
err
==
'\0'
&&
max_cpu_id
<
cpu_id
)
if
(
freqstr
[
1
]
!=
'\0'
&&
*
err
==
'\0'
&&
max_cpu_id
<
cpu_id
)
max_cpu_id
=
cpu_id
;
max_cpu_id
=
cpu_id
;
}
}
...
@@ -181,17 +180,17 @@ void InitializeSystemInfo() {
...
@@ -181,17 +180,17 @@ void InitializeSystemInfo() {
}
}
#elif defined OS_FREEBSD
#elif defined OS_FREEBSD
// For this sysctl to work, the machine must be configured without
// For this sysctl to work, the machine must be configured without
// SMP, APIC, or APM support. hz should be 64-bit in freebsd 7.0
// SMP, APIC, or APM support. hz should be 64-bit in freebsd 7.0
// and later. Before that, it's a 32-bit quantity (and gives the
// and later. Before that, it's a 32-bit quantity (and gives the
// wrong answer on machines faster than 2^32 Hz). See
// wrong answer on machines faster than 2^32 Hz). See
// http://lists.freebsd.org/pipermail/freebsd-i386/2004-November/001846.html
// http://lists.freebsd.org/pipermail/freebsd-i386/2004-November/001846.html
// But also compare FreeBSD 7.0:
// But also compare FreeBSD 7.0:
// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG70#L223
// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG70#L223
// 231 error = sysctl_handle_quad(oidp, &freq, 0, req);
// 231 error = sysctl_handle_quad(oidp, &freq, 0, req);
// To FreeBSD 6.3 (it's the same in 6-STABLE):
// To FreeBSD 6.3 (it's the same in 6-STABLE):
// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG6#L131
// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG6#L131
// 139 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
// 139 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
#if __FreeBSD__ >= 7
#if __FreeBSD__ >= 7
uint64_t
hz
=
0
;
uint64_t
hz
=
0
;
#else
#else
...
@@ -199,25 +198,25 @@ void InitializeSystemInfo() {
...
@@ -199,25 +198,25 @@ void InitializeSystemInfo() {
#endif
#endif
size_t
sz
=
sizeof
(
hz
);
size_t
sz
=
sizeof
(
hz
);
const
char
*
sysctl_path
=
"machdep.tsc_freq"
;
const
char
*
sysctl_path
=
"machdep.tsc_freq"
;
if
(
sysctlbyname
(
sysctl_path
,
&
hz
,
&
sz
,
NULL
,
0
)
!=
0
)
{
if
(
sysctlbyname
(
sysctl_path
,
&
hz
,
&
sz
,
NULL
,
0
)
!=
0
)
{
fprintf
(
stderr
,
"Unable to determine clock rate from sysctl: %s: %s
\n
"
,
fprintf
(
stderr
,
"Unable to determine clock rate from sysctl: %s: %s
\n
"
,
sysctl_path
,
strerror
(
errno
));
sysctl_path
,
strerror
(
errno
));
cpuinfo_cycles_per_second
=
EstimateCyclesPerSecond
(
1000
);
cpuinfo_cycles_per_second
=
EstimateCyclesPerSecond
(
1000
);
}
else
{
}
else
{
cpuinfo_cycles_per_second
=
hz
;
cpuinfo_cycles_per_second
=
hz
;
}
}
// TODO: also figure out cpuinfo_num_cpus
// TODO: also figure out cpuinfo_num_cpus
#elif defined OS_WINDOWS
#elif defined OS_WINDOWS
#
pragma comment(lib, "shlwapi.lib") // for SHGetValue()
#pragma comment(lib, "shlwapi.lib") // for SHGetValue()
// 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.
OSVERSIONINFO
os
;
OSVERSIONINFO
os
;
os
.
dwOSVersionInfoSize
=
sizeof
(
os
);
os
.
dwOSVersionInfoSize
=
sizeof
(
os
);
DWORD
data
,
data_size
=
sizeof
(
data
);
DWORD
data
,
data_size
=
sizeof
(
data
);
if
(
GetVersionEx
(
&
os
)
&&
if
(
GetVersionEx
(
&
os
)
&&
os
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
&&
os
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
&&
SUCCEEDED
(
SUCCEEDED
(
SHGetValueA
(
HKEY_LOCAL_MACHINE
,
SHGetValueA
(
HKEY_LOCAL_MACHINE
,
"HARDWARE
\\
DESCRIPTION
\\
System
\\
CentralProcessor
\\
0"
,
"HARDWARE
\\
DESCRIPTION
\\
System
\\
CentralProcessor
\\
0"
,
"~MHz"
,
NULL
,
&
data
,
&
data_size
)))
"~MHz"
,
NULL
,
&
data
,
&
data_size
)))
cpuinfo_cycles_per_second
=
(
int64
)
data
*
(
int64
)(
1000
*
1000
);
// was mhz
cpuinfo_cycles_per_second
=
(
int64
)
data
*
(
int64
)(
1000
*
1000
);
// was mhz
...
@@ -243,10 +242,10 @@ void InitializeSystemInfo() {
...
@@ -243,10 +242,10 @@ 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
,
0
,
0
)
if
(
::
sysctl
(
numcpus_name
,
arraysize
(
numcpus_name
),
&
num_cpus
,
&
size
,
0
,
0
)
==
==
0
0
&&
&&
(
size
==
sizeof
(
num_cpus
)))
(
size
==
sizeof
(
num_cpus
)))
cpuinfo_num_cpus
=
num_cpus
;
cpuinfo_num_cpus
=
num_cpus
;
#else
#else
...
@@ -262,15 +261,15 @@ static double MyCPUUsageRUsage() {
...
@@ -262,15 +261,15 @@ static double MyCPUUsageRUsage() {
struct
rusage
ru
;
struct
rusage
ru
;
if
(
getrusage
(
RUSAGE_SELF
,
&
ru
)
==
0
)
{
if
(
getrusage
(
RUSAGE_SELF
,
&
ru
)
==
0
)
{
return
(
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_sec
)
+
return
(
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_sec
)
+
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_usec
)
*
1e-6
+
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_usec
)
*
1e-6
+
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_sec
)
+
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_sec
)
+
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_usec
)
*
1e-6
);
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_usec
)
*
1e-6
);
}
else
{
}
else
{
return
0.0
;
return
0.0
;
}
}
}
}
static
bool
MyCPUUsageCPUTimeNsLocked
(
double
*
cputime
)
{
static
bool
MyCPUUsageCPUTimeNsLocked
(
double
*
cputime
)
{
static
int
cputime_fd
=
-
1
;
static
int
cputime_fd
=
-
1
;
if
(
cputime_fd
==
-
1
)
{
if
(
cputime_fd
==
-
1
)
{
cputime_fd
=
open
(
"/proc/self/cputime_ns"
,
O_RDONLY
);
cputime_fd
=
open
(
"/proc/self/cputime_ns"
,
O_RDONLY
);
...
@@ -281,7 +280,7 @@ static bool MyCPUUsageCPUTimeNsLocked(double *cputime) {
...
@@ -281,7 +280,7 @@ static bool MyCPUUsageCPUTimeNsLocked(double *cputime) {
}
}
char
buff
[
64
];
char
buff
[
64
];
memset
(
buff
,
0
,
sizeof
(
buff
));
memset
(
buff
,
0
,
sizeof
(
buff
));
if
(
pread
(
cputime_fd
,
buff
,
sizeof
(
buff
)
-
1
,
0
)
<=
0
)
{
if
(
pread
(
cputime_fd
,
buff
,
sizeof
(
buff
)
-
1
,
0
)
<=
0
)
{
close
(
cputime_fd
);
close
(
cputime_fd
);
cputime_fd
=
-
1
;
cputime_fd
=
-
1
;
return
false
;
return
false
;
...
@@ -317,9 +316,9 @@ double ChildrenCPUUsage() {
...
@@ -317,9 +316,9 @@ double ChildrenCPUUsage() {
struct
rusage
ru
;
struct
rusage
ru
;
if
(
getrusage
(
RUSAGE_CHILDREN
,
&
ru
)
==
0
)
{
if
(
getrusage
(
RUSAGE_CHILDREN
,
&
ru
)
==
0
)
{
return
(
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_sec
)
+
return
(
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_sec
)
+
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_usec
)
*
1e-6
+
static_cast
<
double
>
(
ru
.
ru_utime
.
tv_usec
)
*
1e-6
+
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_sec
)
+
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_sec
)
+
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_usec
)
*
1e-6
);
static_cast
<
double
>
(
ru
.
ru_stime
.
tv_usec
)
*
1e-6
);
}
else
{
}
else
{
return
0.0
;
return
0.0
;
}
}
...
...
src/walltime.cc
View file @
4ce184d8
...
@@ -75,8 +75,8 @@ void Initialize() {
...
@@ -75,8 +75,8 @@ void Initialize() {
cycles_per_second
=
static_cast
<
int64_t
>
(
CyclesPerSecond
());
cycles_per_second
=
static_cast
<
int64_t
>
(
CyclesPerSecond
());
CHECK
(
cycles_per_second
!=
0
);
CHECK
(
cycles_per_second
!=
0
);
seconds_per_cycle
=
1.0
/
cycles_per_second
;
seconds_per_cycle
=
1.0
/
cycles_per_second
;
max_interval_cycles
=
static_cast
<
int64_t
>
(
max_interval_cycles
=
cycles_per_second
*
kMaxErrorInterval
);
static_cast
<
int64_t
>
(
cycles_per_second
*
kMaxErrorInterval
);
do
{
do
{
base_cycletime
=
cycleclock
::
Now
();
base_cycletime
=
cycleclock
::
Now
();
base_walltime
=
Slow
();
base_walltime
=
Slow
();
...
@@ -90,8 +90,7 @@ void Initialize() {
...
@@ -90,8 +90,7 @@ void Initialize() {
}
}
WallTime
Now
()
{
WallTime
Now
()
{
if
(
!
std
::
atomic_load
(
&
initialized
))
if
(
!
std
::
atomic_load
(
&
initialized
))
return
Slow
();
return
Slow
();
WallTime
now
=
0.0
;
WallTime
now
=
0.0
;
WallTime
result
=
0.0
;
WallTime
result
=
0.0
;
...
@@ -119,8 +118,8 @@ WallTime Now() {
...
@@ -119,8 +118,8 @@ WallTime Now() {
return
now
;
return
now
;
}
}
std
::
string
Print
(
WallTime
time
,
const
char
*
format
,
bool
local
,
std
::
string
Print
(
WallTime
time
,
const
char
*
format
,
bool
local
,
int
*
remainder_us
)
{
int
*
remainder_us
)
{
char
storage
[
32
];
char
storage
[
32
];
struct
tm
split
;
struct
tm
split
;
double
subsecond
;
double
subsecond
;
...
...
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