Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --benchmark_human_readable flag #1607

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ Colin Braley <braley.colin@gmail.com>
Daniel Harvey <danielharvey458@gmail.com>
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
Deniz Evrenci <denizevrenci@gmail.com>
Dirac Research
Dirac Research
Diego Krupitza <info@diegokrupitza.com>
Dominik Czarnota <dominik.b.czarnota@gmail.com>
Dominik Korman <kormandominik@gmail.com>
Donald Aingworth <donalds_junk_mail@yahoo.com>
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Cyrille Faucheux <cyrille.faucheux@gmail.com>
Daniel Harvey <danielharvey458@gmail.com>
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
Deniz Evrenci <denizevrenci@gmail.com>
Diego Krupitza <info@diegokrupitza.com>
Dominic Hamon <dma@stripysock.com> <dominic@google.com>
Dominik Czarnota <dominik.b.czarnota@gmail.com>
Dominik Korman <kormandominik@gmail.com>
Expand Down
51 changes: 51 additions & 0 deletions docs/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,57 @@ BM_memcpy/32 12 ns 12 ns 54687500
BM_memcpy/32k 1834 ns 1837 ns 357143
```

<a name="running-with-human-readable-format" />

## Human Readable Format

The `--benchmark_human_readable={true|false}` option can be used to display
args in a more human friendly format. Meaning numbers that are power of 2
will be formatted as `2^x`. Furthermore, for numbers that are the power of
10 special formatting abbreviations are used. For instance, `1000` will be
formatted to `1k`, `32000` to `32k`, `1000000` to `1m` and so on.

By default `benchmark_human_readable` is disabled.


```bash
$ ./run_benchmarks.x
Run on (1 X 2300 MHz CPU )
2016-06-25 19:34:24
BM_base_two_args/1 2.22 ns 2.22 ns 6280843
BM_base_two_args/2 2.20 ns 2.20 ns 6278027
BM_base_two_args/64 2.14 ns 2.14 ns 6263982
BM_base_two_args/128 2.22 ns 2.22 ns 6286484
BM_base_ten_args/1 2.25 ns 2.25 ns 6349206
BM_base_ten_args/10 2.18 ns 2.18 ns 6241641
BM_base_ten_args/100 2.24 ns 2.24 ns 6167401
BM_base_ten_args/1000 2.25 ns 2.25 ns 6137659
BM_base_ten_args/10000 2.24 ns 2.24 ns 6068487
BM_base_ten_args/32000 2.26 ns 2.26 ns 6063231
BM_base_ten_args/100000 2.25 ns 2.25 ns 6105539
BM_base_ten_args/1000000 2.21 ns 2.21 ns 6766554
BM_base_ten_args/1000000000 2.23 ns 2.23 ns 6233304
```

```bash
$ ./run_benchmarks.x --benchmark_human_readable
Run on (1 X 2300 MHz CPU )
2016-06-25 19:34:24
BM_base_two_args/1 2.18 ns 2.18 ns 6222222
BM_base_two_args/2^1 2.24 ns 2.24 ns 6208426
BM_base_two_args/2^6 2.24 ns 2.24 ns 6159261
BM_base_two_args/2^7 2.25 ns 2.25 ns 6337709
BM_base_ten_args/1 2.27 ns 2.27 ns 6071119
BM_base_ten_args/10 2.32 ns 2.32 ns 6278027
BM_base_ten_args/100 2.28 ns 2.27 ns 6029285
BM_base_ten_args/1k 2.27 ns 2.26 ns 5845511
BM_base_ten_args/10k 2.27 ns 2.26 ns 6252791
BM_base_ten_args/32k 2.27 ns 2.26 ns 6208426
BM_base_ten_args/100k 2.27 ns 2.26 ns 6129597
BM_base_ten_args/1M 2.28 ns 2.28 ns 5988024
BM_base_ten_args/1B 2.25 ns 2.25 ns 6211180
```

## Disabling Benchmarks

It is possible to temporarily disable benchmarks by renaming the benchmark
Expand Down
8 changes: 7 additions & 1 deletion src/benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ BM_DEFINE_string(benchmark_time_unit, "");
// The level of verbose logging to output
BM_DEFINE_int32(v, 0);

// defines whether to use human-readable format or not
BM_DEFINE_bool(benchmark_human_readable, false);

namespace internal {

std::map<std::string, std::string>* global_context = nullptr;
Expand Down Expand Up @@ -691,7 +694,9 @@ void ParseCommandLineFlags(int* argc, char** argv) {
&FLAGS_benchmark_context) ||
ParseStringFlag(argv[i], "benchmark_time_unit",
&FLAGS_benchmark_time_unit) ||
ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
ParseInt32Flag(argv[i], "v", &FLAGS_v) ||
ParseBoolFlag(argv[i], "benchmark_human_readable",
&FLAGS_benchmark_human_readable)) {
for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1];

--(*argc);
Expand Down Expand Up @@ -743,6 +748,7 @@ void PrintDefaultHelp() {
#endif
" [--benchmark_context=<key>=<value>,...]\n"
" [--benchmark_time_unit={ns|us|ms|s}]\n"
" [--benchmark_human_readable={true|false}]\n"
" [--v=<verbosity>]\n");
}

Expand Down
12 changes: 11 additions & 1 deletion src/benchmark_api_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "string_util.h"

namespace benchmark {

BM_DECLARE_bool(benchmark_human_readable);

namespace internal {

BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
Expand Down Expand Up @@ -43,7 +46,13 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
}
}

name_.args += StrFormat("%" PRId64, arg);
// formatting args either in default mode or in human-readable
if (FLAGS_benchmark_human_readable) {
name_.args += FormatHumanReadable(arg);
} else {
name_.args += StrFormat("%" PRId64, arg);
}

++arg_i;
}

Expand Down Expand Up @@ -114,5 +123,6 @@ void BenchmarkInstance::Teardown() const {
teardown_(st);
}
}

} // namespace internal
} // namespace benchmark
2 changes: 2 additions & 0 deletions src/benchmark_api_internal.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef BENCHMARK_API_INTERNAL_H
#define BENCHMARK_API_INTERNAL_H

#include <array>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still seeing these two headers. i'm sure they don't need to be added and i'd rather minimise any dependencies.

#include <cinttypes>
#include <cmath>
#include <iosfwd>
#include <limits>
Expand Down
52 changes: 50 additions & 2 deletions src/string_util.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "string_util.h"

#include <array>
#include <cinttypes>
#ifdef BENCHMARK_STL_ANDROID_GNUSTL
#include <cerrno>
#endif
Expand All @@ -15,6 +16,11 @@
namespace benchmark {
namespace {

// Thousands, Millions, Billions, Trillions, Quadrillions, Quintillions,
// Sextillions, Septillions.
const std::array<std::string, 8> base10Units = {"k", "M", "B", "T",
"Q", "Qi", "Sx", "Sp"};

// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
const char kBigSIUnits[] = "kMGTPEZY";
// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
Expand All @@ -32,7 +38,8 @@ static const int64_t kUnitsSize = arraysize(kBigSIUnits);

void ToExponentAndMantissa(double val, double thresh, int precision,
double one_k, std::string* mantissa,
int64_t* exponent) {
int64_t* exponent,
bool inclusiveBigThreshhold = false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like we only set this to true when we're doing base-10. it might be worth having a comment why this is necessary for base-10. or even better, renaming the variable to indicate that directly.

std::stringstream mantissa_stream;

if (val < 0) {
Expand All @@ -44,7 +51,13 @@ void ToExponentAndMantissa(double val, double thresh, int precision,
// 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;

// used to make the big_threshold inclusive or not. By subtracting 1 from
// big_threshold we make the range inclusive
const double big_threshold_slide = inclusiveBigThreshhold ? 1.0 : 0.0;
const double big_threshold =
(adjusted_threshold * one_k) - big_threshold_slide;

const double small_threshold = adjusted_threshold;
// Values in ]simple_threshold,small_threshold[ will be printed as-is
const double simple_threshold = 0.01;
Expand Down Expand Up @@ -262,4 +275,39 @@ double stod(const std::string& str, size_t* pos) {
}
#endif

std::string ExponentToBase10Prefix(int64_t exponent) {
if (exponent == 0) return "";

const int64_t index = (exponent > 0 ? exponent - 1 : -exponent - 1);
if (index >= kUnitsSize) return "";

return base10Units[index];
}

std::string Base10HumanReadableFormat(const int64_t& arg) {
std::string mantissa;
int64_t exponent;
ToExponentAndMantissa(arg, 1, 1, 1000, &mantissa, &exponent, true);
return mantissa + ExponentToBase10Prefix(exponent);
}

/**
* Check whether the given value is a power of two or not.
* @param val the value to check
*/
bool IsPowerOfTwo(const int64_t& val) {
return (val & (val - 1)) == 0 && (val > 1);
}

std::string Base2HumanReadableFormat(const int64_t& arg) {
return StrFormat("2^%.0f", std::log2(arg));
}

std::string FormatHumanReadable(const int64_t& arg) {
if (IsPowerOfTwo(arg)) {
return Base2HumanReadableFormat(arg);
}
return Base10HumanReadableFormat(arg);
}

} // end namespace benchmark
23 changes: 23 additions & 0 deletions src/string_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ using std::stoul; // NOLINT(misc-unused-using-decls)
#endif
// NOLINTEND

/**
* Gets the human readable format for a given base10 value.
* In other words converts 1_000 to 1k, 40_000_000 to 40m etc
* @param arg the positive value to convert
* @return human readable formatted string
*/
std::string Base10HumanReadableFormat(const int64_t& arg);

/**
* Gets the human readable format for a given base2 value.
* In other words converts 64 to 2^6, 1024 to 2^10 etc
* @param arg the positive value to convert
* @return human readable formatted string
*/
std::string Base2HumanReadableFormat(const int64_t& arg);

/**
* Formats an argument into a human readable format.
* @param arg the argument to format
* @return the argument formatted as human readable
*/
std::string FormatHumanReadable(const int64_t& arg);

} // end namespace benchmark

#endif // BENCHMARK_STRING_UTIL_H_
1 change: 1 addition & 0 deletions test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ PER_SRC_TEST_ARGS = {
"repetitions_test.cc": [" --benchmark_repetitions=3"],
"spec_arg_test.cc": ["--benchmark_filter=BM_NotChosen"],
"spec_arg_verbosity_test.cc": ["--v=42"],
"human_readable_formatting_test.cc": ["--benchmark_human_readable"]
}

cc_library(
Expand Down
7 changes: 7 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ add_test(NAME user_counters_thousands_test COMMAND user_counters_thousands_test
compile_output_test(memory_manager_test)
add_test(NAME memory_manager_test COMMAND memory_manager_test --benchmark_min_time=0.01s)

compile_benchmark_test(human_readable_formatting_test)
add_test(NAME human_readable_formatting_test COMMAND human_readable_formatting_test --benchmark_min_time=0.01s --benchmark_human_readable)

compile_benchmark_test(non_human_readable_formatting_test)
add_test(NAME non_human_readable_formatting_test COMMAND non_human_readable_formatting_test --benchmark_min_time=0.01s --benchmark_human_readable=false)

# MSVC does not allow to set the language standard to C++98/03.
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
compile_benchmark_test(cxx03_test)
Expand Down Expand Up @@ -237,6 +243,7 @@ if (BENCHMARK_ENABLE_GTEST_TESTS)
add_gtest(perf_counters_gtest)
add_gtest(time_unit_gtest)
add_gtest(min_time_parse_gtest)
add_gtest(human_readable_gtest)
endif(BENCHMARK_ENABLE_GTEST_TESTS)

###############################################################################
Expand Down
Loading
Loading