/Users/deen/code/yugabyte-db/src/yb/util/fast_varint-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #include <algorithm> |
15 | | #include <cstdint> |
16 | | #include <random> |
17 | | #include <string> |
18 | | |
19 | | #include <glog/logging.h> |
20 | | |
21 | | #include "yb/util/bytes_formatter.h" |
22 | | #include "yb/util/cast.h" |
23 | | #include "yb/util/fast_varint.h" |
24 | | #include "yb/util/random.h" |
25 | | #include "yb/util/result.h" |
26 | | #include "yb/util/test_macros.h" |
27 | | #include "yb/util/test_util.h" |
28 | | #include "yb/util/tsan_util.h" |
29 | | #include "yb/util/varint.h" |
30 | | |
31 | | using namespace std::literals; |
32 | | using strings::Substitute; |
33 | | using yb::FormatBytesAsStr; |
34 | | |
35 | | namespace yb { |
36 | | namespace util { |
37 | | |
38 | | namespace { |
39 | | |
40 | 22.1k | void CheckEncoding(int64_t v) { |
41 | 22.1k | SCOPED_TRACE(Substitute("v=$0", v)); |
42 | | |
43 | 22.1k | const string correct_encoded(VarInt(v).EncodeToComparable()); |
44 | 22.1k | uint8_t buf[16]; |
45 | 22.1k | size_t encoded_size = 0; |
46 | | |
47 | 22.1k | FastEncodeSignedVarInt(v, buf, &encoded_size); |
48 | 22.1k | ASSERT_EQ(correct_encoded.size(), encoded_size); |
49 | 22.1k | ASSERT_EQ(correct_encoded, string(to_char_ptr(buf), encoded_size)); |
50 | | |
51 | 22.1k | { |
52 | 22.1k | int64_t decoded = 0; |
53 | 22.1k | size_t decoded_size = 0; |
54 | 22.1k | ASSERT_OK(FastDecodeSignedVarIntUnsafe(correct_encoded, &decoded, &decoded_size)); |
55 | 22.1k | ASSERT_EQ(v, decoded); |
56 | 22.1k | ASSERT_EQ(correct_encoded.size(), decoded_size); |
57 | 22.1k | } |
58 | | |
59 | 22.1k | { |
60 | 22.1k | constexpr auto kPrefixSize = 4; |
61 | 22.1k | const auto encoded_prefixed = std::string(kPrefixSize, 'x') + correct_encoded; |
62 | 22.1k | int64_t decoded = 0; |
63 | 22.1k | size_t decoded_size = 0; |
64 | 22.1k | ASSERT_OK(FastDecodeSignedVarInt( |
65 | 22.1k | encoded_prefixed.c_str() + kPrefixSize, |
66 | 22.1k | correct_encoded.size(), |
67 | 22.1k | encoded_prefixed.c_str(), |
68 | 22.1k | &decoded, |
69 | 22.1k | &decoded_size)); |
70 | 22.1k | ASSERT_EQ(v, decoded); |
71 | 22.1k | ASSERT_EQ(correct_encoded.size(), decoded_size); |
72 | 22.1k | } |
73 | | |
74 | 22.1k | { |
75 | | // Provide a way to generate examples for checking value validity during decoding. These could |
76 | | // be copied and pasted into TestDecodeIncorrectValues. |
77 | 22.1k | int64_t unused_decoded_value ATTRIBUTE_UNUSED; |
78 | 22.1k | size_t unused_decoded_size ATTRIBUTE_UNUSED; |
79 | | |
80 | 22.1k | constexpr bool kGenerateInvalidDecodingExamples = false; |
81 | 22.1k | if (kGenerateInvalidDecodingExamples && |
82 | 0 | !FastDecodeSignedVarIntUnsafe( |
83 | 0 | buf + 1, encoded_size - 1, &unused_decoded_value, &unused_decoded_size).ok()) { |
84 | 0 | std::cout << "ASSERT_FALSE(FastDecodeSignedVarIntUnsafe(" |
85 | 0 | << FormatBytesAsStr(to_char_ptr(buf) + 1, encoded_size - 1) << ", " |
86 | 0 | << encoded_size - 1 << ", " |
87 | 0 | << "&v, &n).ok());" << std::endl; |
88 | 0 | } |
89 | 22.1k | } |
90 | | |
91 | | // Also test "descending varint" encoding. This is only makes sense for numbers that can be |
92 | | // negated (not the minimum possible 64-bit integer). |
93 | 22.1k | if (v != std::numeric_limits<int64_t>::min()) { |
94 | | // Our "descending varint" encoding is simply the encoding of the negated argument. |
95 | 22.1k | static const string kPrefix = "some_prefix"; |
96 | 22.1k | string encoded_dest = kPrefix; |
97 | 22.1k | FastEncodeDescendingSignedVarInt(-v, &encoded_dest); |
98 | 22.1k | const auto encoded_size = encoded_dest.size() - kPrefix.size(); |
99 | 22.1k | ASSERT_EQ(correct_encoded, |
100 | 22.1k | encoded_dest.substr(kPrefix.size(), encoded_size)); |
101 | | |
102 | 22.1k | Slice slice_for_decoding(encoded_dest.c_str() + kPrefix.size(), encoded_size); |
103 | 22.1k | int64_t decoded_value = 0; |
104 | 22.1k | ASSERT_OK(FastDecodeDescendingSignedVarIntUnsafe(&slice_for_decoding, &decoded_value)); |
105 | 22.1k | ASSERT_EQ(0, slice_for_decoding.size()); |
106 | 22.1k | ASSERT_EQ(-v, decoded_value); |
107 | 22.1k | } |
108 | 22.1k | } |
109 | | |
110 | | } // anonymous namespace |
111 | | |
112 | 1 | TEST(FastVarintTest, TestEncodeDecode) { |
113 | 1 | Random rng(SeedRandom()); |
114 | 1 | CheckEncoding(-1); |
115 | 64 | for (int i = 0; i <= 62; ++i) { |
116 | 63 | SCOPED_TRACE(Substitute("i (power of 2)=$0", i)); |
117 | 63 | CheckEncoding(1LL << i); |
118 | 63 | CheckEncoding((1LL << i) + 1); |
119 | 63 | CheckEncoding((1LL << i) - 1); |
120 | 63 | } |
121 | 1 | CheckEncoding(numeric_limits<int64_t>::max()); |
122 | 1 | CheckEncoding(numeric_limits<int64_t>::max() - 1); |
123 | 1 | CheckEncoding(numeric_limits<int64_t>::min()); |
124 | 1 | CheckEncoding(numeric_limits<int64_t>::min() + 1); |
125 | | |
126 | 10.0k | for (int i = 0; i < 10000; ++i) { |
127 | 10.0k | int64_t v = static_cast<int64_t>(rng.Next64()); |
128 | 30.0k | for (int m = 0; m < 2; ++m, v = -v) { |
129 | 20.0k | CheckEncoding(v); |
130 | 20.0k | } |
131 | 10.0k | } |
132 | | |
133 | 2.00k | for (int i = -1000; i <= 1000; ++i) { |
134 | 2.00k | CheckEncoding(i); |
135 | 2.00k | } |
136 | | |
137 | 1 | ASSERT_EQ(BINARY_STRING("\x80"), FastEncodeSignedVarIntToStr(0)); |
138 | 1 | ASSERT_EQ(BINARY_STRING("\x81"), FastEncodeSignedVarIntToStr(1)); |
139 | | // Many people don't know that "~" is \x7e. Did you know that? Very interesting! |
140 | 1 | ASSERT_EQ(BINARY_STRING("~"), FastEncodeSignedVarIntToStr(-1)); |
141 | 1 | ASSERT_EQ(BINARY_STRING("\xc0\x40"), FastEncodeSignedVarIntToStr(64)); |
142 | 1 | ASSERT_EQ(BINARY_STRING("\xdf\xff"), FastEncodeSignedVarIntToStr(8191)); |
143 | 1 | } |
144 | | |
145 | | template<class T> |
146 | 5 | std::vector<T> GenerateRandomValues(size_t values_per_length = NonTsanVsTsan(500000, 1000)) { |
147 | 5 | std::mt19937_64 rng(123456); |
148 | 5 | constexpr size_t kMinLength = 1; |
149 | 5 | constexpr size_t kMaxLength = 63; |
150 | 5 | std::vector<T> values; |
151 | 5 | values.reserve((kMaxLength - kMinLength + 1) * values_per_length); |
152 | 5 | uint64_t min_value = kMinLength == 1 ? 0 : 1ULL << (kMinLength - 1); |
153 | 5 | std::uniform_int_distribution<int> bool_dist(0, 1); |
154 | 320 | for (size_t i = kMinLength; i <= kMaxLength; ++i) { |
155 | 310 | uint64_t max_value = min_value ? min_value * 2 - 1 : 1; |
156 | 315 | std::uniform_int_distribution<T> distribution(min_value, max_value); |
157 | 126M | for (size_t j = values_per_length; j-- != 0;) { |
158 | 126M | if (std::is_signed<T>::value && bool_dist(rng)) { |
159 | 31.5M | values.push_back(-distribution(rng)); |
160 | 94.5M | } else { |
161 | 94.5M | values.push_back(distribution(rng)); |
162 | 94.5M | } |
163 | 126M | } |
164 | 315 | min_value = max_value + 1; |
165 | 315 | } |
166 | 5 | std::shuffle(values.begin(), values.end(), rng); |
167 | 5 | return values; |
168 | 5 | } _ZN2yb4util20GenerateRandomValuesIxEENSt3__16vectorIT_NS2_9allocatorIS4_EEEEm Line | Count | Source | 146 | 3 | std::vector<T> GenerateRandomValues(size_t values_per_length = NonTsanVsTsan(500000, 1000)) { | 147 | 3 | std::mt19937_64 rng(123456); | 148 | 3 | constexpr size_t kMinLength = 1; | 149 | 3 | constexpr size_t kMaxLength = 63; | 150 | 3 | std::vector<T> values; | 151 | 3 | values.reserve((kMaxLength - kMinLength + 1) * values_per_length); | 152 | 3 | uint64_t min_value = kMinLength == 1 ? 0 : 1ULL << (kMinLength - 1); | 153 | 3 | std::uniform_int_distribution<int> bool_dist(0, 1); | 154 | 192 | for (size_t i = kMinLength; i <= kMaxLength; ++i) { | 155 | 186 | uint64_t max_value = min_value ? min_value * 2 - 1 : 1; | 156 | 189 | std::uniform_int_distribution<T> distribution(min_value, max_value); | 157 | 63.0M | for (size_t j = values_per_length; j-- != 0;) { | 158 | 63.0M | if (std::is_signed<T>::value && bool_dist(rng)) { | 159 | 31.5M | values.push_back(-distribution(rng)); | 160 | 31.5M | } else { | 161 | 31.5M | values.push_back(distribution(rng)); | 162 | 31.5M | } | 163 | 63.0M | } | 164 | 189 | min_value = max_value + 1; | 165 | 189 | } | 166 | 3 | std::shuffle(values.begin(), values.end(), rng); | 167 | 3 | return values; | 168 | 3 | } |
_ZN2yb4util20GenerateRandomValuesIyEENSt3__16vectorIT_NS2_9allocatorIS4_EEEEm Line | Count | Source | 146 | 2 | std::vector<T> GenerateRandomValues(size_t values_per_length = NonTsanVsTsan(500000, 1000)) { | 147 | 2 | std::mt19937_64 rng(123456); | 148 | 2 | constexpr size_t kMinLength = 1; | 149 | 2 | constexpr size_t kMaxLength = 63; | 150 | 2 | std::vector<T> values; | 151 | 2 | values.reserve((kMaxLength - kMinLength + 1) * values_per_length); | 152 | 2 | uint64_t min_value = kMinLength == 1 ? 0 : 1ULL << (kMinLength - 1); | 153 | 2 | std::uniform_int_distribution<int> bool_dist(0, 1); | 154 | 128 | for (size_t i = kMinLength; i <= kMaxLength; ++i) { | 155 | 124 | uint64_t max_value = min_value ? min_value * 2 - 1 : 1; | 156 | 126 | std::uniform_int_distribution<T> distribution(min_value, max_value); | 157 | 63.0M | for (size_t j = values_per_length; j-- != 0;) { | 158 | 63.0M | if (std::is_signed<T>::value && bool_dist(rng)) { | 159 | 0 | values.push_back(-distribution(rng)); | 160 | 63.0M | } else { | 161 | 63.0M | values.push_back(distribution(rng)); | 162 | 63.0M | } | 163 | 63.0M | } | 164 | 126 | min_value = max_value + 1; | 165 | 126 | } | 166 | 2 | std::shuffle(values.begin(), values.end(), rng); | 167 | 2 | return values; | 168 | 2 | } |
|
169 | | |
170 | 1 | TEST(FastVarIntTest, TestEncodePerformance) { |
171 | 1 | const std::vector<int64_t> values = GenerateRandomValues<int64_t>(); |
172 | | |
173 | 1 | uint8_t buf[kMaxVarIntBufferSize]; |
174 | 1 | size_t encoded_size = 0; |
175 | 1 | std::clock_t start_time = std::clock(); |
176 | 31.5M | for (auto value : values) { |
177 | 31.5M | FastEncodeSignedVarInt(value, buf, &encoded_size); |
178 | 31.5M | } |
179 | 1 | std::clock_t end_time = std::clock(); |
180 | 1 | LOG(INFO) << std::fixed << std::setprecision(2) << "CPU time used: " |
181 | 1 | << 1000.0 * (end_time - start_time) / CLOCKS_PER_SEC << " ms\n"; |
182 | 1 | } |
183 | | |
184 | 1 | TEST(FastVarIntTest, TestSignedPositiveVarIntLength) { |
185 | 1 | ASSERT_EQ(1, SignedPositiveVarIntLength(0)); |
186 | 1 | ASSERT_EQ(1, SignedPositiveVarIntLength(63)); |
187 | 1 | ASSERT_EQ(2, SignedPositiveVarIntLength(64)); |
188 | | |
189 | 1 | int n_bits; |
190 | 1 | int n_bytes; |
191 | 10 | for (n_bits = 6, n_bytes = 1; n_bits <= 62; n_bits += 7, n_bytes += 1) { |
192 | 9 | const int64_t max_with_this_n_bytes = (1LL << n_bits) - 1; |
193 | 9 | ASSERT_EQ(n_bytes, SignedPositiveVarIntLength(max_with_this_n_bytes)); |
194 | 9 | ASSERT_EQ(n_bytes + 1, SignedPositiveVarIntLength(max_with_this_n_bytes + 1)); |
195 | 9 | } |
196 | 1 | } |
197 | | |
198 | 2 | const std::vector<std::string>& IncorrectValues() { |
199 | 2 | static std::vector<std::string> result = { |
200 | 2 | ""s, |
201 | 2 | "0"s, |
202 | 2 | "1"s, |
203 | 2 | "<"s, |
204 | 2 | "="s, |
205 | 2 | ">"s, |
206 | 2 | " "s, |
207 | 2 | "-"s, |
208 | 2 | ","s, |
209 | 2 | ";"s, |
210 | 2 | ":"s, |
211 | 2 | "!"s, |
212 | 2 | "?"s, |
213 | 2 | "/"s, |
214 | 2 | "."s, |
215 | 2 | "'"s, |
216 | 2 | "("s, |
217 | 2 | ")"s, |
218 | 2 | "$"s, |
219 | 2 | "*"s, |
220 | 2 | "\""s, |
221 | 2 | "&"s, |
222 | 2 | "#"s, |
223 | 2 | "%"s, |
224 | 2 | "+"s, |
225 | 2 | "2"s, |
226 | 2 | "3"s, |
227 | 2 | "4"s, |
228 | 2 | "5"s, |
229 | 2 | "6"s, |
230 | 2 | "7"s, |
231 | 2 | "8"s, |
232 | 2 | "9"s, |
233 | 2 | "\x00"s, |
234 | 2 | "\x00\x00"s, |
235 | 2 | "\x00\x00\x00"s, |
236 | 2 | "\x00\x00\x00\x00"s, |
237 | 2 | "\x00\x00\x00\x00\x00"s, |
238 | 2 | "\x00\x00\x00\x00\x01"s, |
239 | 2 | "\x00\x00\x00\x01"s, |
240 | 2 | "\x00\x00\x01"s, |
241 | 2 | "\x00\x01"s, |
242 | 2 | "\x01"s, |
243 | 2 | "\x02"s, |
244 | 2 | "\x03"s, |
245 | 2 | "\x04"s, |
246 | 2 | "\x05"s, |
247 | 2 | "\x06"s, |
248 | 2 | "\x07"s, |
249 | 2 | "\x08"s, |
250 | 2 | "\x09"s, |
251 | 2 | "\x0a"s, |
252 | 2 | "\x0b"s, |
253 | 2 | "\x0c"s, |
254 | 2 | "\x0d"s, |
255 | 2 | "\x0e"s, |
256 | 2 | "\x0f"s, |
257 | 2 | "\x10"s, |
258 | 2 | "\x11"s, |
259 | 2 | "\x12"s, |
260 | 2 | "\x13"s, |
261 | 2 | "\x14"s, |
262 | 2 | "\x15"s, |
263 | 2 | "\x16"s, |
264 | 2 | "\x17"s, |
265 | 2 | "\x18"s, |
266 | 2 | "\x19"s, |
267 | 2 | "\x1a"s, |
268 | 2 | "\x1b"s, |
269 | 2 | "\x1c"s, |
270 | 2 | "\x1d"s, |
271 | 2 | "\x1e"s, |
272 | 2 | "\x1f"s, |
273 | 2 | "\xc0"s, |
274 | 2 | "\xc1"s, |
275 | 2 | "\xc2"s, |
276 | 2 | "\xc3"s, |
277 | 2 | "\xc4"s, |
278 | 2 | "\xc5"s, |
279 | 2 | "\xc6"s, |
280 | 2 | "\xc7"s, |
281 | 2 | "\xc8"s, |
282 | 2 | "\xc9"s, |
283 | 2 | "\xca"s, |
284 | 2 | "\xcb"s, |
285 | 2 | "\xcc"s, |
286 | 2 | "\xcd"s, |
287 | 2 | "\xce"s, |
288 | 2 | "\xcf"s, |
289 | 2 | "\xd0"s, |
290 | 2 | "\xd1"s, |
291 | 2 | "\xd2"s, |
292 | 2 | "\xd3"s, |
293 | 2 | "\xd4"s, |
294 | 2 | "\xd5"s, |
295 | 2 | "\xd6"s, |
296 | 2 | "\xd7"s, |
297 | 2 | "\xd8"s, |
298 | 2 | "\xd9"s, |
299 | 2 | "\xda"s, |
300 | 2 | "\xdb"s, |
301 | 2 | "\xdc"s, |
302 | 2 | "\xdd"s, |
303 | 2 | "\xde"s, |
304 | 2 | "\xdf"s, |
305 | 2 | "\xe0"s, |
306 | 2 | "\xe1"s, |
307 | 2 | "\xe2"s, |
308 | 2 | "\xe3"s, |
309 | 2 | "\xe4"s, |
310 | 2 | "\xe5"s, |
311 | 2 | "\xe6"s, |
312 | 2 | "\xe7"s, |
313 | 2 | "\xe8"s, |
314 | 2 | "\xe9"s, |
315 | 2 | "\xea"s, |
316 | 2 | "\xeb"s, |
317 | 2 | "\xec"s, |
318 | 2 | "\xed"s, |
319 | 2 | "\xee"s, |
320 | 2 | "\xef"s, |
321 | 2 | "\xf0"s, |
322 | 2 | "\xf1"s, |
323 | 2 | "\xf2"s, |
324 | 2 | "\xf3"s, |
325 | 2 | "\xf4"s, |
326 | 2 | "\xf5"s, |
327 | 2 | "\xf6"s, |
328 | 2 | "\xf7"s, |
329 | 2 | "\xf8"s, |
330 | 2 | "\xf9"s, |
331 | 2 | "\xfa"s, |
332 | 2 | "\xfb"s, |
333 | 2 | "\xfc"s, |
334 | 2 | "\xfd"s, |
335 | 2 | "\xfe"s, |
336 | 2 | "\xff"s, |
337 | 2 | "\xff\xff"s, |
338 | 2 | "\xff\xff\xff"s, |
339 | 2 | "\xff\xff\xff\xff"s, |
340 | 2 | "\xff\xff\xff\xff\xff"s, |
341 | 2 | "\xff\xff\xff\xff\xff\xff"s, |
342 | 2 | "\x00\x00\x00\x00\x00+g!J"s |
343 | 2 | }; |
344 | 2 | return result; |
345 | 2 | } |
346 | | |
347 | 1 | TEST(FastVarIntTest, TestDecodeIncorrectValues) { |
348 | 1 | int64_t v; |
349 | 1 | size_t n; |
350 | 1 | const auto& incorrect_values = IncorrectValues(); |
351 | 143 | for (const auto& value : incorrect_values) { |
352 | 286 | ASSERT_NOK(FastDecodeSignedVarIntUnsafe(value, &v, &n)) |
353 | 286 | << "Input: " << Slice(value).ToDebugHexString(); |
354 | 143 | } |
355 | 1 | } |
356 | | |
357 | 2 | void CheckUnsignedEncoding(uint64_t value) { |
358 | 2 | uint8_t buf[kMaxVarIntBufferSize]; |
359 | 2 | size_t size = 0; |
360 | 2 | FastEncodeUnsignedVarInt(value, buf, &size); |
361 | 2 | uint64_t decoded_value; |
362 | 2 | size_t decoded_size = 0; |
363 | 2 | ASSERT_OK(FastDecodeUnsignedVarInt(buf, size, &decoded_value, &decoded_size)); |
364 | 2 | ASSERT_EQ(value, decoded_value); |
365 | 4 | ASSERT_EQ(size, decoded_size) << "Value is: " << value; |
366 | 2 | } |
367 | | |
368 | 1 | TEST(FastVarIntTest, Unsigned) { |
369 | 1 | std::mt19937_64 rng(123456); |
370 | 1 | const int kTotalValues = 1000000; |
371 | | |
372 | 1 | std::vector<uint64_t> values(kTotalValues); |
373 | 1 | std::vector<uint8_t> big_buffer(kTotalValues * kMaxVarIntBufferSize); |
374 | 1 | std::vector<Slice> encoded_values(kTotalValues); |
375 | | |
376 | 1 | VarInt varint; |
377 | 1.00M | for (int i = 0; i != kTotalValues; ++i) { |
378 | 1.00M | uint64_t len = std::uniform_int_distribution<uint64_t>(1, 10)(rng); |
379 | 899k | uint64_t max_value = len == 10 ? std::numeric_limits<uint64_t>::max() : (1ULL << (7 * len)) - 1; |
380 | 1.00M | uint64_t value = std::uniform_int_distribution<uint64_t>(0, max_value)(rng); |
381 | 1.00M | values[i] = value; |
382 | 1.00M | uint8_t* buf = big_buffer.data() + kMaxVarIntBufferSize * i; |
383 | 1.00M | size_t size = 0; |
384 | 1.00M | FastEncodeUnsignedVarInt(value, buf, &size); |
385 | 1.00M | encoded_values[i] = Slice(buf, size); |
386 | 1.00M | uint64_t decoded_value; |
387 | 1.00M | size_t decoded_size = 0; |
388 | 1.00M | ASSERT_OK(FastDecodeUnsignedVarInt(buf, size, &decoded_value, &decoded_size)); |
389 | 1.00M | ASSERT_EQ(value, decoded_value); |
390 | 2.00M | ASSERT_EQ(size, decoded_size) << "Value is: " << value; |
391 | 1.00M | } |
392 | 1 | CheckUnsignedEncoding(numeric_limits<uint64_t>::max()); |
393 | 1 | CheckUnsignedEncoding(numeric_limits<uint64_t>::max() - 1); |
394 | | |
395 | 1 | std::sort(values.begin(), values.end()); |
396 | 22.5M | auto compare_slices = [](const Slice& lhs, const Slice& rhs) { |
397 | 22.5M | return lhs.compare(rhs) < 0; |
398 | 22.5M | }; |
399 | 1 | std::sort(encoded_values.begin(), encoded_values.end(), compare_slices); |
400 | 1.00M | for (size_t i = 0; i != kTotalValues; ++i) { |
401 | 1.00M | auto decoded_value = FastDecodeUnsignedVarInt(&encoded_values[i]); |
402 | 1.00M | ASSERT_OK(decoded_value); |
403 | 1.00M | ASSERT_EQ(values[i], *decoded_value); |
404 | 1.00M | } |
405 | 1 | } |
406 | | |
407 | 1 | TEST(FastVarIntTest, DecodeUnsignedIncorrect) { |
408 | 1 | const auto& incorrect_values = IncorrectValues(); |
409 | 143 | for (const auto& value : incorrect_values) { |
410 | | // Values with leading zero bit are correctly decoded in unsigned mode. |
411 | 143 | if (value.size() == 1 && (value[0] & 0x80) == 0) { |
412 | 64 | continue; |
413 | 64 | } |
414 | 158 | ASSERT_NOK(FastDecodeUnsignedVarInt(value)) << "Input: " << Slice(value).ToDebugHexString(); |
415 | 79 | } |
416 | 1 | } |
417 | | |
418 | 1 | TEST(FastVarIntTest, EncodeUnsignedPerformance) { |
419 | 1 | const std::vector<uint64_t> values = GenerateRandomValues<uint64_t>(); |
420 | | |
421 | 1 | uint8_t buf[kMaxVarIntBufferSize]; |
422 | 1 | size_t encoded_size = 0; |
423 | 1 | std::clock_t start_time = std::clock(); |
424 | 31.5M | for (auto value : values) { |
425 | 31.5M | FastEncodeUnsignedVarInt(value, buf, &encoded_size); |
426 | 31.5M | } |
427 | 1 | std::clock_t end_time = std::clock(); |
428 | 1 | LOG(INFO) << std::fixed << std::setprecision(2) << "CPU time used: " |
429 | 1 | << 1000.0 * (end_time - start_time) / CLOCKS_PER_SEC << " ms\n"; |
430 | 1 | } |
431 | | |
432 | | template <class T> |
433 | 2 | void TestDecodeDescendingSignedPerformance() { |
434 | 2 | auto values = GenerateRandomValues<T>(); |
435 | | |
436 | 2 | std::vector<char> buf(kMaxVarIntBufferSize * values.size()); |
437 | 2 | std::vector<char*> bounds; |
438 | 2 | bounds.reserve(values.size()); |
439 | 2 | char* pos = buf.data(); |
440 | 63.0M | for (auto value : values) { |
441 | 63.0M | pos = FastEncodeDescendingSignedVarInt(value, pos); |
442 | 63.0M | bounds.push_back(pos); |
443 | 63.0M | } |
444 | 2 | LOG(INFO) << "Start measure"; |
445 | 2 | std::clock_t start_time = std::clock(); |
446 | 28 | for (int i = 0; i != 25; ++i) { |
447 | 26 | auto prev = buf.data(); |
448 | 787M | for (auto cur : bounds) { |
449 | 787M | Slice slice(prev, cur); |
450 | 787M | int64_t value; |
451 | 787M | ASSERT_OK_FAST(FastDecodeDescendingSignedVarIntUnsafe(&slice, &value)); |
452 | 787M | prev = cur; |
453 | 787M | } |
454 | 26 | } |
455 | 2 | std::clock_t end_time = std::clock(); |
456 | 2 | LOG(INFO) << std::fixed << std::setprecision(2) << "CPU time used: " |
457 | 2 | << 1000.0 * (end_time - start_time) / CLOCKS_PER_SEC << " ms\n"; |
458 | 2 | } _ZN2yb4util37TestDecodeDescendingSignedPerformanceIxEEvv Line | Count | Source | 433 | 1 | void TestDecodeDescendingSignedPerformance() { | 434 | 1 | auto values = GenerateRandomValues<T>(); | 435 | | | 436 | 1 | std::vector<char> buf(kMaxVarIntBufferSize * values.size()); | 437 | 1 | std::vector<char*> bounds; | 438 | 1 | bounds.reserve(values.size()); | 439 | 1 | char* pos = buf.data(); | 440 | 31.5M | for (auto value : values) { | 441 | 31.5M | pos = FastEncodeDescendingSignedVarInt(value, pos); | 442 | 31.5M | bounds.push_back(pos); | 443 | 31.5M | } | 444 | 1 | LOG(INFO) << "Start measure"; | 445 | 1 | std::clock_t start_time = std::clock(); | 446 | 26 | for (int i = 0; i != 25; ++i) { | 447 | 25 | auto prev = buf.data(); | 448 | 787M | for (auto cur : bounds) { | 449 | 787M | Slice slice(prev, cur); | 450 | 787M | int64_t value; | 451 | 787M | ASSERT_OK_FAST(FastDecodeDescendingSignedVarIntUnsafe(&slice, &value)); | 452 | 787M | prev = cur; | 453 | 787M | } | 454 | 25 | } | 455 | 1 | std::clock_t end_time = std::clock(); | 456 | 1 | LOG(INFO) << std::fixed << std::setprecision(2) << "CPU time used: " | 457 | 1 | << 1000.0 * (end_time - start_time) / CLOCKS_PER_SEC << " ms\n"; | 458 | 1 | } |
_ZN2yb4util37TestDecodeDescendingSignedPerformanceIyEEvv Line | Count | Source | 433 | 1 | void TestDecodeDescendingSignedPerformance() { | 434 | 1 | auto values = GenerateRandomValues<T>(); | 435 | | | 436 | 1 | std::vector<char> buf(kMaxVarIntBufferSize * values.size()); | 437 | 1 | std::vector<char*> bounds; | 438 | 1 | bounds.reserve(values.size()); | 439 | 1 | char* pos = buf.data(); | 440 | 31.5M | for (auto value : values) { | 441 | 31.5M | pos = FastEncodeDescendingSignedVarInt(value, pos); | 442 | 31.5M | bounds.push_back(pos); | 443 | 31.5M | } | 444 | 1 | LOG(INFO) << "Start measure"; | 445 | 1 | std::clock_t start_time = std::clock(); | 446 | 2 | for (int i = 0; i != 25; ++i) { | 447 | 1 | auto prev = buf.data(); | 448 | 1 | for (auto cur : bounds) { | 449 | 1 | Slice slice(prev, cur); | 450 | 1 | int64_t value; | 451 | 1 | ASSERT_OK_FAST(FastDecodeDescendingSignedVarIntUnsafe(&slice, &value)); | 452 | 1 | prev = cur; | 453 | 1 | } | 454 | 1 | } | 455 | 1 | std::clock_t end_time = std::clock(); | 456 | 1 | LOG(INFO) << std::fixed << std::setprecision(2) << "CPU time used: " | 457 | 1 | << 1000.0 * (end_time - start_time) / CLOCKS_PER_SEC << " ms\n"; | 458 | 1 | } |
|
459 | | |
460 | 1 | TEST(FastVarIntTest, DecodeDescendingSignedPerformance) { |
461 | 1 | TestDecodeDescendingSignedPerformance<int64_t>(); |
462 | 1 | } |
463 | | |
464 | 1 | TEST(FastVarIntTest, DecodeDescendingSignedPerformancePositiveValues) { |
465 | 1 | TestDecodeDescendingSignedPerformance<uint64_t>(); |
466 | 1 | } |
467 | | |
468 | 1 | TEST(FastVarIntTest, DecodeDescendingSignedCheck) { |
469 | 1 | auto values = GenerateRandomValues<int64_t>(500); |
470 | | |
471 | 1 | char buffer[kMaxVarIntBufferSize]; |
472 | 31.5k | for (auto value : values) { |
473 | 31.5k | SCOPED_TRACE(Format("Value: $0", value)); |
474 | 31.5k | auto end = FastEncodeDescendingSignedVarInt(value, buffer); |
475 | 31.5k | Slice slice(buffer, end); |
476 | 31.5k | auto decoded_value = ASSERT_RESULT_FAST(FastDecodeDescendingSignedVarIntUnsafe(&slice)); |
477 | 31.5k | ASSERT_TRUE(slice.empty()); |
478 | 31.5k | ASSERT_EQ(value, decoded_value); |
479 | 31.5k | } |
480 | 1 | } |
481 | | |
482 | | } // namespace util |
483 | | } // namespace yb |