1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/metrics/sparse_histogram.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <memory>
8*635a8641SAndroid Build Coastguard Worker #include <string>
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_base.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_samples.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/metrics/metrics_hashes.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/metrics/persistent_histogram_allocator.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/metrics/persistent_memory_allocator.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/metrics/sample_map.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/metrics/statistics_recorder.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/pickle.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
20*635a8641SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
21*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
22*635a8641SAndroid Build Coastguard Worker
23*635a8641SAndroid Build Coastguard Worker namespace base {
24*635a8641SAndroid Build Coastguard Worker
25*635a8641SAndroid Build Coastguard Worker // Test parameter indicates if a persistent memory allocator should be used
26*635a8641SAndroid Build Coastguard Worker // for histogram allocation. False will allocate histograms from the process
27*635a8641SAndroid Build Coastguard Worker // heap.
28*635a8641SAndroid Build Coastguard Worker class SparseHistogramTest : public testing::TestWithParam<bool> {
29*635a8641SAndroid Build Coastguard Worker protected:
30*635a8641SAndroid Build Coastguard Worker const int32_t kAllocatorMemorySize = 8 << 20; // 8 MiB
31*635a8641SAndroid Build Coastguard Worker
SparseHistogramTest()32*635a8641SAndroid Build Coastguard Worker SparseHistogramTest() : use_persistent_histogram_allocator_(GetParam()) {}
33*635a8641SAndroid Build Coastguard Worker
SetUp()34*635a8641SAndroid Build Coastguard Worker void SetUp() override {
35*635a8641SAndroid Build Coastguard Worker if (use_persistent_histogram_allocator_)
36*635a8641SAndroid Build Coastguard Worker CreatePersistentMemoryAllocator();
37*635a8641SAndroid Build Coastguard Worker
38*635a8641SAndroid Build Coastguard Worker // Each test will have a clean state (no Histogram / BucketRanges
39*635a8641SAndroid Build Coastguard Worker // registered).
40*635a8641SAndroid Build Coastguard Worker InitializeStatisticsRecorder();
41*635a8641SAndroid Build Coastguard Worker }
42*635a8641SAndroid Build Coastguard Worker
TearDown()43*635a8641SAndroid Build Coastguard Worker void TearDown() override {
44*635a8641SAndroid Build Coastguard Worker if (allocator_) {
45*635a8641SAndroid Build Coastguard Worker ASSERT_FALSE(allocator_->IsFull());
46*635a8641SAndroid Build Coastguard Worker ASSERT_FALSE(allocator_->IsCorrupt());
47*635a8641SAndroid Build Coastguard Worker }
48*635a8641SAndroid Build Coastguard Worker UninitializeStatisticsRecorder();
49*635a8641SAndroid Build Coastguard Worker DestroyPersistentMemoryAllocator();
50*635a8641SAndroid Build Coastguard Worker }
51*635a8641SAndroid Build Coastguard Worker
InitializeStatisticsRecorder()52*635a8641SAndroid Build Coastguard Worker void InitializeStatisticsRecorder() {
53*635a8641SAndroid Build Coastguard Worker DCHECK(!statistics_recorder_);
54*635a8641SAndroid Build Coastguard Worker statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
55*635a8641SAndroid Build Coastguard Worker }
56*635a8641SAndroid Build Coastguard Worker
UninitializeStatisticsRecorder()57*635a8641SAndroid Build Coastguard Worker void UninitializeStatisticsRecorder() {
58*635a8641SAndroid Build Coastguard Worker statistics_recorder_.reset();
59*635a8641SAndroid Build Coastguard Worker }
60*635a8641SAndroid Build Coastguard Worker
CreatePersistentMemoryAllocator()61*635a8641SAndroid Build Coastguard Worker void CreatePersistentMemoryAllocator() {
62*635a8641SAndroid Build Coastguard Worker GlobalHistogramAllocator::CreateWithLocalMemory(
63*635a8641SAndroid Build Coastguard Worker kAllocatorMemorySize, 0, "SparseHistogramAllocatorTest");
64*635a8641SAndroid Build Coastguard Worker allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
65*635a8641SAndroid Build Coastguard Worker }
66*635a8641SAndroid Build Coastguard Worker
DestroyPersistentMemoryAllocator()67*635a8641SAndroid Build Coastguard Worker void DestroyPersistentMemoryAllocator() {
68*635a8641SAndroid Build Coastguard Worker allocator_ = nullptr;
69*635a8641SAndroid Build Coastguard Worker GlobalHistogramAllocator::ReleaseForTesting();
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker
NewSparseHistogram(const char * name)72*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SparseHistogram> NewSparseHistogram(const char* name) {
73*635a8641SAndroid Build Coastguard Worker // std::make_unique can't access protected ctor so do it manually. This
74*635a8641SAndroid Build Coastguard Worker // test class is a friend so can access it.
75*635a8641SAndroid Build Coastguard Worker return std::unique_ptr<SparseHistogram>(new SparseHistogram(name));
76*635a8641SAndroid Build Coastguard Worker }
77*635a8641SAndroid Build Coastguard Worker
78*635a8641SAndroid Build Coastguard Worker const bool use_persistent_histogram_allocator_;
79*635a8641SAndroid Build Coastguard Worker
80*635a8641SAndroid Build Coastguard Worker std::unique_ptr<StatisticsRecorder> statistics_recorder_;
81*635a8641SAndroid Build Coastguard Worker PersistentMemoryAllocator* allocator_ = nullptr;
82*635a8641SAndroid Build Coastguard Worker
83*635a8641SAndroid Build Coastguard Worker private:
84*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SparseHistogramTest);
85*635a8641SAndroid Build Coastguard Worker };
86*635a8641SAndroid Build Coastguard Worker
87*635a8641SAndroid Build Coastguard Worker // Run all HistogramTest cases with both heap and persistent memory.
88*635a8641SAndroid Build Coastguard Worker INSTANTIATE_TEST_CASE_P(HeapAndPersistent,
89*635a8641SAndroid Build Coastguard Worker SparseHistogramTest,
90*635a8641SAndroid Build Coastguard Worker testing::Bool());
91*635a8641SAndroid Build Coastguard Worker
92*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,BasicTest)93*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, BasicTest) {
94*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
95*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
96*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->TotalCount());
97*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->sum());
98*635a8641SAndroid Build Coastguard Worker
99*635a8641SAndroid Build Coastguard Worker histogram->Add(100);
100*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
101*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, snapshot1->TotalCount());
102*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, snapshot1->GetCount(100));
103*635a8641SAndroid Build Coastguard Worker
104*635a8641SAndroid Build Coastguard Worker histogram->Add(100);
105*635a8641SAndroid Build Coastguard Worker histogram->Add(101);
106*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
107*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(3, snapshot2->TotalCount());
108*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(2, snapshot2->GetCount(100));
109*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, snapshot2->GetCount(101));
110*635a8641SAndroid Build Coastguard Worker }
111*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,BasicTestAddCount)112*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, BasicTestAddCount) {
113*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
114*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
115*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->TotalCount());
116*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->sum());
117*635a8641SAndroid Build Coastguard Worker
118*635a8641SAndroid Build Coastguard Worker histogram->AddCount(100, 15);
119*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
120*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(15, snapshot1->TotalCount());
121*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(15, snapshot1->GetCount(100));
122*635a8641SAndroid Build Coastguard Worker
123*635a8641SAndroid Build Coastguard Worker histogram->AddCount(100, 15);
124*635a8641SAndroid Build Coastguard Worker histogram->AddCount(101, 25);
125*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
126*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(55, snapshot2->TotalCount());
127*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(30, snapshot2->GetCount(100));
128*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(25, snapshot2->GetCount(101));
129*635a8641SAndroid Build Coastguard Worker }
130*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,AddCount_LargeValuesDontOverflow)131*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, AddCount_LargeValuesDontOverflow) {
132*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
133*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
134*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->TotalCount());
135*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->sum());
136*635a8641SAndroid Build Coastguard Worker
137*635a8641SAndroid Build Coastguard Worker histogram->AddCount(1000000000, 15);
138*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
139*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(15, snapshot1->TotalCount());
140*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(15, snapshot1->GetCount(1000000000));
141*635a8641SAndroid Build Coastguard Worker
142*635a8641SAndroid Build Coastguard Worker histogram->AddCount(1000000000, 15);
143*635a8641SAndroid Build Coastguard Worker histogram->AddCount(1010000000, 25);
144*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
145*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(55, snapshot2->TotalCount());
146*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(30, snapshot2->GetCount(1000000000));
147*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(25, snapshot2->GetCount(1010000000));
148*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(55250000000LL, snapshot2->sum());
149*635a8641SAndroid Build Coastguard Worker }
150*635a8641SAndroid Build Coastguard Worker
151*635a8641SAndroid Build Coastguard Worker // Make sure that counts returned by Histogram::SnapshotDelta do not overflow
152*635a8641SAndroid Build Coastguard Worker // even when a total count (returned by Histogram::SnapshotSample) does.
TEST_P(SparseHistogramTest,AddCount_LargeCountsDontOverflow)153*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, AddCount_LargeCountsDontOverflow) {
154*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
155*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
156*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->TotalCount());
157*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, snapshot->sum());
158*635a8641SAndroid Build Coastguard Worker
159*635a8641SAndroid Build Coastguard Worker const int count = (1 << 30) - 1;
160*635a8641SAndroid Build Coastguard Worker
161*635a8641SAndroid Build Coastguard Worker // Repeat N times to make sure that there is no internal value overflow.
162*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
163*635a8641SAndroid Build Coastguard Worker histogram->AddCount(42, count);
164*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
165*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(count, samples->TotalCount());
166*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(count, samples->GetCount(42));
167*635a8641SAndroid Build Coastguard Worker }
168*635a8641SAndroid Build Coastguard Worker }
169*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,MacroBasicTest)170*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, MacroBasicTest) {
171*635a8641SAndroid Build Coastguard Worker UmaHistogramSparse("Sparse", 100);
172*635a8641SAndroid Build Coastguard Worker UmaHistogramSparse("Sparse", 200);
173*635a8641SAndroid Build Coastguard Worker UmaHistogramSparse("Sparse", 100);
174*635a8641SAndroid Build Coastguard Worker
175*635a8641SAndroid Build Coastguard Worker const StatisticsRecorder::Histograms histograms =
176*635a8641SAndroid Build Coastguard Worker StatisticsRecorder::GetHistograms();
177*635a8641SAndroid Build Coastguard Worker
178*635a8641SAndroid Build Coastguard Worker ASSERT_THAT(histograms, testing::SizeIs(1));
179*635a8641SAndroid Build Coastguard Worker const HistogramBase* const sparse_histogram = histograms[0];
180*635a8641SAndroid Build Coastguard Worker
181*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(SPARSE_HISTOGRAM, sparse_histogram->GetHistogramType());
182*635a8641SAndroid Build Coastguard Worker EXPECT_EQ("Sparse", StringPiece(sparse_histogram->histogram_name()));
183*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(
184*635a8641SAndroid Build Coastguard Worker HistogramBase::kUmaTargetedHistogramFlag |
185*635a8641SAndroid Build Coastguard Worker (use_persistent_histogram_allocator_ ? HistogramBase::kIsPersistent
186*635a8641SAndroid Build Coastguard Worker : 0),
187*635a8641SAndroid Build Coastguard Worker sparse_histogram->flags());
188*635a8641SAndroid Build Coastguard Worker
189*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> samples =
190*635a8641SAndroid Build Coastguard Worker sparse_histogram->SnapshotSamples();
191*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(3, samples->TotalCount());
192*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(2, samples->GetCount(100));
193*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->GetCount(200));
194*635a8641SAndroid Build Coastguard Worker }
195*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,MacroInLoopTest)196*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, MacroInLoopTest) {
197*635a8641SAndroid Build Coastguard Worker // Unlike the macros in histogram.h, SparseHistogram macros can have a
198*635a8641SAndroid Build Coastguard Worker // variable as histogram name.
199*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
200*635a8641SAndroid Build Coastguard Worker UmaHistogramSparse(StringPrintf("Sparse%d", i), 100);
201*635a8641SAndroid Build Coastguard Worker }
202*635a8641SAndroid Build Coastguard Worker
203*635a8641SAndroid Build Coastguard Worker const StatisticsRecorder::Histograms histograms =
204*635a8641SAndroid Build Coastguard Worker StatisticsRecorder::Sort(StatisticsRecorder::GetHistograms());
205*635a8641SAndroid Build Coastguard Worker ASSERT_THAT(histograms, testing::SizeIs(2));
206*635a8641SAndroid Build Coastguard Worker EXPECT_STREQ(histograms[0]->histogram_name(), "Sparse0");
207*635a8641SAndroid Build Coastguard Worker EXPECT_STREQ(histograms[1]->histogram_name(), "Sparse1");
208*635a8641SAndroid Build Coastguard Worker }
209*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,Serialize)210*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, Serialize) {
211*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
212*635a8641SAndroid Build Coastguard Worker histogram->SetFlags(HistogramBase::kIPCSerializationSourceFlag);
213*635a8641SAndroid Build Coastguard Worker
214*635a8641SAndroid Build Coastguard Worker Pickle pickle;
215*635a8641SAndroid Build Coastguard Worker histogram->SerializeInfo(&pickle);
216*635a8641SAndroid Build Coastguard Worker
217*635a8641SAndroid Build Coastguard Worker PickleIterator iter(pickle);
218*635a8641SAndroid Build Coastguard Worker
219*635a8641SAndroid Build Coastguard Worker int type;
220*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(iter.ReadInt(&type));
221*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(SPARSE_HISTOGRAM, type);
222*635a8641SAndroid Build Coastguard Worker
223*635a8641SAndroid Build Coastguard Worker std::string name;
224*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(iter.ReadString(&name));
225*635a8641SAndroid Build Coastguard Worker EXPECT_EQ("Sparse", name);
226*635a8641SAndroid Build Coastguard Worker
227*635a8641SAndroid Build Coastguard Worker int flag;
228*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(iter.ReadInt(&flag));
229*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag, flag);
230*635a8641SAndroid Build Coastguard Worker
231*635a8641SAndroid Build Coastguard Worker // No more data in the pickle.
232*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(iter.SkipBytes(1));
233*635a8641SAndroid Build Coastguard Worker }
234*635a8641SAndroid Build Coastguard Worker
235*635a8641SAndroid Build Coastguard Worker // Ensure that race conditions that cause multiple, identical sparse histograms
236*635a8641SAndroid Build Coastguard Worker // to be created will safely resolve to a single one.
TEST_P(SparseHistogramTest,DuplicationSafety)237*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, DuplicationSafety) {
238*635a8641SAndroid Build Coastguard Worker const char histogram_name[] = "Duplicated";
239*635a8641SAndroid Build Coastguard Worker size_t histogram_count = StatisticsRecorder::GetHistogramCount();
240*635a8641SAndroid Build Coastguard Worker
241*635a8641SAndroid Build Coastguard Worker // Create a histogram that we will later duplicate.
242*635a8641SAndroid Build Coastguard Worker HistogramBase* original =
243*635a8641SAndroid Build Coastguard Worker SparseHistogram::FactoryGet(histogram_name, HistogramBase::kNoFlags);
244*635a8641SAndroid Build Coastguard Worker ++histogram_count;
245*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
246*635a8641SAndroid Build Coastguard Worker original->Add(1);
247*635a8641SAndroid Build Coastguard Worker
248*635a8641SAndroid Build Coastguard Worker // Create a duplicate. This has to happen differently depending on where the
249*635a8641SAndroid Build Coastguard Worker // memory is taken from.
250*635a8641SAndroid Build Coastguard Worker if (use_persistent_histogram_allocator_) {
251*635a8641SAndroid Build Coastguard Worker // To allocate from persistent memory, clear the last_created reference in
252*635a8641SAndroid Build Coastguard Worker // the GlobalHistogramAllocator. This will cause an Import to recreate
253*635a8641SAndroid Build Coastguard Worker // the just-created histogram which will then be released as a duplicate.
254*635a8641SAndroid Build Coastguard Worker GlobalHistogramAllocator::Get()->ClearLastCreatedReferenceForTesting();
255*635a8641SAndroid Build Coastguard Worker // Creating a different histogram will first do an Import to ensure it
256*635a8641SAndroid Build Coastguard Worker // hasn't been created elsewhere, triggering the duplication and release.
257*635a8641SAndroid Build Coastguard Worker SparseHistogram::FactoryGet("something.new", HistogramBase::kNoFlags);
258*635a8641SAndroid Build Coastguard Worker ++histogram_count;
259*635a8641SAndroid Build Coastguard Worker } else {
260*635a8641SAndroid Build Coastguard Worker // To allocate from the heap, just call the (private) constructor directly.
261*635a8641SAndroid Build Coastguard Worker // Delete it immediately like would have happened within FactoryGet();
262*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SparseHistogram> something =
263*635a8641SAndroid Build Coastguard Worker NewSparseHistogram(histogram_name);
264*635a8641SAndroid Build Coastguard Worker DCHECK_NE(original, something.get());
265*635a8641SAndroid Build Coastguard Worker }
266*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
267*635a8641SAndroid Build Coastguard Worker
268*635a8641SAndroid Build Coastguard Worker // Re-creating the histogram via FactoryGet() will return the same one.
269*635a8641SAndroid Build Coastguard Worker HistogramBase* duplicate =
270*635a8641SAndroid Build Coastguard Worker SparseHistogram::FactoryGet(histogram_name, HistogramBase::kNoFlags);
271*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(original, duplicate);
272*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
273*635a8641SAndroid Build Coastguard Worker duplicate->Add(2);
274*635a8641SAndroid Build Coastguard Worker
275*635a8641SAndroid Build Coastguard Worker // Ensure that original histograms are still cross-functional.
276*635a8641SAndroid Build Coastguard Worker original->Add(2);
277*635a8641SAndroid Build Coastguard Worker duplicate->Add(1);
278*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot_orig = original->SnapshotSamples();
279*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot_dup = duplicate->SnapshotSamples();
280*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(2, snapshot_orig->GetCount(2));
281*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(2, snapshot_dup->GetCount(1));
282*635a8641SAndroid Build Coastguard Worker }
283*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,FactoryTime)284*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, FactoryTime) {
285*635a8641SAndroid Build Coastguard Worker const int kTestCreateCount = 1 << 10; // Must be power-of-2.
286*635a8641SAndroid Build Coastguard Worker const int kTestLookupCount = 100000;
287*635a8641SAndroid Build Coastguard Worker const int kTestAddCount = 100000;
288*635a8641SAndroid Build Coastguard Worker
289*635a8641SAndroid Build Coastguard Worker // Create all histogram names in advance for accurate timing below.
290*635a8641SAndroid Build Coastguard Worker std::vector<std::string> histogram_names;
291*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < kTestCreateCount; ++i) {
292*635a8641SAndroid Build Coastguard Worker histogram_names.push_back(
293*635a8641SAndroid Build Coastguard Worker StringPrintf("TestHistogram.%d", i % kTestCreateCount));
294*635a8641SAndroid Build Coastguard Worker }
295*635a8641SAndroid Build Coastguard Worker
296*635a8641SAndroid Build Coastguard Worker // Calculate cost of creating histograms.
297*635a8641SAndroid Build Coastguard Worker TimeTicks create_start = TimeTicks::Now();
298*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < kTestCreateCount; ++i)
299*635a8641SAndroid Build Coastguard Worker SparseHistogram::FactoryGet(histogram_names[i], HistogramBase::kNoFlags);
300*635a8641SAndroid Build Coastguard Worker TimeDelta create_ticks = TimeTicks::Now() - create_start;
301*635a8641SAndroid Build Coastguard Worker int64_t create_ms = create_ticks.InMilliseconds();
302*635a8641SAndroid Build Coastguard Worker
303*635a8641SAndroid Build Coastguard Worker VLOG(1) << kTestCreateCount << " histogram creations took " << create_ms
304*635a8641SAndroid Build Coastguard Worker << "ms or about "
305*635a8641SAndroid Build Coastguard Worker << (create_ms * 1000000) / kTestCreateCount
306*635a8641SAndroid Build Coastguard Worker << "ns each.";
307*635a8641SAndroid Build Coastguard Worker
308*635a8641SAndroid Build Coastguard Worker // Calculate cost of looking up existing histograms.
309*635a8641SAndroid Build Coastguard Worker TimeTicks lookup_start = TimeTicks::Now();
310*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < kTestLookupCount; ++i) {
311*635a8641SAndroid Build Coastguard Worker // 6007 is co-prime with kTestCreateCount and so will do lookups in an
312*635a8641SAndroid Build Coastguard Worker // order less likely to be cacheable (but still hit them all) should the
313*635a8641SAndroid Build Coastguard Worker // underlying storage use the exact histogram name as the key.
314*635a8641SAndroid Build Coastguard Worker const int i_mult = 6007;
315*635a8641SAndroid Build Coastguard Worker static_assert(i_mult < INT_MAX / kTestCreateCount, "Multiplier too big");
316*635a8641SAndroid Build Coastguard Worker int index = (i * i_mult) & (kTestCreateCount - 1);
317*635a8641SAndroid Build Coastguard Worker SparseHistogram::FactoryGet(histogram_names[index],
318*635a8641SAndroid Build Coastguard Worker HistogramBase::kNoFlags);
319*635a8641SAndroid Build Coastguard Worker }
320*635a8641SAndroid Build Coastguard Worker TimeDelta lookup_ticks = TimeTicks::Now() - lookup_start;
321*635a8641SAndroid Build Coastguard Worker int64_t lookup_ms = lookup_ticks.InMilliseconds();
322*635a8641SAndroid Build Coastguard Worker
323*635a8641SAndroid Build Coastguard Worker VLOG(1) << kTestLookupCount << " histogram lookups took " << lookup_ms
324*635a8641SAndroid Build Coastguard Worker << "ms or about "
325*635a8641SAndroid Build Coastguard Worker << (lookup_ms * 1000000) / kTestLookupCount
326*635a8641SAndroid Build Coastguard Worker << "ns each.";
327*635a8641SAndroid Build Coastguard Worker
328*635a8641SAndroid Build Coastguard Worker // Calculate cost of accessing histograms.
329*635a8641SAndroid Build Coastguard Worker HistogramBase* histogram =
330*635a8641SAndroid Build Coastguard Worker SparseHistogram::FactoryGet(histogram_names[0], HistogramBase::kNoFlags);
331*635a8641SAndroid Build Coastguard Worker ASSERT_TRUE(histogram);
332*635a8641SAndroid Build Coastguard Worker TimeTicks add_start = TimeTicks::Now();
333*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < kTestAddCount; ++i)
334*635a8641SAndroid Build Coastguard Worker histogram->Add(i & 127);
335*635a8641SAndroid Build Coastguard Worker TimeDelta add_ticks = TimeTicks::Now() - add_start;
336*635a8641SAndroid Build Coastguard Worker int64_t add_ms = add_ticks.InMilliseconds();
337*635a8641SAndroid Build Coastguard Worker
338*635a8641SAndroid Build Coastguard Worker VLOG(1) << kTestAddCount << " histogram adds took " << add_ms
339*635a8641SAndroid Build Coastguard Worker << "ms or about "
340*635a8641SAndroid Build Coastguard Worker << (add_ms * 1000000) / kTestAddCount
341*635a8641SAndroid Build Coastguard Worker << "ns each.";
342*635a8641SAndroid Build Coastguard Worker }
343*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,ExtremeValues)344*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, ExtremeValues) {
345*635a8641SAndroid Build Coastguard Worker static const struct {
346*635a8641SAndroid Build Coastguard Worker Histogram::Sample sample;
347*635a8641SAndroid Build Coastguard Worker int64_t expected_max;
348*635a8641SAndroid Build Coastguard Worker } cases[] = {
349*635a8641SAndroid Build Coastguard Worker // Note: We use -2147483647 - 1 rather than -2147483648 because the later
350*635a8641SAndroid Build Coastguard Worker // is interpreted as - operator applied to 2147483648 and the latter can't
351*635a8641SAndroid Build Coastguard Worker // be represented as an int32 and causes a warning.
352*635a8641SAndroid Build Coastguard Worker {-2147483647 - 1, -2147483647LL},
353*635a8641SAndroid Build Coastguard Worker {0, 1},
354*635a8641SAndroid Build Coastguard Worker {2147483647, 2147483648LL},
355*635a8641SAndroid Build Coastguard Worker };
356*635a8641SAndroid Build Coastguard Worker
357*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < arraysize(cases); ++i) {
358*635a8641SAndroid Build Coastguard Worker HistogramBase* histogram =
359*635a8641SAndroid Build Coastguard Worker SparseHistogram::FactoryGet(StringPrintf("ExtremeValues_%zu", i),
360*635a8641SAndroid Build Coastguard Worker HistogramBase::kUmaTargetedHistogramFlag);
361*635a8641SAndroid Build Coastguard Worker histogram->Add(cases[i].sample);
362*635a8641SAndroid Build Coastguard Worker
363*635a8641SAndroid Build Coastguard Worker std::unique_ptr<HistogramSamples> snapshot = histogram->SnapshotSamples();
364*635a8641SAndroid Build Coastguard Worker std::unique_ptr<SampleCountIterator> it = snapshot->Iterator();
365*635a8641SAndroid Build Coastguard Worker ASSERT_FALSE(it->Done());
366*635a8641SAndroid Build Coastguard Worker
367*635a8641SAndroid Build Coastguard Worker base::Histogram::Sample min;
368*635a8641SAndroid Build Coastguard Worker int64_t max;
369*635a8641SAndroid Build Coastguard Worker base::Histogram::Count count;
370*635a8641SAndroid Build Coastguard Worker it->Get(&min, &max, &count);
371*635a8641SAndroid Build Coastguard Worker
372*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, count);
373*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(cases[i].sample, min);
374*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(cases[i].expected_max, max);
375*635a8641SAndroid Build Coastguard Worker
376*635a8641SAndroid Build Coastguard Worker it->Next();
377*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(it->Done());
378*635a8641SAndroid Build Coastguard Worker }
379*635a8641SAndroid Build Coastguard Worker }
380*635a8641SAndroid Build Coastguard Worker
TEST_P(SparseHistogramTest,HistogramNameHash)381*635a8641SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, HistogramNameHash) {
382*635a8641SAndroid Build Coastguard Worker const char kName[] = "TestName";
383*635a8641SAndroid Build Coastguard Worker HistogramBase* histogram = SparseHistogram::FactoryGet(
384*635a8641SAndroid Build Coastguard Worker kName, HistogramBase::kUmaTargetedHistogramFlag);
385*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(histogram->name_hash(), HashMetricName(kName));
386*635a8641SAndroid Build Coastguard Worker }
387*635a8641SAndroid Build Coastguard Worker
388*635a8641SAndroid Build Coastguard Worker } // namespace base
389