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

Side by Side Diff: base/metrics/sparse_histogram_unittest.cc

Issue 1734033003: Add support for persistent sparse histograms. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased Created 4 years, 9 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 unified diff | Download patch
« no previous file with comments | « base/metrics/sparse_histogram.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/sparse_histogram.h" 5 #include "base/metrics/sparse_histogram.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/histogram_base.h" 10 #include "base/metrics/histogram_base.h"
11 #include "base/metrics/histogram_samples.h" 11 #include "base/metrics/histogram_samples.h"
12 #include "base/metrics/persistent_histogram_allocator.h"
13 #include "base/metrics/persistent_memory_allocator.h"
12 #include "base/metrics/sample_map.h" 14 #include "base/metrics/sample_map.h"
13 #include "base/metrics/statistics_recorder.h" 15 #include "base/metrics/statistics_recorder.h"
14 #include "base/pickle.h" 16 #include "base/pickle.h"
15 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
17 19
18 namespace base { 20 namespace base {
19 21
20 class SparseHistogramTest : public testing::Test { 22 // Test parameter indicates if a persistent memory allocator should be used
23 // for histogram allocation. False will allocate histograms from the process
24 // heap.
25 class SparseHistogramTest : public testing::TestWithParam<bool> {
21 protected: 26 protected:
27 const int32_t kAllocatorMemorySize = 8 << 20; // 8 MiB
28
29 SparseHistogramTest() : use_persistent_histogram_allocator_(GetParam()) {}
30
22 void SetUp() override { 31 void SetUp() override {
32 if (use_persistent_histogram_allocator_)
33 CreatePersistentMemoryAllocator();
34
23 // Each test will have a clean state (no Histogram / BucketRanges 35 // Each test will have a clean state (no Histogram / BucketRanges
24 // registered). 36 // registered).
25 InitializeStatisticsRecorder(); 37 InitializeStatisticsRecorder();
26 } 38 }
27 39
28 void TearDown() override { UninitializeStatisticsRecorder(); } 40 void TearDown() override {
41 if (allocator_) {
42 ASSERT_FALSE(allocator_->IsFull());
43 ASSERT_FALSE(allocator_->IsCorrupt());
44 }
45 UninitializeStatisticsRecorder();
46 DestroyPersistentMemoryAllocator();
47 }
29 48
30 void InitializeStatisticsRecorder() { 49 void InitializeStatisticsRecorder() {
50 StatisticsRecorder::ResetForTesting();
31 statistics_recorder_ = new StatisticsRecorder(); 51 statistics_recorder_ = new StatisticsRecorder();
32 } 52 }
33 53
34 void UninitializeStatisticsRecorder() { 54 void UninitializeStatisticsRecorder() {
35 delete statistics_recorder_; 55 delete statistics_recorder_;
36 statistics_recorder_ = NULL; 56 statistics_recorder_ = NULL;
37 } 57 }
38 58
59 void CreatePersistentMemoryAllocator() {
60 // By getting the results-histogram before any persistent allocator
61 // is attached, that histogram is guaranteed not to be stored in
62 // any persistent memory segment (which simplifies some tests).
63 PersistentHistogramAllocator::GetCreateHistogramResultHistogram();
64
65 PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory(
66 kAllocatorMemorySize, 0, "SparseHistogramAllocatorTest");
67 allocator_ =
68 PersistentHistogramAllocator::GetGlobalAllocator()->memory_allocator();
69 }
70
71 void DestroyPersistentMemoryAllocator() {
72 allocator_ = nullptr;
73 PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting();
74 }
75
39 scoped_ptr<SparseHistogram> NewSparseHistogram(const std::string& name) { 76 scoped_ptr<SparseHistogram> NewSparseHistogram(const std::string& name) {
40 return scoped_ptr<SparseHistogram>(new SparseHistogram(name)); 77 return scoped_ptr<SparseHistogram>(new SparseHistogram(name));
41 } 78 }
42 79
80 const bool use_persistent_histogram_allocator_;
81
43 StatisticsRecorder* statistics_recorder_; 82 StatisticsRecorder* statistics_recorder_;
83 scoped_ptr<char[]> allocator_memory_;
84 PersistentMemoryAllocator* allocator_ = nullptr;
85
86 private:
87 DISALLOW_COPY_AND_ASSIGN(SparseHistogramTest);
44 }; 88 };
45 89
46 TEST_F(SparseHistogramTest, BasicTest) { 90 // Run all HistogramTest cases with both heap and persistent memory.
91 INSTANTIATE_TEST_CASE_P(HeapAndPersistent,
92 SparseHistogramTest,
93 testing::Bool());
94
95
96 TEST_P(SparseHistogramTest, BasicTest) {
47 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse")); 97 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
48 scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples()); 98 scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
49 EXPECT_EQ(0, snapshot->TotalCount()); 99 EXPECT_EQ(0, snapshot->TotalCount());
50 EXPECT_EQ(0, snapshot->sum()); 100 EXPECT_EQ(0, snapshot->sum());
51 101
52 histogram->Add(100); 102 histogram->Add(100);
53 scoped_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples()); 103 scoped_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
54 EXPECT_EQ(1, snapshot1->TotalCount()); 104 EXPECT_EQ(1, snapshot1->TotalCount());
55 EXPECT_EQ(1, snapshot1->GetCount(100)); 105 EXPECT_EQ(1, snapshot1->GetCount(100));
56 106
57 histogram->Add(100); 107 histogram->Add(100);
58 histogram->Add(101); 108 histogram->Add(101);
59 scoped_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples()); 109 scoped_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
60 EXPECT_EQ(3, snapshot2->TotalCount()); 110 EXPECT_EQ(3, snapshot2->TotalCount());
61 EXPECT_EQ(2, snapshot2->GetCount(100)); 111 EXPECT_EQ(2, snapshot2->GetCount(100));
62 EXPECT_EQ(1, snapshot2->GetCount(101)); 112 EXPECT_EQ(1, snapshot2->GetCount(101));
63 } 113 }
64 114
65 TEST_F(SparseHistogramTest, BasicTestAddCount) { 115 TEST_P(SparseHistogramTest, BasicTestAddCount) {
66 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse")); 116 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
67 scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples()); 117 scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
68 EXPECT_EQ(0, snapshot->TotalCount()); 118 EXPECT_EQ(0, snapshot->TotalCount());
69 EXPECT_EQ(0, snapshot->sum()); 119 EXPECT_EQ(0, snapshot->sum());
70 120
71 histogram->AddCount(100, 15); 121 histogram->AddCount(100, 15);
72 scoped_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples()); 122 scoped_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
73 EXPECT_EQ(15, snapshot1->TotalCount()); 123 EXPECT_EQ(15, snapshot1->TotalCount());
74 EXPECT_EQ(15, snapshot1->GetCount(100)); 124 EXPECT_EQ(15, snapshot1->GetCount(100));
75 125
76 histogram->AddCount(100, 15); 126 histogram->AddCount(100, 15);
77 histogram->AddCount(101, 25); 127 histogram->AddCount(101, 25);
78 scoped_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples()); 128 scoped_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
79 EXPECT_EQ(55, snapshot2->TotalCount()); 129 EXPECT_EQ(55, snapshot2->TotalCount());
80 EXPECT_EQ(30, snapshot2->GetCount(100)); 130 EXPECT_EQ(30, snapshot2->GetCount(100));
81 EXPECT_EQ(25, snapshot2->GetCount(101)); 131 EXPECT_EQ(25, snapshot2->GetCount(101));
82 } 132 }
83 133
84 TEST_F(SparseHistogramTest, AddCount_LargeValuesDontOverflow) { 134 TEST_P(SparseHistogramTest, AddCount_LargeValuesDontOverflow) {
85 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse")); 135 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
86 scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples()); 136 scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
87 EXPECT_EQ(0, snapshot->TotalCount()); 137 EXPECT_EQ(0, snapshot->TotalCount());
88 EXPECT_EQ(0, snapshot->sum()); 138 EXPECT_EQ(0, snapshot->sum());
89 139
90 histogram->AddCount(1000000000, 15); 140 histogram->AddCount(1000000000, 15);
91 scoped_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples()); 141 scoped_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
92 EXPECT_EQ(15, snapshot1->TotalCount()); 142 EXPECT_EQ(15, snapshot1->TotalCount());
93 EXPECT_EQ(15, snapshot1->GetCount(1000000000)); 143 EXPECT_EQ(15, snapshot1->GetCount(1000000000));
94 144
95 histogram->AddCount(1000000000, 15); 145 histogram->AddCount(1000000000, 15);
96 histogram->AddCount(1010000000, 25); 146 histogram->AddCount(1010000000, 25);
97 scoped_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples()); 147 scoped_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
98 EXPECT_EQ(55, snapshot2->TotalCount()); 148 EXPECT_EQ(55, snapshot2->TotalCount());
99 EXPECT_EQ(30, snapshot2->GetCount(1000000000)); 149 EXPECT_EQ(30, snapshot2->GetCount(1000000000));
100 EXPECT_EQ(25, snapshot2->GetCount(1010000000)); 150 EXPECT_EQ(25, snapshot2->GetCount(1010000000));
101 EXPECT_EQ(55250000000LL, snapshot2->sum()); 151 EXPECT_EQ(55250000000LL, snapshot2->sum());
102 } 152 }
103 153
104 TEST_F(SparseHistogramTest, MacroBasicTest) { 154 TEST_P(SparseHistogramTest, MacroBasicTest) {
105 UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 100); 155 UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 100);
106 UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 200); 156 UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 200);
107 UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 100); 157 UMA_HISTOGRAM_SPARSE_SLOWLY("Sparse", 100);
108 158
109 StatisticsRecorder::Histograms histograms; 159 StatisticsRecorder::Histograms histograms;
110 StatisticsRecorder::GetHistograms(&histograms); 160 StatisticsRecorder::GetHistograms(&histograms);
111 161
112 ASSERT_EQ(1U, histograms.size()); 162 ASSERT_EQ(1U, histograms.size());
113 HistogramBase* sparse_histogram = histograms[0]; 163 HistogramBase* sparse_histogram = histograms[0];
114 164
115 EXPECT_EQ(SPARSE_HISTOGRAM, sparse_histogram->GetHistogramType()); 165 EXPECT_EQ(SPARSE_HISTOGRAM, sparse_histogram->GetHistogramType());
116 EXPECT_EQ("Sparse", sparse_histogram->histogram_name()); 166 EXPECT_EQ("Sparse", sparse_histogram->histogram_name());
117 EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, 167 EXPECT_EQ(
118 sparse_histogram->flags()); 168 HistogramBase::kUmaTargetedHistogramFlag |
169 (use_persistent_histogram_allocator_ ? HistogramBase::kIsPersistent
170 : 0),
171 sparse_histogram->flags());
119 172
120 scoped_ptr<HistogramSamples> samples = sparse_histogram->SnapshotSamples(); 173 scoped_ptr<HistogramSamples> samples = sparse_histogram->SnapshotSamples();
121 EXPECT_EQ(3, samples->TotalCount()); 174 EXPECT_EQ(3, samples->TotalCount());
122 EXPECT_EQ(2, samples->GetCount(100)); 175 EXPECT_EQ(2, samples->GetCount(100));
123 EXPECT_EQ(1, samples->GetCount(200)); 176 EXPECT_EQ(1, samples->GetCount(200));
124 } 177 }
125 178
126 TEST_F(SparseHistogramTest, MacroInLoopTest) { 179 TEST_P(SparseHistogramTest, MacroInLoopTest) {
127 // Unlike the macros in histogram.h, SparseHistogram macros can have a 180 // Unlike the macros in histogram.h, SparseHistogram macros can have a
128 // variable as histogram name. 181 // variable as histogram name.
129 for (int i = 0; i < 2; i++) { 182 for (int i = 0; i < 2; i++) {
130 std::string name = StringPrintf("Sparse%d", i + 1); 183 std::string name = StringPrintf("Sparse%d", i + 1);
131 UMA_HISTOGRAM_SPARSE_SLOWLY(name, 100); 184 UMA_HISTOGRAM_SPARSE_SLOWLY(name, 100);
132 } 185 }
133 186
134 StatisticsRecorder::Histograms histograms; 187 StatisticsRecorder::Histograms histograms;
135 StatisticsRecorder::GetHistograms(&histograms); 188 StatisticsRecorder::GetHistograms(&histograms);
136 ASSERT_EQ(2U, histograms.size()); 189 ASSERT_EQ(2U, histograms.size());
137 190
138 std::string name1 = histograms[0]->histogram_name(); 191 std::string name1 = histograms[0]->histogram_name();
139 std::string name2 = histograms[1]->histogram_name(); 192 std::string name2 = histograms[1]->histogram_name();
140 EXPECT_TRUE(("Sparse1" == name1 && "Sparse2" == name2) || 193 EXPECT_TRUE(("Sparse1" == name1 && "Sparse2" == name2) ||
141 ("Sparse2" == name1 && "Sparse1" == name2)); 194 ("Sparse2" == name1 && "Sparse1" == name2));
142 } 195 }
143 196
144 TEST_F(SparseHistogramTest, Serialize) { 197 TEST_P(SparseHistogramTest, Serialize) {
145 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse")); 198 scoped_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
146 histogram->SetFlags(HistogramBase::kIPCSerializationSourceFlag); 199 histogram->SetFlags(HistogramBase::kIPCSerializationSourceFlag);
147 200
148 Pickle pickle; 201 Pickle pickle;
149 histogram->SerializeInfo(&pickle); 202 histogram->SerializeInfo(&pickle);
150 203
151 PickleIterator iter(pickle); 204 PickleIterator iter(pickle);
152 205
153 int type; 206 int type;
154 EXPECT_TRUE(iter.ReadInt(&type)); 207 EXPECT_TRUE(iter.ReadInt(&type));
155 EXPECT_EQ(SPARSE_HISTOGRAM, type); 208 EXPECT_EQ(SPARSE_HISTOGRAM, type);
156 209
157 std::string name; 210 std::string name;
158 EXPECT_TRUE(iter.ReadString(&name)); 211 EXPECT_TRUE(iter.ReadString(&name));
159 EXPECT_EQ("Sparse", name); 212 EXPECT_EQ("Sparse", name);
160 213
161 int flag; 214 int flag;
162 EXPECT_TRUE(iter.ReadInt(&flag)); 215 EXPECT_TRUE(iter.ReadInt(&flag));
163 EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag, flag); 216 EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag, flag);
164 217
165 // No more data in the pickle. 218 // No more data in the pickle.
166 EXPECT_FALSE(iter.SkipBytes(1)); 219 EXPECT_FALSE(iter.SkipBytes(1));
167 } 220 }
168 221
222 TEST_P(SparseHistogramTest, FactoryTime) {
223 const int kTestCreateCount = 1 << 10; // Must be power-of-2.
224 const int kTestLookupCount = 100000;
225 const int kTestAddCount = 100000;
226
227 // Create all histogram names in advance for accurate timing below.
228 std::vector<std::string> histogram_names;
229 for (int i = 0; i < kTestCreateCount; ++i) {
230 histogram_names.push_back(
231 StringPrintf("TestHistogram.%d", i % kTestCreateCount));
232 }
233
234 // Calculate cost of creating histograms.
235 TimeTicks create_start = TimeTicks::Now();
236 for (int i = 0; i < kTestCreateCount; ++i)
237 SparseHistogram::FactoryGet(histogram_names[i], HistogramBase::kNoFlags);
238 TimeDelta create_ticks = TimeTicks::Now() - create_start;
239 int64_t create_ms = create_ticks.InMilliseconds();
240
241 VLOG(1) << kTestCreateCount << " histogram creations took " << create_ms
242 << "ms or about "
243 << (create_ms * 1000000) / kTestCreateCount
244 << "ns each.";
245
246 // Calculate cost of looking up existing histograms.
247 TimeTicks lookup_start = TimeTicks::Now();
248 for (int i = 0; i < kTestLookupCount; ++i) {
249 // 6007 is co-prime with kTestCreateCount and so will do lookups in an
250 // order less likely to be cacheable (but still hit them all) should the
251 // underlying storage use the exact histogram name as the key.
252 const int i_mult = 6007;
253 static_assert(i_mult < INT_MAX / kTestCreateCount, "Multiplier too big");
254 int index = (i * i_mult) & (kTestCreateCount - 1);
255 SparseHistogram::FactoryGet(histogram_names[index],
256 HistogramBase::kNoFlags);
257 }
258 TimeDelta lookup_ticks = TimeTicks::Now() - lookup_start;
259 int64_t lookup_ms = lookup_ticks.InMilliseconds();
260
261 VLOG(1) << kTestLookupCount << " histogram lookups took " << lookup_ms
262 << "ms or about "
263 << (lookup_ms * 1000000) / kTestLookupCount
264 << "ns each.";
265
266 // Calculate cost of accessing histograms.
267 HistogramBase* histogram =
268 SparseHistogram::FactoryGet(histogram_names[0], HistogramBase::kNoFlags);
269 ASSERT_TRUE(histogram);
270 TimeTicks add_start = TimeTicks::Now();
271 for (int i = 0; i < kTestAddCount; ++i)
272 histogram->Add(i & 127);
273 TimeDelta add_ticks = TimeTicks::Now() - add_start;
274 int64_t add_ms = add_ticks.InMilliseconds();
275
276 VLOG(1) << kTestAddCount << " histogram adds took " << add_ms
277 << "ms or about "
278 << (add_ms * 1000000) / kTestAddCount
279 << "ns each.";
280 }
281
169 } // namespace base 282 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/sparse_histogram.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698