OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/metrics/sample_vector.h" | 5 #include "base/metrics/sample_vector.h" |
6 | 6 |
7 #include <limits.h> | 7 #include <limits.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <atomic> | |
11 #include <memory> | 10 #include <memory> |
12 #include <vector> | 11 #include <vector> |
13 | 12 |
14 #include "base/metrics/bucket_ranges.h" | 13 #include "base/metrics/bucket_ranges.h" |
15 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
16 #include "base/metrics/persistent_memory_allocator.h" | |
17 #include "base/test/gtest_util.h" | 15 #include "base/test/gtest_util.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
19 | 17 |
20 namespace base { | 18 namespace base { |
| 19 namespace { |
21 | 20 |
22 // This framework class has "friend" access to the SampleVector for accessing | 21 TEST(SampleVectorTest, AccumulateTest) { |
23 // non-public methods and fields. | |
24 class SampleVectorTest : public testing::Test { | |
25 public: | |
26 const HistogramBase::AtomicCount* GetSamplesCounts( | |
27 const SampleVectorBase& samples) { | |
28 return samples.counts(); | |
29 } | |
30 }; | |
31 | |
32 TEST_F(SampleVectorTest, Accumulate) { | |
33 // Custom buckets: [1, 5) [5, 10) | 22 // Custom buckets: [1, 5) [5, 10) |
34 BucketRanges ranges(3); | 23 BucketRanges ranges(3); |
35 ranges.set_range(0, 1); | 24 ranges.set_range(0, 1); |
36 ranges.set_range(1, 5); | 25 ranges.set_range(1, 5); |
37 ranges.set_range(2, 10); | 26 ranges.set_range(2, 10); |
38 SampleVector samples(1, &ranges); | 27 SampleVector samples(1, &ranges); |
39 | 28 |
40 samples.Accumulate(1, 200); | 29 samples.Accumulate(1, 200); |
41 samples.Accumulate(2, -300); | 30 samples.Accumulate(2, -300); |
42 EXPECT_EQ(-100, samples.GetCountAtIndex(0)); | 31 EXPECT_EQ(-100, samples.GetCountAtIndex(0)); |
43 | 32 |
44 samples.Accumulate(5, 200); | 33 samples.Accumulate(5, 200); |
45 EXPECT_EQ(200, samples.GetCountAtIndex(1)); | 34 EXPECT_EQ(200, samples.GetCountAtIndex(1)); |
46 | 35 |
47 EXPECT_EQ(600, samples.sum()); | 36 EXPECT_EQ(600, samples.sum()); |
48 EXPECT_EQ(100, samples.redundant_count()); | 37 EXPECT_EQ(100, samples.redundant_count()); |
49 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); | 38 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); |
50 | 39 |
51 samples.Accumulate(5, -100); | 40 samples.Accumulate(5, -100); |
52 EXPECT_EQ(100, samples.GetCountAtIndex(1)); | 41 EXPECT_EQ(100, samples.GetCountAtIndex(1)); |
53 | 42 |
54 EXPECT_EQ(100, samples.sum()); | 43 EXPECT_EQ(100, samples.sum()); |
55 EXPECT_EQ(0, samples.redundant_count()); | 44 EXPECT_EQ(0, samples.redundant_count()); |
56 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); | 45 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); |
57 } | 46 } |
58 | 47 |
59 TEST_F(SampleVectorTest, Accumulate_LargeValuesDontOverflow) { | 48 TEST(SampleVectorTest, Accumulate_LargeValuesDontOverflow) { |
60 // Custom buckets: [1, 250000000) [250000000, 500000000) | 49 // Custom buckets: [1, 250000000) [250000000, 500000000) |
61 BucketRanges ranges(3); | 50 BucketRanges ranges(3); |
62 ranges.set_range(0, 1); | 51 ranges.set_range(0, 1); |
63 ranges.set_range(1, 250000000); | 52 ranges.set_range(1, 250000000); |
64 ranges.set_range(2, 500000000); | 53 ranges.set_range(2, 500000000); |
65 SampleVector samples(1, &ranges); | 54 SampleVector samples(1, &ranges); |
66 | 55 |
67 samples.Accumulate(240000000, 200); | 56 samples.Accumulate(240000000, 200); |
68 samples.Accumulate(249999999, -300); | 57 samples.Accumulate(249999999, -300); |
69 EXPECT_EQ(-100, samples.GetCountAtIndex(0)); | 58 EXPECT_EQ(-100, samples.GetCountAtIndex(0)); |
70 | 59 |
71 samples.Accumulate(250000000, 200); | 60 samples.Accumulate(250000000, 200); |
72 EXPECT_EQ(200, samples.GetCountAtIndex(1)); | 61 EXPECT_EQ(200, samples.GetCountAtIndex(1)); |
73 | 62 |
74 EXPECT_EQ(23000000300LL, samples.sum()); | 63 EXPECT_EQ(23000000300LL, samples.sum()); |
75 EXPECT_EQ(100, samples.redundant_count()); | 64 EXPECT_EQ(100, samples.redundant_count()); |
76 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); | 65 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); |
77 | 66 |
78 samples.Accumulate(250000000, -100); | 67 samples.Accumulate(250000000, -100); |
79 EXPECT_EQ(100, samples.GetCountAtIndex(1)); | 68 EXPECT_EQ(100, samples.GetCountAtIndex(1)); |
80 | 69 |
81 EXPECT_EQ(-1999999700LL, samples.sum()); | 70 EXPECT_EQ(-1999999700LL, samples.sum()); |
82 EXPECT_EQ(0, samples.redundant_count()); | 71 EXPECT_EQ(0, samples.redundant_count()); |
83 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); | 72 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); |
84 } | 73 } |
85 | 74 |
86 TEST_F(SampleVectorTest, AddSubtract) { | 75 TEST(SampleVectorTest, AddSubtractTest) { |
87 // Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX) | 76 // Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX) |
88 BucketRanges ranges(5); | 77 BucketRanges ranges(5); |
89 ranges.set_range(0, 0); | 78 ranges.set_range(0, 0); |
90 ranges.set_range(1, 1); | 79 ranges.set_range(1, 1); |
91 ranges.set_range(2, 2); | 80 ranges.set_range(2, 2); |
92 ranges.set_range(3, 3); | 81 ranges.set_range(3, 3); |
93 ranges.set_range(4, INT_MAX); | 82 ranges.set_range(4, INT_MAX); |
94 | 83 |
95 SampleVector samples1(1, &ranges); | 84 SampleVector samples1(1, &ranges); |
96 samples1.Accumulate(0, 100); | 85 samples1.Accumulate(0, 100); |
(...skipping 23 matching lines...) Expand all Loading... |
120 samples1.Subtract(samples2); | 109 samples1.Subtract(samples2); |
121 EXPECT_EQ(100, samples1.GetCountAtIndex(0)); | 110 EXPECT_EQ(100, samples1.GetCountAtIndex(0)); |
122 EXPECT_EQ(0, samples1.GetCountAtIndex(1)); | 111 EXPECT_EQ(0, samples1.GetCountAtIndex(1)); |
123 EXPECT_EQ(100, samples1.GetCountAtIndex(2)); | 112 EXPECT_EQ(100, samples1.GetCountAtIndex(2)); |
124 EXPECT_EQ(100, samples1.GetCountAtIndex(3)); | 113 EXPECT_EQ(100, samples1.GetCountAtIndex(3)); |
125 EXPECT_EQ(600, samples1.sum()); | 114 EXPECT_EQ(600, samples1.sum()); |
126 EXPECT_EQ(300, samples1.TotalCount()); | 115 EXPECT_EQ(300, samples1.TotalCount()); |
127 EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); | 116 EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); |
128 } | 117 } |
129 | 118 |
130 TEST_F(SampleVectorTest, BucketIndexDeath) { | 119 TEST(SampleVectorDeathTest, BucketIndexTest) { |
131 // 8 buckets with exponential layout: | 120 // 8 buckets with exponential layout: |
132 // [0, 1) [1, 2) [2, 4) [4, 8) [8, 16) [16, 32) [32, 64) [64, INT_MAX) | 121 // [0, 1) [1, 2) [2, 4) [4, 8) [8, 16) [16, 32) [32, 64) [64, INT_MAX) |
133 BucketRanges ranges(9); | 122 BucketRanges ranges(9); |
134 Histogram::InitializeBucketRanges(1, 64, &ranges); | 123 Histogram::InitializeBucketRanges(1, 64, &ranges); |
135 SampleVector samples(1, &ranges); | 124 SampleVector samples(1, &ranges); |
136 | 125 |
137 // Normal case | 126 // Normal case |
138 samples.Accumulate(0, 1); | 127 samples.Accumulate(0, 1); |
139 samples.Accumulate(3, 2); | 128 samples.Accumulate(3, 2); |
140 samples.Accumulate(64, 3); | 129 samples.Accumulate(64, 3); |
(...skipping 21 matching lines...) Expand all Loading... |
162 samples2.Accumulate(5, 2); | 151 samples2.Accumulate(5, 2); |
163 samples2.Accumulate(9, 2); | 152 samples2.Accumulate(9, 2); |
164 EXPECT_EQ(2, samples2.GetCount(1)); | 153 EXPECT_EQ(2, samples2.GetCount(1)); |
165 EXPECT_EQ(4, samples2.GetCount(5)); | 154 EXPECT_EQ(4, samples2.GetCount(5)); |
166 | 155 |
167 // Extreme case. | 156 // Extreme case. |
168 EXPECT_DCHECK_DEATH(samples2.Accumulate(0, 100)); | 157 EXPECT_DCHECK_DEATH(samples2.Accumulate(0, 100)); |
169 EXPECT_DCHECK_DEATH(samples2.Accumulate(10, 100)); | 158 EXPECT_DCHECK_DEATH(samples2.Accumulate(10, 100)); |
170 } | 159 } |
171 | 160 |
172 TEST_F(SampleVectorTest, AddSubtractBucketNotMatchDeath) { | 161 TEST(SampleVectorDeathTest, AddSubtractBucketNotMatchTest) { |
173 // Custom buckets 1: [1, 3) [3, 5) | 162 // Custom buckets 1: [1, 3) [3, 5) |
174 BucketRanges ranges1(3); | 163 BucketRanges ranges1(3); |
175 ranges1.set_range(0, 1); | 164 ranges1.set_range(0, 1); |
176 ranges1.set_range(1, 3); | 165 ranges1.set_range(1, 3); |
177 ranges1.set_range(2, 5); | 166 ranges1.set_range(2, 5); |
178 SampleVector samples1(1, &ranges1); | 167 SampleVector samples1(1, &ranges1); |
179 | 168 |
180 // Custom buckets 2: [0, 1) [1, 3) [3, 6) [6, 7) | 169 // Custom buckets 2: [0, 1) [1, 3) [3, 6) [6, 7) |
181 BucketRanges ranges2(5); | 170 BucketRanges ranges2(5); |
182 ranges2.set_range(0, 0); | 171 ranges2.set_range(0, 0); |
(...skipping 18 matching lines...) Expand all Loading... |
201 EXPECT_DCHECK_DEATH(samples1.Add(samples2)); | 190 EXPECT_DCHECK_DEATH(samples1.Add(samples2)); |
202 EXPECT_DCHECK_DEATH(samples1.Subtract(samples2)); | 191 EXPECT_DCHECK_DEATH(samples1.Subtract(samples2)); |
203 | 192 |
204 // Bucket not match: [3, 5) VS [3, 6) | 193 // Bucket not match: [3, 5) VS [3, 6) |
205 samples2.Accumulate(6, -100); | 194 samples2.Accumulate(6, -100); |
206 samples2.Accumulate(3, 100); | 195 samples2.Accumulate(3, 100); |
207 EXPECT_DCHECK_DEATH(samples1.Add(samples2)); | 196 EXPECT_DCHECK_DEATH(samples1.Add(samples2)); |
208 EXPECT_DCHECK_DEATH(samples1.Subtract(samples2)); | 197 EXPECT_DCHECK_DEATH(samples1.Subtract(samples2)); |
209 } | 198 } |
210 | 199 |
211 TEST_F(SampleVectorTest, Iterate) { | 200 TEST(SampleVectorIteratorTest, IterateTest) { |
212 BucketRanges ranges(5); | 201 BucketRanges ranges(5); |
213 ranges.set_range(0, 0); | 202 ranges.set_range(0, 0); |
214 ranges.set_range(1, 1); | 203 ranges.set_range(1, 1); |
215 ranges.set_range(2, 2); | 204 ranges.set_range(2, 2); |
216 ranges.set_range(3, 3); | 205 ranges.set_range(3, 3); |
217 ranges.set_range(4, 4); | 206 ranges.set_range(4, 4); |
218 | 207 |
219 std::vector<HistogramBase::Count> counts(3); | 208 std::vector<HistogramBase::Count> counts(3); |
220 counts[0] = 1; | 209 counts[0] = 1; |
221 counts[1] = 0; // Iterator will bypass this empty bucket. | 210 counts[1] = 0; // Iterator will bypass this empty bucket. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 EXPECT_EQ(i + 1, max); | 250 EXPECT_EQ(i + 1, max); |
262 EXPECT_EQ(i, count); | 251 EXPECT_EQ(i, count); |
263 | 252 |
264 size_t index; | 253 size_t index; |
265 EXPECT_TRUE(it2->GetBucketIndex(&index)); | 254 EXPECT_TRUE(it2->GetBucketIndex(&index)); |
266 EXPECT_EQ(static_cast<size_t>(i), index); | 255 EXPECT_EQ(static_cast<size_t>(i), index); |
267 } | 256 } |
268 EXPECT_EQ(4, i); | 257 EXPECT_EQ(4, i); |
269 } | 258 } |
270 | 259 |
271 TEST_F(SampleVectorTest, IterateDoneDeath) { | 260 TEST(SampleVectorIteratorDeathTest, IterateDoneTest) { |
272 BucketRanges ranges(5); | 261 BucketRanges ranges(5); |
273 ranges.set_range(0, 0); | 262 ranges.set_range(0, 0); |
274 ranges.set_range(1, 1); | 263 ranges.set_range(1, 1); |
275 ranges.set_range(2, 2); | 264 ranges.set_range(2, 2); |
276 ranges.set_range(3, 3); | 265 ranges.set_range(3, 3); |
277 ranges.set_range(4, INT_MAX); | 266 ranges.set_range(4, INT_MAX); |
278 SampleVector samples(1, &ranges); | 267 SampleVector samples(1, &ranges); |
279 | 268 |
280 std::unique_ptr<SampleCountIterator> it = samples.Iterator(); | 269 std::unique_ptr<SampleCountIterator> it = samples.Iterator(); |
281 | 270 |
282 EXPECT_TRUE(it->Done()); | 271 EXPECT_TRUE(it->Done()); |
283 | 272 |
284 HistogramBase::Sample min; | 273 HistogramBase::Sample min; |
285 HistogramBase::Sample max; | 274 HistogramBase::Sample max; |
286 HistogramBase::Count count; | 275 HistogramBase::Count count; |
287 EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count)); | 276 EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count)); |
288 | 277 |
289 EXPECT_DCHECK_DEATH(it->Next()); | 278 EXPECT_DCHECK_DEATH(it->Next()); |
290 | 279 |
291 samples.Accumulate(2, 100); | 280 samples.Accumulate(2, 100); |
292 it = samples.Iterator(); | 281 it = samples.Iterator(); |
293 EXPECT_FALSE(it->Done()); | 282 EXPECT_FALSE(it->Done()); |
294 } | 283 } |
295 | 284 |
296 TEST_F(SampleVectorTest, SingleSample) { | 285 } // namespace |
297 // Custom buckets: [1, 5) [5, 10) | |
298 BucketRanges ranges(3); | |
299 ranges.set_range(0, 1); | |
300 ranges.set_range(1, 5); | |
301 ranges.set_range(2, 10); | |
302 SampleVector samples(&ranges); | |
303 | |
304 // Ensure that a single value accumulates correctly. | |
305 EXPECT_FALSE(GetSamplesCounts(samples)); | |
306 samples.Accumulate(3, 200); | |
307 EXPECT_EQ(200, samples.GetCount(3)); | |
308 EXPECT_FALSE(GetSamplesCounts(samples)); | |
309 samples.Accumulate(3, 400); | |
310 EXPECT_EQ(600, samples.GetCount(3)); | |
311 EXPECT_FALSE(GetSamplesCounts(samples)); | |
312 EXPECT_EQ(3 * 600, samples.sum()); | |
313 EXPECT_EQ(600, samples.TotalCount()); | |
314 EXPECT_EQ(600, samples.redundant_count()); | |
315 | |
316 // Ensure that the iterator returns only one value. | |
317 HistogramBase::Sample min; | |
318 HistogramBase::Sample max; | |
319 HistogramBase::Count count; | |
320 std::unique_ptr<SampleCountIterator> it = samples.Iterator(); | |
321 ASSERT_FALSE(it->Done()); | |
322 it->Get(&min, &max, &count); | |
323 EXPECT_EQ(1, min); | |
324 EXPECT_EQ(5, max); | |
325 EXPECT_EQ(600, count); | |
326 it->Next(); | |
327 EXPECT_TRUE(it->Done()); | |
328 | |
329 // Ensure that it can be merged to another single-sample vector. | |
330 SampleVector samples_copy(&ranges); | |
331 samples_copy.Add(samples); | |
332 EXPECT_FALSE(GetSamplesCounts(samples_copy)); | |
333 EXPECT_EQ(3 * 600, samples_copy.sum()); | |
334 EXPECT_EQ(600, samples_copy.TotalCount()); | |
335 EXPECT_EQ(600, samples_copy.redundant_count()); | |
336 | |
337 // A different value should cause creation of the counts array. | |
338 samples.Accumulate(8, 100); | |
339 EXPECT_TRUE(GetSamplesCounts(samples)); | |
340 EXPECT_EQ(600, samples.GetCount(3)); | |
341 EXPECT_EQ(100, samples.GetCount(8)); | |
342 EXPECT_EQ(3 * 600 + 8 * 100, samples.sum()); | |
343 EXPECT_EQ(600 + 100, samples.TotalCount()); | |
344 EXPECT_EQ(600 + 100, samples.redundant_count()); | |
345 | |
346 // The iterator should now return both values. | |
347 it = samples.Iterator(); | |
348 ASSERT_FALSE(it->Done()); | |
349 it->Get(&min, &max, &count); | |
350 EXPECT_EQ(1, min); | |
351 EXPECT_EQ(5, max); | |
352 EXPECT_EQ(600, count); | |
353 it->Next(); | |
354 ASSERT_FALSE(it->Done()); | |
355 it->Get(&min, &max, &count); | |
356 EXPECT_EQ(5, min); | |
357 EXPECT_EQ(10, max); | |
358 EXPECT_EQ(100, count); | |
359 it->Next(); | |
360 EXPECT_TRUE(it->Done()); | |
361 | |
362 // Ensure that it can merged to a single-sample vector. | |
363 samples_copy.Add(samples); | |
364 EXPECT_TRUE(GetSamplesCounts(samples_copy)); | |
365 EXPECT_EQ(3 * 1200 + 8 * 100, samples_copy.sum()); | |
366 EXPECT_EQ(1200 + 100, samples_copy.TotalCount()); | |
367 EXPECT_EQ(1200 + 100, samples_copy.redundant_count()); | |
368 } | |
369 | |
370 TEST_F(SampleVectorTest, PersistentSampleVector) { | |
371 LocalPersistentMemoryAllocator allocator(64 << 10, 0, ""); | |
372 std::atomic<PersistentMemoryAllocator::Reference> samples_ref; | |
373 samples_ref.store(0, std::memory_order_relaxed); | |
374 HistogramSamples::Metadata samples_meta; | |
375 memset(&samples_meta, 0, sizeof(samples_meta)); | |
376 | |
377 // Custom buckets: [1, 5) [5, 10) | |
378 BucketRanges ranges(3); | |
379 ranges.set_range(0, 1); | |
380 ranges.set_range(1, 5); | |
381 ranges.set_range(2, 10); | |
382 | |
383 // Persistent allocation. | |
384 const size_t counts_bytes = | |
385 sizeof(HistogramBase::AtomicCount) * ranges.bucket_count(); | |
386 const DelayedPersistentAllocation allocation(&allocator, &samples_ref, 1, | |
387 counts_bytes, false); | |
388 | |
389 PersistentSampleVector samples1(0, &ranges, &samples_meta, allocation); | |
390 EXPECT_FALSE(GetSamplesCounts(samples1)); | |
391 samples1.Accumulate(3, 200); | |
392 EXPECT_EQ(200, samples1.GetCount(3)); | |
393 EXPECT_FALSE(GetSamplesCounts(samples1)); | |
394 EXPECT_EQ(0, samples1.GetCount(8)); | |
395 EXPECT_FALSE(GetSamplesCounts(samples1)); | |
396 | |
397 PersistentSampleVector samples2(0, &ranges, &samples_meta, allocation); | |
398 EXPECT_EQ(200, samples2.GetCount(3)); | |
399 EXPECT_FALSE(GetSamplesCounts(samples2)); | |
400 | |
401 HistogramBase::Sample min; | |
402 HistogramBase::Sample max; | |
403 HistogramBase::Count count; | |
404 std::unique_ptr<SampleCountIterator> it = samples2.Iterator(); | |
405 ASSERT_FALSE(it->Done()); | |
406 it->Get(&min, &max, &count); | |
407 EXPECT_EQ(1, min); | |
408 EXPECT_EQ(5, max); | |
409 EXPECT_EQ(200, count); | |
410 it->Next(); | |
411 EXPECT_TRUE(it->Done()); | |
412 | |
413 samples1.Accumulate(8, 100); | |
414 EXPECT_TRUE(GetSamplesCounts(samples1)); | |
415 | |
416 EXPECT_FALSE(GetSamplesCounts(samples2)); | |
417 EXPECT_EQ(200, samples2.GetCount(3)); | |
418 EXPECT_EQ(100, samples2.GetCount(8)); | |
419 EXPECT_TRUE(GetSamplesCounts(samples2)); | |
420 EXPECT_EQ(3 * 200 + 8 * 100, samples2.sum()); | |
421 EXPECT_EQ(300, samples2.TotalCount()); | |
422 EXPECT_EQ(300, samples2.redundant_count()); | |
423 | |
424 it = samples2.Iterator(); | |
425 ASSERT_FALSE(it->Done()); | |
426 it->Get(&min, &max, &count); | |
427 EXPECT_EQ(1, min); | |
428 EXPECT_EQ(5, max); | |
429 EXPECT_EQ(200, count); | |
430 it->Next(); | |
431 ASSERT_FALSE(it->Done()); | |
432 it->Get(&min, &max, &count); | |
433 EXPECT_EQ(5, min); | |
434 EXPECT_EQ(10, max); | |
435 EXPECT_EQ(100, count); | |
436 it->Next(); | |
437 EXPECT_TRUE(it->Done()); | |
438 | |
439 PersistentSampleVector samples3(0, &ranges, &samples_meta, allocation); | |
440 EXPECT_TRUE(GetSamplesCounts(samples2)); | |
441 EXPECT_EQ(200, samples3.GetCount(3)); | |
442 EXPECT_EQ(100, samples3.GetCount(8)); | |
443 EXPECT_EQ(3 * 200 + 8 * 100, samples3.sum()); | |
444 EXPECT_EQ(300, samples3.TotalCount()); | |
445 EXPECT_EQ(300, samples3.redundant_count()); | |
446 | |
447 it = samples3.Iterator(); | |
448 ASSERT_FALSE(it->Done()); | |
449 it->Get(&min, &max, &count); | |
450 EXPECT_EQ(1, min); | |
451 EXPECT_EQ(5, max); | |
452 EXPECT_EQ(200, count); | |
453 it->Next(); | |
454 ASSERT_FALSE(it->Done()); | |
455 it->Get(&min, &max, &count); | |
456 EXPECT_EQ(5, min); | |
457 EXPECT_EQ(10, max); | |
458 EXPECT_EQ(100, count); | |
459 it->Next(); | |
460 EXPECT_TRUE(it->Done()); | |
461 } | |
462 | |
463 TEST_F(SampleVectorTest, PersistentSampleVectorTestWithOutsideAlloc) { | |
464 LocalPersistentMemoryAllocator allocator(64 << 10, 0, ""); | |
465 std::atomic<PersistentMemoryAllocator::Reference> samples_ref; | |
466 samples_ref.store(0, std::memory_order_relaxed); | |
467 HistogramSamples::Metadata samples_meta; | |
468 memset(&samples_meta, 0, sizeof(samples_meta)); | |
469 | |
470 // Custom buckets: [1, 5) [5, 10) | |
471 BucketRanges ranges(3); | |
472 ranges.set_range(0, 1); | |
473 ranges.set_range(1, 5); | |
474 ranges.set_range(2, 10); | |
475 | |
476 // Persistent allocation. | |
477 const size_t counts_bytes = | |
478 sizeof(HistogramBase::AtomicCount) * ranges.bucket_count(); | |
479 const DelayedPersistentAllocation allocation(&allocator, &samples_ref, 1, | |
480 counts_bytes, false); | |
481 | |
482 PersistentSampleVector samples1(0, &ranges, &samples_meta, allocation); | |
483 EXPECT_FALSE(GetSamplesCounts(samples1)); | |
484 samples1.Accumulate(3, 200); | |
485 EXPECT_EQ(200, samples1.GetCount(3)); | |
486 EXPECT_FALSE(GetSamplesCounts(samples1)); | |
487 | |
488 // Because the delayed allocation can be shared with other objects (the | |
489 // |offset| parameter allows concatinating multiple data blocks into the | |
490 // same allocation), it's possible that the allocation gets realized from | |
491 // the outside even though the data block being accessed is all zero. | |
492 allocation.Get(); | |
493 EXPECT_EQ(200, samples1.GetCount(3)); | |
494 EXPECT_FALSE(GetSamplesCounts(samples1)); | |
495 | |
496 HistogramBase::Sample min; | |
497 HistogramBase::Sample max; | |
498 HistogramBase::Count count; | |
499 std::unique_ptr<SampleCountIterator> it = samples1.Iterator(); | |
500 ASSERT_FALSE(it->Done()); | |
501 it->Get(&min, &max, &count); | |
502 EXPECT_EQ(1, min); | |
503 EXPECT_EQ(5, max); | |
504 EXPECT_EQ(200, count); | |
505 it->Next(); | |
506 EXPECT_TRUE(it->Done()); | |
507 | |
508 // A duplicate samples object should still see the single-sample entry even | |
509 // when storage is available. | |
510 PersistentSampleVector samples2(0, &ranges, &samples_meta, allocation); | |
511 EXPECT_EQ(200, samples2.GetCount(3)); | |
512 | |
513 // New accumulations, in both directions, of the existing value should work. | |
514 samples1.Accumulate(3, 50); | |
515 EXPECT_EQ(250, samples1.GetCount(3)); | |
516 EXPECT_EQ(250, samples2.GetCount(3)); | |
517 samples2.Accumulate(3, 50); | |
518 EXPECT_EQ(300, samples1.GetCount(3)); | |
519 EXPECT_EQ(300, samples2.GetCount(3)); | |
520 | |
521 it = samples1.Iterator(); | |
522 ASSERT_FALSE(it->Done()); | |
523 it->Get(&min, &max, &count); | |
524 EXPECT_EQ(1, min); | |
525 EXPECT_EQ(5, max); | |
526 EXPECT_EQ(300, count); | |
527 it->Next(); | |
528 EXPECT_TRUE(it->Done()); | |
529 | |
530 samples1.Accumulate(8, 100); | |
531 EXPECT_TRUE(GetSamplesCounts(samples1)); | |
532 EXPECT_EQ(300, samples1.GetCount(3)); | |
533 EXPECT_EQ(300, samples2.GetCount(3)); | |
534 EXPECT_EQ(100, samples1.GetCount(8)); | |
535 EXPECT_EQ(100, samples2.GetCount(8)); | |
536 samples2.Accumulate(8, 100); | |
537 EXPECT_EQ(300, samples1.GetCount(3)); | |
538 EXPECT_EQ(300, samples2.GetCount(3)); | |
539 EXPECT_EQ(200, samples1.GetCount(8)); | |
540 EXPECT_EQ(200, samples2.GetCount(8)); | |
541 } | |
542 | |
543 } // namespace base | 286 } // namespace base |
OLD | NEW |