|
5 | 5 | #include "string_util.h"
|
6 | 6 |
|
7 | 7 | namespace benchmark {
|
| 8 | + |
| 9 | +BM_DECLARE_bool(benchmark_human_readable); |
| 10 | + |
8 | 11 | namespace internal {
|
9 | 12 |
|
10 | 13 | BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
|
@@ -43,7 +46,20 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
|
43 | 46 | }
|
44 | 47 | }
|
45 | 48 |
|
46 |
| - name_.args += StrFormat("%" PRId64, arg); |
| 49 | + // formatting args either in default mode or in human-readable |
| 50 | + auto formattedArgument = StrFormat("%" PRId64, arg); |
| 51 | + |
| 52 | + if (FLAGS_benchmark_human_readable) { |
| 53 | + if ((arg & (arg - 1)) == 0 && (arg > 1)) { |
| 54 | + // power of two human format |
| 55 | + formattedArgument = StrFormat("2^%.0f", std::log2(arg)); |
| 56 | + } else if (arg % 10 == 0 && (arg > 0)) { |
| 57 | + // base 10 human format |
| 58 | + formattedArgument = Base10HumanReadableFormat::get(arg); |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + name_.args += formattedArgument; |
47 | 63 | ++arg_i;
|
48 | 64 | }
|
49 | 65 |
|
@@ -114,5 +130,55 @@ void BenchmarkInstance::Teardown() const {
|
114 | 130 | teardown_(st);
|
115 | 131 | }
|
116 | 132 | }
|
| 133 | + |
| 134 | +const std::array<Base10HumanReadableFormat, 5> |
| 135 | + Base10HumanReadableFormat::ranges = { |
| 136 | + Base10HumanReadableFormat{1, ""}, // from 0 to 10^3-1 |
| 137 | + Base10HumanReadableFormat{1000, "k"}, // from 10^3 to 10^6-1 |
| 138 | + Base10HumanReadableFormat{1000000, "m"}, // from 10^6 to 10^9-1 |
| 139 | + Base10HumanReadableFormat{1000000000, "bn"}, // from 10^9 to 10^12-1 |
| 140 | + Base10HumanReadableFormat{1000000000000, ""} // above show as full |
| 141 | +}; |
| 142 | + |
| 143 | +std::string Base10HumanReadableFormat::get(const int64_t& arg) { |
| 144 | + // binary search for the best match |
| 145 | + std::size_t left = 0; |
| 146 | + std::size_t right = ranges.size() - 1; |
| 147 | + |
| 148 | + while (left <= right) { |
| 149 | + const std::size_t middle = left + std::floor((right - left) / 2); |
| 150 | + const auto& middle_val = ranges[middle].entry_val_; |
| 151 | + |
| 152 | + if (middle_val == arg) { |
| 153 | + left = middle; |
| 154 | + break; |
| 155 | + } |
| 156 | + |
| 157 | + if (arg < middle_val) { |
| 158 | + right = middle - 1; |
| 159 | + } else { |
| 160 | + left = middle + 1; |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + const auto min_index = std::min(left, right); |
| 165 | + |
| 166 | + // in case we get the "above" we return the '1' just for simplicity. |
| 167 | + // because we use the "entry_val_" in later stages for division. |
| 168 | + const auto& readable_format = |
| 169 | + ranges[(min_index == ranges.size() - 1 ? 0 : min_index)]; |
| 170 | + |
| 171 | + // if it is not a perfect match we return the value |
| 172 | + // e.g. 1030 we do not want 10k we want 1030 |
| 173 | + if (arg % readable_format.entry_val_ != 0) { |
| 174 | + return StrFormat("%" PRId64, arg); |
| 175 | + } |
| 176 | + |
| 177 | + // for everything else we want the abbreviation |
| 178 | + const auto reduced_val = arg / readable_format.entry_val_; |
| 179 | + return StrFormat("%" PRId64 "%s", reduced_val, |
| 180 | + readable_format.abbreviation_.c_str()); |
| 181 | +} |
| 182 | + |
117 | 183 | } // namespace internal
|
118 | 184 | } // namespace benchmark
|
0 commit comments