| Index: base/metrics/sparse_histogram_unittest.cc
|
| diff --git a/base/metrics/sparse_histogram_unittest.cc b/base/metrics/sparse_histogram_unittest.cc
|
| index 7ad5558b64319d7e905f59494954624e7530b391..9f65c18ac6c8b81ad698a3a50d7f678a7699808f 100644
|
| --- a/base/metrics/sparse_histogram_unittest.cc
|
| +++ b/base/metrics/sparse_histogram_unittest.cc
|
| @@ -8,7 +8,9 @@
|
|
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/metrics/histogram_base.h"
|
| +#include "base/metrics/histogram_persistence.h"
|
| #include "base/metrics/histogram_samples.h"
|
| +#include "base/metrics/persistent_memory_allocator.h"
|
| #include "base/metrics/sample_map.h"
|
| #include "base/metrics/statistics_recorder.h"
|
| #include "base/pickle.h"
|
| @@ -17,17 +19,35 @@
|
|
|
| namespace base {
|
|
|
| -class SparseHistogramTest : public testing::Test {
|
| +// Test parameter indicates if a persistent memory allocator should be used
|
| +// for histogram allocation. False will allocate histograms from the process
|
| +// heap.
|
| +class SparseHistogramTest : public testing::TestWithParam<bool> {
|
| protected:
|
| + const int32_t kAllocatorMemorySize = 8 << 20; // 8 MiB
|
| +
|
| + SparseHistogramTest() : use_persistent_histogram_allocator_(GetParam()) {}
|
| +
|
| void SetUp() override {
|
| + if (use_persistent_histogram_allocator_)
|
| + CreatePersistentMemoryAllocator();
|
| +
|
| // Each test will have a clean state (no Histogram / BucketRanges
|
| // registered).
|
| InitializeStatisticsRecorder();
|
| }
|
|
|
| - void TearDown() override { UninitializeStatisticsRecorder(); }
|
| + void TearDown() override {
|
| + if (allocator_) {
|
| + ASSERT_FALSE(allocator_->IsFull());
|
| + ASSERT_FALSE(allocator_->IsCorrupt());
|
| + }
|
| + UninitializeStatisticsRecorder();
|
| + DestroyPersistentMemoryAllocator();
|
| + }
|
|
|
| void InitializeStatisticsRecorder() {
|
| + StatisticsRecorder::ResetForTesting();
|
| statistics_recorder_ = new StatisticsRecorder();
|
| }
|
|
|
| @@ -36,14 +56,46 @@ class SparseHistogramTest : public testing::Test {
|
| statistics_recorder_ = NULL;
|
| }
|
|
|
| + void CreatePersistentMemoryAllocator() {
|
| + if (!allocator_memory_)
|
| + allocator_memory_.reset(new char[kAllocatorMemorySize]);
|
| +
|
| + delete ReleasePersistentHistogramMemoryAllocatorForTesting();
|
| + memset(allocator_memory_.get(), 0, kAllocatorMemorySize);
|
| + GetCreateHistogramResultHistogram();
|
| + SetPersistentHistogramMemoryAllocator(
|
| + new PersistentMemoryAllocator(
|
| + allocator_memory_.get(), kAllocatorMemorySize, 0,
|
| + 0, "SparseHistogramTestAllocator", false));
|
| + allocator_ = GetPersistentHistogramMemoryAllocator();
|
| + }
|
| +
|
| + void DestroyPersistentMemoryAllocator() {
|
| + allocator_ = nullptr;
|
| + delete ReleasePersistentHistogramMemoryAllocatorForTesting();
|
| + }
|
| +
|
| scoped_ptr<SparseHistogram> NewSparseHistogram(const std::string& name) {
|
| return scoped_ptr<SparseHistogram>(new SparseHistogram(name));
|
| }
|
|
|
| + const bool use_persistent_histogram_allocator_;
|
| +
|
| StatisticsRecorder* statistics_recorder_;
|
| + scoped_ptr<char[]> allocator_memory_;
|
| + PersistentMemoryAllocator* allocator_ = nullptr;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(SparseHistogramTest);
|
| };
|
|
|
| -TEST_F(SparseHistogramTest, BasicTest) {
|
| +// Run all HistogramTest cases with both heap and persistent memory.
|
| +INSTANTIATE_TEST_CASE_P(HeapAndPersistent,
|
| + SparseHistogramTest,
|
| + testing::Bool());
|
| +
|
| +
|
| +TEST_P(SparseHistogramTest, BasicTest) {
|
| scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
|
| scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
|
| EXPECT_EQ(0, snapshot->TotalCount());
|
| @@ -62,7 +114,7 @@ TEST_F(SparseHistogramTest, BasicTest) {
|
| EXPECT_EQ(1, snapshot2->GetCount(101));
|
| }
|
|
|
| -TEST_F(SparseHistogramTest, BasicTestAddCount) {
|
| +TEST_P(SparseHistogramTest, BasicTestAddCount) {
|
| scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
|
| scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
|
| EXPECT_EQ(0, snapshot->TotalCount());
|
| @@ -81,7 +133,7 @@ TEST_F(SparseHistogramTest, BasicTestAddCount) {
|
| EXPECT_EQ(25, snapshot2->GetCount(101));
|
| }
|
|
|
| -TEST_F(SparseHistogramTest, AddCount_LargeValuesDontOverflow) {
|
| +TEST_P(SparseHistogramTest, AddCount_LargeValuesDontOverflow) {
|
| scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
|
| scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
|
| EXPECT_EQ(0, snapshot->TotalCount());
|
| @@ -101,7 +153,7 @@ TEST_F(SparseHistogramTest, AddCount_LargeValuesDontOverflow) {
|
| EXPECT_EQ(55250000000LL, snapshot2->sum());
|
| }
|
|
|
| -TEST_F(SparseHistogramTest, MacroBasicTest) {
|
| +TEST_P(SparseHistogramTest, MacroBasicTest) {
|
| UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 100);
|
| UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 200);
|
| UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 100);
|
| @@ -114,8 +166,11 @@ TEST_F(SparseHistogramTest, MacroBasicTest) {
|
|
|
| EXPECT_EQ(SPARSE_HISTOGRAM, sparse_histogram->GetHistogramType());
|
| EXPECT_EQ("Sparse", sparse_histogram->histogram_name());
|
| - EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag,
|
| - sparse_histogram->flags());
|
| + EXPECT_EQ(
|
| + HistogramBase::kUmaTargetedHistogramFlag |
|
| + (use_persistent_histogram_allocator_ ? HistogramBase::kIsPersistent
|
| + : 0),
|
| + sparse_histogram->flags());
|
|
|
| scoped_ptr<HistogramSamples> samples = sparse_histogram->SnapshotSamples();
|
| EXPECT_EQ(3, samples->TotalCount());
|
| @@ -123,7 +178,7 @@ TEST_F(SparseHistogramTest, MacroBasicTest) {
|
| EXPECT_EQ(1, samples->GetCount(200));
|
| }
|
|
|
| -TEST_F(SparseHistogramTest, MacroInLoopTest) {
|
| +TEST_P(SparseHistogramTest, MacroInLoopTest) {
|
| // Unlike the macros in histogram.h, SparseHistogram macros can have a
|
| // variable as histogram name.
|
| for (int i = 0; i < 2; i++) {
|
| @@ -141,7 +196,7 @@ TEST_F(SparseHistogramTest, MacroInLoopTest) {
|
| ("Sparse2" == name1 && "Sparse1" == name2));
|
| }
|
|
|
| -TEST_F(SparseHistogramTest, Serialize) {
|
| +TEST_P(SparseHistogramTest, Serialize) {
|
| scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
|
| histogram->SetFlags(HistogramBase::kIPCSerializationSourceFlag);
|
|
|
| @@ -166,4 +221,64 @@ TEST_F(SparseHistogramTest, Serialize) {
|
| EXPECT_FALSE(iter.SkipBytes(1));
|
| }
|
|
|
| +TEST_P(SparseHistogramTest, FactoryTime) {
|
| + const int kTestCreateCount = 1 << 10; // Must be power-of-2.
|
| + const int kTestLookupCount = 100000;
|
| + const int kTestAddCount = 100000;
|
| +
|
| + // Create all histogram names in advance for accurate timing below.
|
| + std::vector<std::string> histogram_names;
|
| + for (int i = 0; i < kTestCreateCount; ++i) {
|
| + histogram_names.push_back(
|
| + StringPrintf("TestHistogram.%d", i % kTestCreateCount));
|
| + }
|
| +
|
| + // Calculate cost of creating histograms.
|
| + TimeTicks create_start = TimeTicks::Now();
|
| + for (int i = 0; i < kTestCreateCount; ++i)
|
| + SparseHistogram::FactoryGet(histogram_names[i], HistogramBase::kNoFlags);
|
| + TimeDelta create_ticks = TimeTicks::Now() - create_start;
|
| + int64_t create_ms = create_ticks.InMilliseconds();
|
| +
|
| + VLOG(1) << kTestCreateCount << " histogram creations took " << create_ms
|
| + << "ms or about "
|
| + << (create_ms * 1000000) / kTestCreateCount
|
| + << "ns each.";
|
| +
|
| + // Calculate cost of looking up existing histograms.
|
| + TimeTicks lookup_start = TimeTicks::Now();
|
| + for (int i = 0; i < kTestLookupCount; ++i) {
|
| + // 6007 is co-prime with kTestCreateCount and so will do lookups in an
|
| + // order less likely to be cacheable (but still hit them all) should the
|
| + // underlying storage use the exact histogram name as the key.
|
| + const int i_mult = 6007;
|
| + static_assert(i_mult < INT_MAX / kTestCreateCount, "Multiplier too big");
|
| + int index = (i * i_mult) & (kTestCreateCount - 1);
|
| + SparseHistogram::FactoryGet(histogram_names[index],
|
| + HistogramBase::kNoFlags);
|
| + }
|
| + TimeDelta lookup_ticks = TimeTicks::Now() - lookup_start;
|
| + int64_t lookup_ms = lookup_ticks.InMilliseconds();
|
| +
|
| + VLOG(1) << kTestLookupCount << " histogram lookups took " << lookup_ms
|
| + << "ms or about "
|
| + << (lookup_ms * 1000000) / kTestLookupCount
|
| + << "ns each.";
|
| +
|
| + // Calculate cost of accessing histograms.
|
| + HistogramBase* histogram =
|
| + SparseHistogram::FactoryGet(histogram_names[0], HistogramBase::kNoFlags);
|
| + ASSERT_TRUE(histogram);
|
| + TimeTicks add_start = TimeTicks::Now();
|
| + for (int i = 0; i < kTestAddCount; ++i)
|
| + histogram->Add(i & 127);
|
| + TimeDelta add_ticks = TimeTicks::Now() - add_start;
|
| + int64_t add_ms = add_ticks.InMilliseconds();
|
| +
|
| + VLOG(1) << kTestAddCount << " histogram adds took " << add_ms
|
| + << "ms or about "
|
| + << (add_ms * 1000000) / kTestAddCount
|
| + << "ns each.";
|
| +}
|
| +
|
| } // namespace base
|
|
|