Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2662)

Unified Diff: base/metrics/sample_vector_unittest.cc

Issue 2811713003: Embed a single sample in histogram metadata. (Closed)
Patch Set: rebased Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/metrics/sample_vector.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/metrics/sample_vector_unittest.cc
diff --git a/base/metrics/sample_vector_unittest.cc b/base/metrics/sample_vector_unittest.cc
index 2d77d2376b83a7442fd2e0929e5e21d832d6ba88..9616c00e782f849bca1af70a355723e0c161a9c0 100644
--- a/base/metrics/sample_vector_unittest.cc
+++ b/base/metrics/sample_vector_unittest.cc
@@ -7,18 +7,29 @@
#include <limits.h>
#include <stddef.h>
+#include <atomic>
#include <memory>
#include <vector>
#include "base/metrics/bucket_ranges.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/persistent_memory_allocator.h"
#include "base/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
-namespace {
-TEST(SampleVectorTest, AccumulateTest) {
+// This framework class has "friend" access to the SampleVector for accessing
+// non-public methods and fields.
+class SampleVectorTest : public testing::Test {
+ public:
+ const HistogramBase::AtomicCount* GetSamplesCounts(
+ const SampleVectorBase& samples) {
+ return samples.counts();
+ }
+};
+
+TEST_F(SampleVectorTest, Accumulate) {
// Custom buckets: [1, 5) [5, 10)
BucketRanges ranges(3);
ranges.set_range(0, 1);
@@ -45,7 +56,7 @@ TEST(SampleVectorTest, AccumulateTest) {
EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
}
-TEST(SampleVectorTest, Accumulate_LargeValuesDontOverflow) {
+TEST_F(SampleVectorTest, Accumulate_LargeValuesDontOverflow) {
// Custom buckets: [1, 250000000) [250000000, 500000000)
BucketRanges ranges(3);
ranges.set_range(0, 1);
@@ -72,7 +83,7 @@ TEST(SampleVectorTest, Accumulate_LargeValuesDontOverflow) {
EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
}
-TEST(SampleVectorTest, AddSubtractTest) {
+TEST_F(SampleVectorTest, AddSubtract) {
// Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX)
BucketRanges ranges(5);
ranges.set_range(0, 0);
@@ -116,7 +127,7 @@ TEST(SampleVectorTest, AddSubtractTest) {
EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
}
-TEST(SampleVectorDeathTest, BucketIndexTest) {
+TEST_F(SampleVectorTest, BucketIndexDeath) {
// 8 buckets with exponential layout:
// [0, 1) [1, 2) [2, 4) [4, 8) [8, 16) [16, 32) [32, 64) [64, INT_MAX)
BucketRanges ranges(9);
@@ -158,7 +169,7 @@ TEST(SampleVectorDeathTest, BucketIndexTest) {
EXPECT_DCHECK_DEATH(samples2.Accumulate(10, 100));
}
-TEST(SampleVectorDeathTest, AddSubtractBucketNotMatchTest) {
+TEST_F(SampleVectorTest, AddSubtractBucketNotMatchDeath) {
// Custom buckets 1: [1, 3) [3, 5)
BucketRanges ranges1(3);
ranges1.set_range(0, 1);
@@ -197,7 +208,7 @@ TEST(SampleVectorDeathTest, AddSubtractBucketNotMatchTest) {
EXPECT_DCHECK_DEATH(samples1.Subtract(samples2));
}
-TEST(SampleVectorIteratorTest, IterateTest) {
+TEST_F(SampleVectorTest, Iterate) {
BucketRanges ranges(5);
ranges.set_range(0, 0);
ranges.set_range(1, 1);
@@ -257,7 +268,7 @@ TEST(SampleVectorIteratorTest, IterateTest) {
EXPECT_EQ(4, i);
}
-TEST(SampleVectorIteratorDeathTest, IterateDoneTest) {
+TEST_F(SampleVectorTest, IterateDoneDeath) {
BucketRanges ranges(5);
ranges.set_range(0, 0);
ranges.set_range(1, 1);
@@ -282,5 +293,251 @@ TEST(SampleVectorIteratorDeathTest, IterateDoneTest) {
EXPECT_FALSE(it->Done());
}
-} // namespace
+TEST_F(SampleVectorTest, SingleSample) {
+ // Custom buckets: [1, 5) [5, 10)
+ BucketRanges ranges(3);
+ ranges.set_range(0, 1);
+ ranges.set_range(1, 5);
+ ranges.set_range(2, 10);
+ SampleVector samples(&ranges);
+
+ // Ensure that a single value accumulates correctly.
+ EXPECT_FALSE(GetSamplesCounts(samples));
+ samples.Accumulate(3, 200);
+ EXPECT_EQ(200, samples.GetCount(3));
+ EXPECT_FALSE(GetSamplesCounts(samples));
+ samples.Accumulate(3, 400);
+ EXPECT_EQ(600, samples.GetCount(3));
+ EXPECT_FALSE(GetSamplesCounts(samples));
+ EXPECT_EQ(3 * 600, samples.sum());
+ EXPECT_EQ(600, samples.TotalCount());
+ EXPECT_EQ(600, samples.redundant_count());
+
+ // Ensure that the iterator returns only one value.
+ HistogramBase::Sample min;
+ HistogramBase::Sample max;
+ HistogramBase::Count count;
+ std::unique_ptr<SampleCountIterator> it = samples.Iterator();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(1, min);
+ EXPECT_EQ(5, max);
+ EXPECT_EQ(600, count);
+ it->Next();
+ EXPECT_TRUE(it->Done());
+
+ // Ensure that it can be merged to another single-sample vector.
+ SampleVector samples_copy(&ranges);
+ samples_copy.Add(samples);
+ EXPECT_FALSE(GetSamplesCounts(samples_copy));
+ EXPECT_EQ(3 * 600, samples_copy.sum());
+ EXPECT_EQ(600, samples_copy.TotalCount());
+ EXPECT_EQ(600, samples_copy.redundant_count());
+
+ // A different value should cause creation of the counts array.
+ samples.Accumulate(8, 100);
+ EXPECT_TRUE(GetSamplesCounts(samples));
+ EXPECT_EQ(600, samples.GetCount(3));
+ EXPECT_EQ(100, samples.GetCount(8));
+ EXPECT_EQ(3 * 600 + 8 * 100, samples.sum());
+ EXPECT_EQ(600 + 100, samples.TotalCount());
+ EXPECT_EQ(600 + 100, samples.redundant_count());
+
+ // The iterator should now return both values.
+ it = samples.Iterator();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(1, min);
+ EXPECT_EQ(5, max);
+ EXPECT_EQ(600, count);
+ it->Next();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(5, min);
+ EXPECT_EQ(10, max);
+ EXPECT_EQ(100, count);
+ it->Next();
+ EXPECT_TRUE(it->Done());
+
+ // Ensure that it can merged to a single-sample vector.
+ samples_copy.Add(samples);
+ EXPECT_TRUE(GetSamplesCounts(samples_copy));
+ EXPECT_EQ(3 * 1200 + 8 * 100, samples_copy.sum());
+ EXPECT_EQ(1200 + 100, samples_copy.TotalCount());
+ EXPECT_EQ(1200 + 100, samples_copy.redundant_count());
+}
+
+TEST_F(SampleVectorTest, PersistentSampleVector) {
+ LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");
+ std::atomic<PersistentMemoryAllocator::Reference> samples_ref;
+ samples_ref.store(0, std::memory_order_relaxed);
+ HistogramSamples::Metadata samples_meta;
+ memset(&samples_meta, 0, sizeof(samples_meta));
+
+ // Custom buckets: [1, 5) [5, 10)
+ BucketRanges ranges(3);
+ ranges.set_range(0, 1);
+ ranges.set_range(1, 5);
+ ranges.set_range(2, 10);
+
+ // Persistent allocation.
+ const size_t counts_bytes =
+ sizeof(HistogramBase::AtomicCount) * ranges.bucket_count();
+ const DelayedPersistentAllocation allocation(&allocator, &samples_ref, 1,
+ counts_bytes, false);
+
+ PersistentSampleVector samples1(0, &ranges, &samples_meta, allocation);
+ EXPECT_FALSE(GetSamplesCounts(samples1));
+ samples1.Accumulate(3, 200);
+ EXPECT_EQ(200, samples1.GetCount(3));
+ EXPECT_FALSE(GetSamplesCounts(samples1));
+ EXPECT_EQ(0, samples1.GetCount(8));
+ EXPECT_FALSE(GetSamplesCounts(samples1));
+
+ PersistentSampleVector samples2(0, &ranges, &samples_meta, allocation);
+ EXPECT_EQ(200, samples2.GetCount(3));
+ EXPECT_FALSE(GetSamplesCounts(samples2));
+
+ HistogramBase::Sample min;
+ HistogramBase::Sample max;
+ HistogramBase::Count count;
+ std::unique_ptr<SampleCountIterator> it = samples2.Iterator();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(1, min);
+ EXPECT_EQ(5, max);
+ EXPECT_EQ(200, count);
+ it->Next();
+ EXPECT_TRUE(it->Done());
+
+ samples1.Accumulate(8, 100);
+ EXPECT_TRUE(GetSamplesCounts(samples1));
+
+ EXPECT_FALSE(GetSamplesCounts(samples2));
+ EXPECT_EQ(200, samples2.GetCount(3));
+ EXPECT_EQ(100, samples2.GetCount(8));
+ EXPECT_TRUE(GetSamplesCounts(samples2));
+ EXPECT_EQ(3 * 200 + 8 * 100, samples2.sum());
+ EXPECT_EQ(300, samples2.TotalCount());
+ EXPECT_EQ(300, samples2.redundant_count());
+
+ it = samples2.Iterator();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(1, min);
+ EXPECT_EQ(5, max);
+ EXPECT_EQ(200, count);
+ it->Next();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(5, min);
+ EXPECT_EQ(10, max);
+ EXPECT_EQ(100, count);
+ it->Next();
+ EXPECT_TRUE(it->Done());
+
+ PersistentSampleVector samples3(0, &ranges, &samples_meta, allocation);
+ EXPECT_TRUE(GetSamplesCounts(samples2));
+ EXPECT_EQ(200, samples3.GetCount(3));
+ EXPECT_EQ(100, samples3.GetCount(8));
+ EXPECT_EQ(3 * 200 + 8 * 100, samples3.sum());
+ EXPECT_EQ(300, samples3.TotalCount());
+ EXPECT_EQ(300, samples3.redundant_count());
+
+ it = samples3.Iterator();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(1, min);
+ EXPECT_EQ(5, max);
+ EXPECT_EQ(200, count);
+ it->Next();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(5, min);
+ EXPECT_EQ(10, max);
+ EXPECT_EQ(100, count);
+ it->Next();
+ EXPECT_TRUE(it->Done());
+}
+
+TEST_F(SampleVectorTest, PersistentSampleVectorTestWithOutsideAlloc) {
+ LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");
+ std::atomic<PersistentMemoryAllocator::Reference> samples_ref;
+ samples_ref.store(0, std::memory_order_relaxed);
+ HistogramSamples::Metadata samples_meta;
+ memset(&samples_meta, 0, sizeof(samples_meta));
+
+ // Custom buckets: [1, 5) [5, 10)
+ BucketRanges ranges(3);
+ ranges.set_range(0, 1);
+ ranges.set_range(1, 5);
+ ranges.set_range(2, 10);
+
+ // Persistent allocation.
+ const size_t counts_bytes =
+ sizeof(HistogramBase::AtomicCount) * ranges.bucket_count();
+ const DelayedPersistentAllocation allocation(&allocator, &samples_ref, 1,
+ counts_bytes, false);
+
+ PersistentSampleVector samples1(0, &ranges, &samples_meta, allocation);
+ EXPECT_FALSE(GetSamplesCounts(samples1));
+ samples1.Accumulate(3, 200);
+ EXPECT_EQ(200, samples1.GetCount(3));
+ EXPECT_FALSE(GetSamplesCounts(samples1));
+
+ // Because the delayed allocation can be shared with other objects (the
+ // |offset| parameter allows concatinating multiple data blocks into the
+ // same allocation), it's possible that the allocation gets realized from
+ // the outside even though the data block being accessed is all zero.
+ allocation.Get();
+ EXPECT_EQ(200, samples1.GetCount(3));
+ EXPECT_FALSE(GetSamplesCounts(samples1));
+
+ HistogramBase::Sample min;
+ HistogramBase::Sample max;
+ HistogramBase::Count count;
+ std::unique_ptr<SampleCountIterator> it = samples1.Iterator();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(1, min);
+ EXPECT_EQ(5, max);
+ EXPECT_EQ(200, count);
+ it->Next();
+ EXPECT_TRUE(it->Done());
+
+ // A duplicate samples object should still see the single-sample entry even
+ // when storage is available.
+ PersistentSampleVector samples2(0, &ranges, &samples_meta, allocation);
+ EXPECT_EQ(200, samples2.GetCount(3));
+
+ // New accumulations, in both directions, of the existing value should work.
+ samples1.Accumulate(3, 50);
+ EXPECT_EQ(250, samples1.GetCount(3));
+ EXPECT_EQ(250, samples2.GetCount(3));
+ samples2.Accumulate(3, 50);
+ EXPECT_EQ(300, samples1.GetCount(3));
+ EXPECT_EQ(300, samples2.GetCount(3));
+
+ it = samples1.Iterator();
+ ASSERT_FALSE(it->Done());
+ it->Get(&min, &max, &count);
+ EXPECT_EQ(1, min);
+ EXPECT_EQ(5, max);
+ EXPECT_EQ(300, count);
+ it->Next();
+ EXPECT_TRUE(it->Done());
+
+ samples1.Accumulate(8, 100);
+ EXPECT_TRUE(GetSamplesCounts(samples1));
+ EXPECT_EQ(300, samples1.GetCount(3));
+ EXPECT_EQ(300, samples2.GetCount(3));
+ EXPECT_EQ(100, samples1.GetCount(8));
+ EXPECT_EQ(100, samples2.GetCount(8));
+ samples2.Accumulate(8, 100);
+ EXPECT_EQ(300, samples1.GetCount(3));
+ EXPECT_EQ(300, samples2.GetCount(3));
+ EXPECT_EQ(200, samples1.GetCount(8));
+ EXPECT_EQ(200, samples2.GetCount(8));
+}
+
} // namespace base
« no previous file with comments | « base/metrics/sample_vector.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698