/Users/deen/code/yugabyte-db/src/yb/util/format-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright (c) YugaByte, Inc. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
5 | | // in compliance with the License. You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
10 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
11 | | // or implied. See the License for the specific language governing permissions and limitations |
12 | | // under the License. |
13 | | // |
14 | | // |
15 | | |
16 | | #include <sstream> |
17 | | #include <string> |
18 | | #include <unordered_map> |
19 | | #include <vector> |
20 | | |
21 | | #include <gtest/gtest.h> |
22 | | |
23 | | #include "yb/gutil/macros.h" |
24 | | |
25 | | #include "yb/util/monotime.h" |
26 | | #include "yb/util/status.h" |
27 | | #include "yb/util/test_macros.h" |
28 | | |
29 | | using namespace std::literals; |
30 | | |
31 | | namespace yb { |
32 | | |
33 | | namespace { |
34 | | |
35 | | template<class... Args> |
36 | 70 | void CheckPlain(const std::string& format, Args&&... args) { |
37 | 70 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), |
38 | 70 | Format(format, std::forward<Args>(args)...)); |
39 | 70 | } format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRKiEEEvRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJiEEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 6 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 6 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 6 | Format(format, std::forward<Args>(args)...)); | 39 | 6 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRKsEEEvRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJsEEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 6 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 6 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 6 | Format(format, std::forward<Args>(args)...)); | 39 | 6 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRKjEEEvRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJjEEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 6 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 6 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 6 | Format(format, std::forward<Args>(args)...)); | 39 | 6 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRKmEEEvRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJmEEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 6 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 6 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 6 | Format(format, std::forward<Args>(args)...)); | 39 | 6 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRKlEEEvRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJlEEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 6 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 6 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 6 | Format(format, std::forward<Args>(args)...)); | 39 | 6 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRKaEEEvRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJaEEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 6 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 6 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 6 | Format(format, std::forward<Args>(args)...)); | 39 | 6 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRA9_KcEEEvRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRPKcEEEvRKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJPcEEEvRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEDpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJRNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEvRKS8_DpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEvRKS8_DpOT_ Line | Count | Source | 36 | 3 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 3 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 3 | Format(format, std::forward<Args>(args)...)); | 39 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckPlainIJiRA7_KcNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEEvRKSB_DpOT_ Line | Count | Source | 36 | 1 | void CheckPlain(const std::string& format, Args&&... args) { | 37 | 1 | ASSERT_EQ(strings::Substitute(format, std::forward<Args>(args)...), | 38 | 1 | Format(format, std::forward<Args>(args)...)); | 39 | 1 | } |
|
40 | | |
41 | | template<class T> |
42 | 18 | void CheckInt(const std::string& format, const T& t) { |
43 | 18 | CheckPlain(format, t); |
44 | 18 | CheckPlain(format, std::numeric_limits<T>::min()); |
45 | 18 | CheckPlain(format, std::numeric_limits<T>::max()); |
46 | 18 | } format-test.cc:_ZN2yb12_GLOBAL__N_18CheckIntIiEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERKT_ Line | Count | Source | 42 | 3 | void CheckInt(const std::string& format, const T& t) { | 43 | 3 | CheckPlain(format, t); | 44 | 3 | CheckPlain(format, std::numeric_limits<T>::min()); | 45 | 3 | CheckPlain(format, std::numeric_limits<T>::max()); | 46 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_18CheckIntIsEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERKT_ Line | Count | Source | 42 | 3 | void CheckInt(const std::string& format, const T& t) { | 43 | 3 | CheckPlain(format, t); | 44 | 3 | CheckPlain(format, std::numeric_limits<T>::min()); | 45 | 3 | CheckPlain(format, std::numeric_limits<T>::max()); | 46 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_18CheckIntIjEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERKT_ Line | Count | Source | 42 | 3 | void CheckInt(const std::string& format, const T& t) { | 43 | 3 | CheckPlain(format, t); | 44 | 3 | CheckPlain(format, std::numeric_limits<T>::min()); | 45 | 3 | CheckPlain(format, std::numeric_limits<T>::max()); | 46 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_18CheckIntImEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERKT_ Line | Count | Source | 42 | 3 | void CheckInt(const std::string& format, const T& t) { | 43 | 3 | CheckPlain(format, t); | 44 | 3 | CheckPlain(format, std::numeric_limits<T>::min()); | 45 | 3 | CheckPlain(format, std::numeric_limits<T>::max()); | 46 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_18CheckIntIlEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERKT_ Line | Count | Source | 42 | 3 | void CheckInt(const std::string& format, const T& t) { | 43 | 3 | CheckPlain(format, t); | 44 | 3 | CheckPlain(format, std::numeric_limits<T>::min()); | 45 | 3 | CheckPlain(format, std::numeric_limits<T>::max()); | 46 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_18CheckIntIaEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERKT_ Line | Count | Source | 42 | 3 | void CheckInt(const std::string& format, const T& t) { | 43 | 3 | CheckPlain(format, t); | 44 | 3 | CheckPlain(format, std::numeric_limits<T>::min()); | 45 | 3 | CheckPlain(format, std::numeric_limits<T>::max()); | 46 | 3 | } |
|
47 | | |
48 | | template<class Collection> |
49 | 6 | void CheckCollection(const std::string& format, const Collection& collection) { |
50 | 6 | ASSERT_EQ(strings::Substitute(format, ToString(collection)), Format(format, collection)); |
51 | 6 | } format-test.cc:_ZN2yb12_GLOBAL__N_115CheckCollectionINSt3__16vectorIiNS2_9allocatorIiEEEEEEvRKNS2_12basic_stringIcNS2_11char_traitsIcEENS4_IcEEEERKT_ Line | Count | Source | 49 | 3 | void CheckCollection(const std::string& format, const Collection& collection) { | 50 | 3 | ASSERT_EQ(strings::Substitute(format, ToString(collection)), Format(format, collection)); | 51 | 3 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_115CheckCollectionINSt3__113unordered_mapIiNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_4hashIiEENS2_8equal_toIiEENS7_INS2_4pairIKiS9_EEEEEEEEvRKS9_RKT_ Line | Count | Source | 49 | 3 | void CheckCollection(const std::string& format, const Collection& collection) { | 50 | 3 | ASSERT_EQ(strings::Substitute(format, ToString(collection)), Format(format, collection)); | 51 | 3 | } |
|
52 | | |
53 | | std::vector<std::string> kFormats = { "Is it $0?", "Yes, it is $0", "$0 == $0, right?"}; |
54 | | std::string kLongFormat = "We have format of $0 and $1, may be also $2"; |
55 | | |
56 | | class Custom { |
57 | | public: |
58 | 3 | explicit Custom(int v) : value_(v) {} |
59 | | |
60 | | Custom(const Custom&) = delete; |
61 | | void operator=(const Custom&) = delete; |
62 | | |
63 | 6 | std::string ToString() const { |
64 | 6 | return Format("{ Custom: $0 }", value_); |
65 | 6 | } |
66 | | private: |
67 | | int value_; |
68 | | }; |
69 | | |
70 | 6 | double ClocksToMs(std::clock_t clocks) { |
71 | 6 | return 1000.0 * clocks / CLOCKS_PER_SEC; |
72 | 6 | } |
73 | | |
74 | | template<class... Args> |
75 | 3 | void CheckSpeed(const std::string& format, Args&&... args) { |
76 | | #ifdef THREAD_SANITIZER |
77 | | const size_t kCycles = 5000; |
78 | | #else |
79 | 3 | const size_t kCycles = 500000; |
80 | 3 | #endif |
81 | 3 | const size_t kMeasurements = 10; |
82 | 3 | std::vector<std::clock_t> substitute_times, format_times; |
83 | 3 | substitute_times.reserve(kMeasurements); |
84 | 3 | format_times.reserve(kMeasurements); |
85 | 33 | for (size_t m = 0; m != kMeasurements; ++m) { |
86 | 30 | const auto start = std::clock(); |
87 | 15.0M | for (size_t i = 0; i != kCycles; ++i) { |
88 | 15.0M | strings::Substitute(format, std::forward<Args>(args)...); |
89 | 15.0M | } |
90 | 30 | const auto mid = std::clock(); |
91 | 15.0M | for (size_t i = 0; i != kCycles; ++i) { |
92 | 15.0M | Format(format, std::forward<Args>(args)...); |
93 | 15.0M | } |
94 | 30 | const auto stop = std::clock(); |
95 | 30 | substitute_times.push_back(mid - start); |
96 | 30 | format_times.push_back(stop - mid); |
97 | 30 | } |
98 | 3 | std::sort(substitute_times.begin(), substitute_times.end()); |
99 | 3 | std::sort(format_times.begin(), format_times.end()); |
100 | 3 | std::clock_t substitute_time = 0; |
101 | 3 | std::clock_t format_time = 0; |
102 | 3 | size_t count = 0; |
103 | 18 | for (size_t i = kMeasurements / 4; i != kMeasurements * 3 / 4; ++i) { |
104 | 15 | substitute_time += substitute_times[i]; |
105 | 15 | format_time += format_times[i]; |
106 | 15 | ++count; |
107 | 15 | } |
108 | 3 | substitute_time /= count; |
109 | 3 | format_time /= count; |
110 | 3 | if (format_time > substitute_time) { |
111 | 0 | LOG(INFO) << Format("Format times: $0, substitute times: $1", format_times, substitute_times); |
112 | 0 | } |
113 | 3 | LOG(INFO) << "Performance results for [[ " |
114 | 3 | << Format(format, std::forward<Args>(args)...) << " ]]: " |
115 | 3 | << "substitute: " << ClocksToMs(substitute_time) << "ms, " |
116 | 3 | << "format: " << ClocksToMs(format_time) << "ms"; |
117 | | |
118 | | // Check that Format and Substitute differ by a factor within a certain range. |
119 | 3 | ASSERT_PERF_LE(format_time, substitute_time * 3); |
120 | 3 | ASSERT_PERF_LE(substitute_time, format_time * 10); |
121 | 3 | } format-test.cc:_ZN2yb12_GLOBAL__N_110CheckSpeedIJiiiEEEvRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEDpOT_ Line | Count | Source | 75 | 1 | void CheckSpeed(const std::string& format, Args&&... args) { | 76 | | #ifdef THREAD_SANITIZER | 77 | | const size_t kCycles = 5000; | 78 | | #else | 79 | 1 | const size_t kCycles = 500000; | 80 | 1 | #endif | 81 | 1 | const size_t kMeasurements = 10; | 82 | 1 | std::vector<std::clock_t> substitute_times, format_times; | 83 | 1 | substitute_times.reserve(kMeasurements); | 84 | 1 | format_times.reserve(kMeasurements); | 85 | 11 | for (size_t m = 0; m != kMeasurements; ++m) { | 86 | 10 | const auto start = std::clock(); | 87 | 5.00M | for (size_t i = 0; i != kCycles; ++i) { | 88 | 5.00M | strings::Substitute(format, std::forward<Args>(args)...); | 89 | 5.00M | } | 90 | 10 | const auto mid = std::clock(); | 91 | 5.00M | for (size_t i = 0; i != kCycles; ++i) { | 92 | 5.00M | Format(format, std::forward<Args>(args)...); | 93 | 5.00M | } | 94 | 10 | const auto stop = std::clock(); | 95 | 10 | substitute_times.push_back(mid - start); | 96 | 10 | format_times.push_back(stop - mid); | 97 | 10 | } | 98 | 1 | std::sort(substitute_times.begin(), substitute_times.end()); | 99 | 1 | std::sort(format_times.begin(), format_times.end()); | 100 | 1 | std::clock_t substitute_time = 0; | 101 | 1 | std::clock_t format_time = 0; | 102 | 1 | size_t count = 0; | 103 | 6 | for (size_t i = kMeasurements / 4; i != kMeasurements * 3 / 4; ++i) { | 104 | 5 | substitute_time += substitute_times[i]; | 105 | 5 | format_time += format_times[i]; | 106 | 5 | ++count; | 107 | 5 | } | 108 | 1 | substitute_time /= count; | 109 | 1 | format_time /= count; | 110 | 1 | if (format_time > substitute_time) { | 111 | 0 | LOG(INFO) << Format("Format times: $0, substitute times: $1", format_times, substitute_times); | 112 | 0 | } | 113 | 1 | LOG(INFO) << "Performance results for [[ " | 114 | 1 | << Format(format, std::forward<Args>(args)...) << " ]]: " | 115 | 1 | << "substitute: " << ClocksToMs(substitute_time) << "ms, " | 116 | 1 | << "format: " << ClocksToMs(format_time) << "ms"; | 117 | | | 118 | | // Check that Format and Substitute differ by a factor within a certain range. | 119 | 1 | ASSERT_PERF_LE(format_time, substitute_time * 3); | 120 | 1 | ASSERT_PERF_LE(substitute_time, format_time * 10); | 121 | 1 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckSpeedIJiRA7_KcNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEEvRKSB_DpOT_ Line | Count | Source | 75 | 1 | void CheckSpeed(const std::string& format, Args&&... args) { | 76 | | #ifdef THREAD_SANITIZER | 77 | | const size_t kCycles = 5000; | 78 | | #else | 79 | 1 | const size_t kCycles = 500000; | 80 | 1 | #endif | 81 | 1 | const size_t kMeasurements = 10; | 82 | 1 | std::vector<std::clock_t> substitute_times, format_times; | 83 | 1 | substitute_times.reserve(kMeasurements); | 84 | 1 | format_times.reserve(kMeasurements); | 85 | 11 | for (size_t m = 0; m != kMeasurements; ++m) { | 86 | 10 | const auto start = std::clock(); | 87 | 5.00M | for (size_t i = 0; i != kCycles; ++i) { | 88 | 5.00M | strings::Substitute(format, std::forward<Args>(args)...); | 89 | 5.00M | } | 90 | 10 | const auto mid = std::clock(); | 91 | 5.00M | for (size_t i = 0; i != kCycles; ++i) { | 92 | 5.00M | Format(format, std::forward<Args>(args)...); | 93 | 5.00M | } | 94 | 10 | const auto stop = std::clock(); | 95 | 10 | substitute_times.push_back(mid - start); | 96 | 10 | format_times.push_back(stop - mid); | 97 | 10 | } | 98 | 1 | std::sort(substitute_times.begin(), substitute_times.end()); | 99 | 1 | std::sort(format_times.begin(), format_times.end()); | 100 | 1 | std::clock_t substitute_time = 0; | 101 | 1 | std::clock_t format_time = 0; | 102 | 1 | size_t count = 0; | 103 | 6 | for (size_t i = kMeasurements / 4; i != kMeasurements * 3 / 4; ++i) { | 104 | 5 | substitute_time += substitute_times[i]; | 105 | 5 | format_time += format_times[i]; | 106 | 5 | ++count; | 107 | 5 | } | 108 | 1 | substitute_time /= count; | 109 | 1 | format_time /= count; | 110 | 1 | if (format_time > substitute_time) { | 111 | 0 | LOG(INFO) << Format("Format times: $0, substitute times: $1", format_times, substitute_times); | 112 | 0 | } | 113 | 1 | LOG(INFO) << "Performance results for [[ " | 114 | 1 | << Format(format, std::forward<Args>(args)...) << " ]]: " | 115 | 1 | << "substitute: " << ClocksToMs(substitute_time) << "ms, " | 116 | 1 | << "format: " << ClocksToMs(format_time) << "ms"; | 117 | | | 118 | | // Check that Format and Substitute differ by a factor within a certain range. | 119 | 1 | ASSERT_PERF_LE(format_time, substitute_time * 3); | 120 | 1 | ASSERT_PERF_LE(substitute_time, format_time * 10); | 121 | 1 | } |
format-test.cc:_ZN2yb12_GLOBAL__N_110CheckSpeedIJPvRA7_KcNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_EEEvRKSC_DpOT_ Line | Count | Source | 75 | 1 | void CheckSpeed(const std::string& format, Args&&... args) { | 76 | | #ifdef THREAD_SANITIZER | 77 | | const size_t kCycles = 5000; | 78 | | #else | 79 | 1 | const size_t kCycles = 500000; | 80 | 1 | #endif | 81 | 1 | const size_t kMeasurements = 10; | 82 | 1 | std::vector<std::clock_t> substitute_times, format_times; | 83 | 1 | substitute_times.reserve(kMeasurements); | 84 | 1 | format_times.reserve(kMeasurements); | 85 | 11 | for (size_t m = 0; m != kMeasurements; ++m) { | 86 | 10 | const auto start = std::clock(); | 87 | 5.00M | for (size_t i = 0; i != kCycles; ++i) { | 88 | 5.00M | strings::Substitute(format, std::forward<Args>(args)...); | 89 | 5.00M | } | 90 | 10 | const auto mid = std::clock(); | 91 | 5.00M | for (size_t i = 0; i != kCycles; ++i) { | 92 | 5.00M | Format(format, std::forward<Args>(args)...); | 93 | 5.00M | } | 94 | 10 | const auto stop = std::clock(); | 95 | 10 | substitute_times.push_back(mid - start); | 96 | 10 | format_times.push_back(stop - mid); | 97 | 10 | } | 98 | 1 | std::sort(substitute_times.begin(), substitute_times.end()); | 99 | 1 | std::sort(format_times.begin(), format_times.end()); | 100 | 1 | std::clock_t substitute_time = 0; | 101 | 1 | std::clock_t format_time = 0; | 102 | 1 | size_t count = 0; | 103 | 6 | for (size_t i = kMeasurements / 4; i != kMeasurements * 3 / 4; ++i) { | 104 | 5 | substitute_time += substitute_times[i]; | 105 | 5 | format_time += format_times[i]; | 106 | 5 | ++count; | 107 | 5 | } | 108 | 1 | substitute_time /= count; | 109 | 1 | format_time /= count; | 110 | 1 | if (format_time > substitute_time) { | 111 | 0 | LOG(INFO) << Format("Format times: $0, substitute times: $1", format_times, substitute_times); | 112 | 0 | } | 113 | 1 | LOG(INFO) << "Performance results for [[ " | 114 | 1 | << Format(format, std::forward<Args>(args)...) << " ]]: " | 115 | 1 | << "substitute: " << ClocksToMs(substitute_time) << "ms, " | 116 | 1 | << "format: " << ClocksToMs(format_time) << "ms"; | 117 | | | 118 | | // Check that Format and Substitute differ by a factor within a certain range. | 119 | 1 | ASSERT_PERF_LE(format_time, substitute_time * 3); | 120 | 1 | ASSERT_PERF_LE(substitute_time, format_time * 10); | 121 | 1 | } |
|
122 | | |
123 | | } // namespace |
124 | | |
125 | 1 | TEST(FormatTest, Number) { |
126 | 3 | for (const auto& format : kFormats) { |
127 | 3 | CheckInt<int>(format, 1984); |
128 | 3 | CheckInt<int16>(format, 2349); |
129 | 3 | CheckInt<uint32_t>(format, 23984296); |
130 | 3 | CheckInt<size_t>(format, 2936429238477); |
131 | 3 | CheckInt<ptrdiff_t>(format, -962394729); |
132 | 3 | CheckInt<int8_t>(format, 45); |
133 | 3 | } |
134 | 1 | } |
135 | | |
136 | 1 | TEST(FormatTest, String) { |
137 | 3 | for (const auto& format : kFormats) { |
138 | 3 | CheckPlain(format, "YugaByte"); |
139 | 3 | const char* pointer = "Pointer"; |
140 | 3 | CheckPlain(format, pointer); |
141 | 3 | char array[] = "Array"; |
142 | 3 | CheckPlain(format, &array[0]); |
143 | 3 | std::string string = "String"; |
144 | 3 | CheckPlain(format, string); |
145 | 3 | CheckPlain(format, "TempString"s); |
146 | 3 | } |
147 | 1 | } |
148 | | |
149 | | // strings::Substitute ignores actual size of array. |
150 | | // That is why CheckPlain helper can't be used to check Format with array argument without '\0'. |
151 | 1 | TEST(FormatTest, Array) { |
152 | 1 | union { |
153 | 1 | char data[10] = "head-tail"; |
154 | 1 | char head[4]; |
155 | 1 | } sub_array_accesor; |
156 | 1 | ASSERT_EQ("This should be head only", |
157 | 1 | Format("This should be $0 only", sub_array_accesor.head)); |
158 | 1 | } |
159 | | |
160 | 1 | TEST(FormatTest, Collections) { |
161 | 3 | for (const auto& format : kFormats) { |
162 | 3 | CheckCollection<std::vector<int>>(format, {1, 2, 3}); |
163 | 3 | CheckCollection<std::unordered_map<int, std::string>>(format, |
164 | 3 | {{1, "one"}, {2, "two"}, {3, "three"}}); |
165 | 3 | } |
166 | 1 | } |
167 | | |
168 | 1 | TEST(FormatTest, MultiArgs) { |
169 | 1 | CheckPlain(kLongFormat, 5, "String", "zero\0zero"s); |
170 | 1 | } |
171 | | |
172 | 1 | TEST(FormatTest, Custom) { |
173 | 3 | for (const auto& format : kFormats) { |
174 | 3 | Custom value(42); |
175 | 3 | ASSERT_EQ(strings::Substitute(format, value.ToString()), Format(format, value)); |
176 | 3 | } |
177 | 1 | } |
178 | | |
179 | 1 | TEST(FormatTest, Performance) { |
180 | 1 | CheckSpeed(kLongFormat, 1, 2, 3); |
181 | 1 | CheckSpeed(kLongFormat, 5, "String", "zero\0zero"s); |
182 | 1 | CheckSpeed("Connection ($0) $1 $2 => $3", |
183 | 1 | static_cast<void*>(this), |
184 | 1 | "client", |
185 | 1 | "127.0.0.1:12345"s, |
186 | 1 | "127.0.0.1:9042"s); |
187 | 1 | } |
188 | | |
189 | 1 | TEST(FormatTest, Time) { |
190 | 1 | ASSERT_EQ("Time: 10.000s", Format("Time: $0", 10s)); |
191 | 1 | ASSERT_EQ("Time: 0.001s", Format("Time: $0", 1ms)); |
192 | 1 | std::ostringstream out; |
193 | 1 | out << 15s; |
194 | 1 | ASSERT_EQ("15.000s", out.str()); |
195 | 1 | } |
196 | | |
197 | | } // namespace yb |