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..5d5dbcbb9b1fb6bc79871c83f84de0e4f748d703 100644 |
--- a/base/metrics/sparse_histogram_unittest.cc |
+++ b/base/metrics/sparse_histogram_unittest.cc |
@@ -9,6 +9,8 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/metrics/histogram_base.h" |
#include "base/metrics/histogram_samples.h" |
+#include "base/metrics/persistent_histogram_allocator.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,44 @@ class SparseHistogramTest : public testing::Test { |
statistics_recorder_ = NULL; |
} |
+ void CreatePersistentMemoryAllocator() { |
+ // By getting the results-histogram before any persistent allocator |
+ // is attached, that histogram is guaranteed not to be stored in |
+ // any persistent memory segment (which simplifies some tests). |
+ PersistentHistogramAllocator::GetCreateHistogramResultHistogram(); |
+ |
+ PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( |
+ kAllocatorMemorySize, 0, "SparseHistogramAllocatorTest"); |
+ allocator_ = |
+ PersistentHistogramAllocator::GetGlobalAllocator()->memory_allocator(); |
+ } |
+ |
+ void DestroyPersistentMemoryAllocator() { |
+ allocator_ = nullptr; |
+ PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting(); |
+ } |
+ |
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 +112,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 +131,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 +151,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 +164,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 +176,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 +194,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 +219,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 |