mirror of https://github.com/google/benchmark.git
Third step in moving towards adopting new timer semantics
This commit is contained in:
parent
f947cebe15
commit
a187aa0803
|
@ -3,7 +3,8 @@ include_directories(${PROJECT_SOURCE_DIR}/src)
|
|||
|
||||
# Define the source files
|
||||
set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc"
|
||||
"log.cc" "sleep.cc" "sysinfo.cc" "walltime.cc")
|
||||
"log.cc" "sleep.cc" "string_util.cc" "sysinfo.cc"
|
||||
"walltime.cc")
|
||||
# Determine the correct regular expression engine to use
|
||||
if(HAVE_STD_REGEX)
|
||||
set(RE_FILES "re_std.cc")
|
||||
|
|
107
src/benchmark.cc
107
src/benchmark.cc
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -22,6 +22,7 @@
|
|||
#include "re.h"
|
||||
#include "sleep.h"
|
||||
#include "stat.h"
|
||||
#include "string_util.h"
|
||||
#include "sysinfo.h"
|
||||
#include "walltime.h"
|
||||
|
||||
|
@ -82,108 +83,6 @@ DECLARE_string(heap_check);
|
|||
|
||||
namespace benchmark {
|
||||
namespace {
|
||||
// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
|
||||
const char kBigSIUnits[] = "kMGTPEZY";
|
||||
// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
|
||||
const char kBigIECUnits[] = "KMGTPEZY";
|
||||
// milli, micro, nano, pico, femto, atto, zepto, yocto.
|
||||
const char kSmallSIUnits[] = "munpfazy";
|
||||
|
||||
// We require that all three arrays have the same size.
|
||||
static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits),
|
||||
"SI and IEC unit arrays must be the same size");
|
||||
static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
|
||||
"Small SI and Big SI unit arrays must be the same size");
|
||||
static const size_t kUnitsSize = arraysize(kBigSIUnits);
|
||||
|
||||
void ToExponentAndMantissa(double val, double thresh, int precision,
|
||||
double one_k, std::string* mantissa, size_t* exponent) {
|
||||
std::stringstream mantissa_stream;
|
||||
|
||||
if (val < 0) {
|
||||
mantissa_stream << "-";
|
||||
val = -val;
|
||||
}
|
||||
|
||||
// Adjust threshold so that it never excludes things which can't be rendered
|
||||
// in 'precision' digits.
|
||||
const double adjusted_threshold =
|
||||
std::max(thresh, 1.0 / pow(10.0, precision));
|
||||
const double big_threshold = adjusted_threshold * one_k;
|
||||
const double small_threshold = adjusted_threshold;
|
||||
|
||||
if (val > big_threshold) {
|
||||
// Positive powers
|
||||
double scaled = val;
|
||||
for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) {
|
||||
scaled /= one_k;
|
||||
if (scaled <= big_threshold) {
|
||||
mantissa_stream << scaled;
|
||||
*exponent = i + 1;
|
||||
*mantissa = mantissa_stream.str();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mantissa_stream << val;
|
||||
*exponent = 0;
|
||||
} else if (val < small_threshold) {
|
||||
// Negative powers
|
||||
double scaled = val;
|
||||
for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) {
|
||||
scaled *= one_k;
|
||||
if (scaled >= small_threshold) {
|
||||
mantissa_stream << scaled;
|
||||
*exponent = -i - 1;
|
||||
*mantissa = mantissa_stream.str();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mantissa_stream << val;
|
||||
*exponent = 0;
|
||||
} else {
|
||||
mantissa_stream << val;
|
||||
*exponent = 0;
|
||||
}
|
||||
*mantissa = mantissa_stream.str();
|
||||
}
|
||||
|
||||
std::string ExponentToPrefix(size_t exponent, bool iec) {
|
||||
if (exponent == 0) return "";
|
||||
|
||||
const size_t index = (exponent > 0 ? exponent - 1 : -exponent - 1);
|
||||
if (index >= kUnitsSize) return "";
|
||||
|
||||
const char* array =
|
||||
(exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits);
|
||||
if (iec)
|
||||
return array[index] + std::string("i");
|
||||
else
|
||||
return std::string(1, array[index]);
|
||||
}
|
||||
|
||||
std::string ToBinaryStringFullySpecified(double value, double threshold,
|
||||
int precision) {
|
||||
std::string mantissa;
|
||||
size_t exponent;
|
||||
ToExponentAndMantissa(value, threshold, precision, 1024.0, &mantissa,
|
||||
&exponent);
|
||||
return mantissa + ExponentToPrefix(exponent, false);
|
||||
}
|
||||
|
||||
inline void AppendHumanReadable(int n, std::string* str) {
|
||||
std::stringstream ss;
|
||||
// Round down to the nearest SI prefix.
|
||||
ss << "/" << ToBinaryStringFullySpecified(n, 1.0, 0);
|
||||
*str += ss.str();
|
||||
}
|
||||
|
||||
inline std::string HumanReadableNumber(double n) {
|
||||
// 1.1 means that figures up to 1.1k should be shown with the next unit down;
|
||||
// this softens edge effects.
|
||||
// 1 means that we should show one decimal place of precision.
|
||||
return ToBinaryStringFullySpecified(n, 1.1, 1);
|
||||
}
|
||||
|
||||
// For non-dense Range, intermediate values are powers of kRangeMultiplier.
|
||||
static const int kRangeMultiplier = 8;
|
||||
|
||||
|
@ -271,7 +170,7 @@ void ComputeStats(const std::vector<BenchmarkReporter::Run>& reports,
|
|||
mean_data->iterations;
|
||||
mean_data->bytes_per_second = bytes_per_second_stat.Mean();
|
||||
mean_data->items_per_second = items_per_second_stat.Mean();
|
||||
mean_data->max_heapbytes_used = max_heapbytes_used_stat.max();
|
||||
mean_data->max_heapbytes_used = max_heapbytes_used_stat.Max();
|
||||
|
||||
// Only add label to mean/stddev if it is same for all runs
|
||||
mean_data->report_label = reports[0].report_label;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -14,9 +14,10 @@
|
|||
|
||||
#include "colorprint.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "commandlineflags.h"
|
||||
#include "internal_macros.h"
|
||||
|
||||
DECLARE_bool(color_print);
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
|
||||
#include "commandlineflags.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
|
@ -75,10 +74,7 @@ bool ParseDouble(const std::string& src_text, const char* str, double* value) {
|
|||
}
|
||||
|
||||
inline const char* GetEnv(const char* name) {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
// We are on Windows CE, which has no environment variables.
|
||||
return NULL;
|
||||
#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
|
||||
#if defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
|
||||
// Environment variables which we programmatically clear will be set to the
|
||||
// empty string rather than unset (NULL). Handle that case.
|
||||
const char* const env = getenv(name);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#ifndef BENCHMARK_COMMANDLINEFLAGS_H_
|
||||
#define BENCHMARK_COMMANDLINEFLAGS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// Macro for referencing flags.
|
||||
|
@ -72,6 +71,6 @@ bool ParseStringFlag(const char* str, const char* flag, std::string* value);
|
|||
// Returns true if the string matches the flag.
|
||||
bool IsFlag(const char* str, const char* flag);
|
||||
|
||||
} // end namespace gbenchmark
|
||||
} // end namespace benchmark
|
||||
|
||||
#endif // BENCHMARK_COMMANDLINEFLAGS_H_
|
||||
|
|
|
@ -21,7 +21,10 @@
|
|||
#ifndef BENCHMARK_CYCLECLOCK_H_
|
||||
#define BENCHMARK_CYCLECLOCK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include "benchmark/macros.h"
|
||||
#include "internal_macros.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include <mach/mach_time.h>
|
||||
|
@ -39,8 +42,6 @@ extern "C" uint64_t __rdtsc();
|
|||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "benchmark/macros.h"
|
||||
|
||||
namespace benchmark {
|
||||
// NOTE: only i386 and x86_64 have been well tested.
|
||||
// PPC, sparc, alpha, and ia64 are based on
|
||||
|
|
2
src/re.h
2
src/re.h
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -12,7 +12,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <benchmark/macros.h>
|
||||
#include "re.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -14,8 +14,10 @@
|
|||
|
||||
#include "sleep.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <cerrno>
|
||||
#include <ctime>
|
||||
|
||||
#include "internal_macros.h"
|
||||
|
||||
namespace benchmark {
|
||||
#ifdef OS_WINDOWS
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef BENCHMARK_SLEEP_H_
|
||||
#define BENCHMARK_SLEEP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace benchmark {
|
||||
const int64_t kNumMillisPerSecond = 1000LL;
|
||||
|
|
11
src/stat.h
11
src/stat.h
|
@ -1,11 +1,12 @@
|
|||
#ifndef BENCHMARK_STAT_H_
|
||||
#define BENCHMARK_STAT_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <ostream>
|
||||
#include <limits>
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
template <typename VType, typename NumType>
|
||||
class Stat1;
|
||||
|
||||
|
@ -103,7 +104,7 @@ class Stat1 {
|
|||
NumType numSamples() const { return numsamples_; }
|
||||
|
||||
// Return the sum of this sample set
|
||||
VType sum() const { return sum_; }
|
||||
VType Sum() const { return sum_; }
|
||||
|
||||
// Return the mean of this sample set
|
||||
VType Mean() const {
|
||||
|
@ -267,9 +268,9 @@ class Stat1MinMax : public Stat1<VType, NumType> {
|
|||
Self operator*(const VType &k) const { return Self(*this) *= k; }
|
||||
|
||||
// Return the maximal value in this sample set
|
||||
VType max() const { return max_; }
|
||||
VType Max() const { return max_; }
|
||||
// Return the minimal value in this sample set
|
||||
VType min() const { return min_; }
|
||||
VType Min() const { return min_; }
|
||||
|
||||
private:
|
||||
// The - operation makes no sense with Min/Max
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
#include "string_util.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "arraysize.h"
|
||||
|
||||
namespace benchmark {
|
||||
namespace {
|
||||
|
||||
// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
|
||||
const char kBigSIUnits[] = "kMGTPEZY";
|
||||
// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
|
||||
const char kBigIECUnits[] = "KMGTPEZY";
|
||||
// milli, micro, nano, pico, femto, atto, zepto, yocto.
|
||||
const char kSmallSIUnits[] = "munpfazy";
|
||||
|
||||
// We require that all three arrays have the same size.
|
||||
static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits),
|
||||
"SI and IEC unit arrays must be the same size");
|
||||
static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
|
||||
"Small SI and Big SI unit arrays must be the same size");
|
||||
|
||||
static const int kUnitsSize = arraysize(kBigSIUnits);
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
void ToExponentAndMantissa(double val, double thresh, int precision,
|
||||
double one_k, std::string* mantissa,
|
||||
int* exponent) {
|
||||
std::stringstream mantissa_stream;
|
||||
|
||||
if (val < 0) {
|
||||
mantissa_stream << "-";
|
||||
val = -val;
|
||||
}
|
||||
|
||||
// Adjust threshold so that it never excludes things which can't be rendered
|
||||
// in 'precision' digits.
|
||||
const double adjusted_threshold =
|
||||
std::max(thresh, 1.0 / std::pow(10.0, precision));
|
||||
const double big_threshold = adjusted_threshold * one_k;
|
||||
const double small_threshold = adjusted_threshold;
|
||||
|
||||
if (val > big_threshold) {
|
||||
// Positive powers
|
||||
double scaled = val;
|
||||
for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) {
|
||||
scaled /= one_k;
|
||||
if (scaled <= big_threshold) {
|
||||
mantissa_stream << scaled;
|
||||
*exponent = i + 1;
|
||||
*mantissa = mantissa_stream.str();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mantissa_stream << val;
|
||||
*exponent = 0;
|
||||
} else if (val < small_threshold) {
|
||||
// Negative powers
|
||||
double scaled = val;
|
||||
for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) {
|
||||
scaled *= one_k;
|
||||
if (scaled >= small_threshold) {
|
||||
mantissa_stream << scaled;
|
||||
*exponent = -i - 1;
|
||||
*mantissa = mantissa_stream.str();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mantissa_stream << val;
|
||||
*exponent = 0;
|
||||
} else {
|
||||
mantissa_stream << val;
|
||||
*exponent = 0;
|
||||
}
|
||||
*mantissa = mantissa_stream.str();
|
||||
}
|
||||
|
||||
std::string ExponentToPrefix(int exponent, bool iec) {
|
||||
if (exponent == 0) return "";
|
||||
|
||||
const int index = (exponent > 0 ? exponent - 1 : -exponent - 1);
|
||||
if (index >= kUnitsSize) return "";
|
||||
|
||||
const char* array =
|
||||
(exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits);
|
||||
if (iec)
|
||||
return array[index] + std::string("i");
|
||||
else
|
||||
return std::string(1, array[index]);
|
||||
}
|
||||
|
||||
std::string ToBinaryStringFullySpecified(double value, double threshold,
|
||||
int precision) {
|
||||
std::string mantissa;
|
||||
int exponent;
|
||||
ToExponentAndMantissa(value, threshold, precision, 1024.0, &mantissa,
|
||||
&exponent);
|
||||
return mantissa + ExponentToPrefix(exponent, false);
|
||||
}
|
||||
|
||||
void AppendHumanReadable(int n, std::string* str) {
|
||||
std::stringstream ss;
|
||||
// Round down to the nearest SI prefix.
|
||||
ss << "/" << ToBinaryStringFullySpecified(n, 1.0, 0);
|
||||
*str += ss.str();
|
||||
}
|
||||
|
||||
std::string HumanReadableNumber(double n) {
|
||||
// 1.1 means that figures up to 1.1k should be shown with the next unit down;
|
||||
// this softens edge effects.
|
||||
// 1 means that we should show one decimal place of precision.
|
||||
return ToBinaryStringFullySpecified(n, 1.1, 1);
|
||||
}
|
||||
|
||||
std::string StringPrintFImp(const char *msg, va_list args)
|
||||
{
|
||||
// we might need a second shot at this, so pre-emptivly make a copy
|
||||
va_list args_cp;
|
||||
va_copy(args_cp, args);
|
||||
|
||||
// TODO(ericwf): use std::array for first attempt to avoid one memory
|
||||
// allocation guess what the size might be
|
||||
std::array<char, 256> local_buff;
|
||||
std::size_t size = local_buff.size();
|
||||
auto ret = std::vsnprintf(local_buff.data(), size, msg, args_cp);
|
||||
|
||||
va_end(args_cp);
|
||||
|
||||
// handle empty expansion
|
||||
if (ret == 0)
|
||||
return std::string{};
|
||||
if (static_cast<std::size_t>(ret) < size)
|
||||
return std::string(local_buff.data());
|
||||
|
||||
// we did not provide a long enough buffer on our first attempt.
|
||||
// add 1 to size to account for null-byte in size cast to prevent overflow
|
||||
size = static_cast<std::size_t>(ret) + 1;
|
||||
auto buff_ptr = std::unique_ptr<char[]>(new char[size]);
|
||||
ret = std::vsnprintf(buff_ptr.get(), size, msg, args);
|
||||
return std::string(buff_ptr.get());
|
||||
}
|
||||
|
||||
std::string StringPrintF(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
std::string tmp = StringPrintFImp(format, args);
|
||||
va_end(args);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
} // end namespace benchmark
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef BENCHMARK_STRING_UTIL_H
|
||||
#define BENCHMARK_STRING_UTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
void ToExponentAndMantissa(double val, double thresh, int precision,
|
||||
double one_k, std::string* mantissa, int* exponent);
|
||||
|
||||
std::string ExponentToPrefix(int exponent, bool iec);
|
||||
|
||||
std::string ToBinaryStringFullySpecified(double value, double threshold,
|
||||
int precision);
|
||||
|
||||
void AppendHumanReadable(int n, std::string* str);
|
||||
|
||||
std::string HumanReadableNumber(double n);
|
||||
|
||||
std::string StringPrintF(const char* format, ...);
|
||||
|
||||
inline std::ostream&
|
||||
StringCatImp(std::ostream& out) noexcept
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class First, class ...Rest>
|
||||
inline std::ostream&
|
||||
StringCatImp(std::ostream& out, First&& f, Rest&&... rest)
|
||||
{
|
||||
out << std::forward<First>(f);
|
||||
return StringCatImp(out, std::forward<Rest>(rest)...);
|
||||
}
|
||||
|
||||
template<class ...Args>
|
||||
inline std::string StrCat(Args&&... args)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
StringCatImp(ss, std::forward<Args>(args)...);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // end namespace benchmark
|
||||
|
||||
#endif // BENCHMARK_STRING_UTIL_H
|
|
@ -14,24 +14,26 @@
|
|||
|
||||
#include "sysinfo.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
|
||||
#include "arraysize.h"
|
||||
#include "check.h"
|
||||
#include "cycleclock.h"
|
||||
#include "internal_macros.h"
|
||||
#include "sleep.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
Loading…
Reference in New Issue