OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/metrics/subprocess_metrics_provider.h" | 5 #include "chrome/browser/metrics/subprocess_metrics_provider.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/metrics/histogram_flattener.h" | 11 #include "base/metrics/histogram_flattener.h" |
12 #include "base/metrics/histogram_snapshot_manager.h" | 12 #include "base/metrics/histogram_snapshot_manager.h" |
13 #include "base/metrics/persistent_histogram_allocator.h" | 13 #include "base/metrics/persistent_histogram_allocator.h" |
14 #include "base/metrics/persistent_memory_allocator.h" | 14 #include "base/metrics/persistent_memory_allocator.h" |
| 15 #include "base/metrics/statistics_recorder.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
16 | 17 |
17 namespace { | 18 namespace { |
18 | 19 |
19 const uint32_t TEST_MEMORY_SIZE = 64 << 10; // 64 KiB | 20 const uint32_t TEST_MEMORY_SIZE = 64 << 10; // 64 KiB |
20 | 21 |
21 class HistogramFlattenerDeltaRecorder : public base::HistogramFlattener { | 22 class HistogramFlattenerDeltaRecorder : public base::HistogramFlattener { |
22 public: | 23 public: |
23 HistogramFlattenerDeltaRecorder() {} | 24 HistogramFlattenerDeltaRecorder() {} |
24 | 25 |
(...skipping 27 matching lines...) Expand all Loading... |
52 }; | 53 }; |
53 | 54 |
54 } // namespace | 55 } // namespace |
55 | 56 |
56 class SubprocessMetricsProviderTest : public testing::Test { | 57 class SubprocessMetricsProviderTest : public testing::Test { |
57 protected: | 58 protected: |
58 SubprocessMetricsProviderTest() { | 59 SubprocessMetricsProviderTest() { |
59 // Get this first so it isn't created inside a persistent allocator. | 60 // Get this first so it isn't created inside a persistent allocator. |
60 base::PersistentHistogramAllocator::GetCreateHistogramResultHistogram(); | 61 base::PersistentHistogramAllocator::GetCreateHistogramResultHistogram(); |
61 | 62 |
62 // RecordHistogramSnapshots needs to be called beause it uses a histogram | 63 // MergeHistogramDeltas needs to be called beause it uses a histogram |
63 // macro which caches a pointer to a histogram. If not done before setting | 64 // macro which caches a pointer to a histogram. If not done before setting |
64 // a persistent global allocator, then it would point into memory that | 65 // a persistent global allocator, then it would point into memory that |
65 // will go away. The easiest way to call it is through an existing utility | 66 // will go away. |
66 // method. | 67 provider_.MergeHistogramDeltas(); |
67 GetSnapshotHistogramCount(); | 68 |
| 69 // Create a dedicated StatisticsRecorder for this test. |
| 70 test_recorder_.reset(new base::StatisticsRecorder()); |
68 | 71 |
69 // Create a global allocator using a block of memory from the heap. | 72 // Create a global allocator using a block of memory from the heap. |
70 base::GlobalHistogramAllocator::CreateWithLocalMemory(TEST_MEMORY_SIZE, | 73 base::GlobalHistogramAllocator::CreateWithLocalMemory(TEST_MEMORY_SIZE, |
71 0, ""); | 74 0, ""); |
72 | |
73 // Enable metrics reporting by default. | |
74 provider_.OnRecordingEnabled(); | |
75 } | 75 } |
76 | 76 |
77 ~SubprocessMetricsProviderTest() override { | 77 ~SubprocessMetricsProviderTest() override { |
78 base::GlobalHistogramAllocator::ReleaseForTesting(); | 78 base::GlobalHistogramAllocator::ReleaseForTesting(); |
79 } | 79 } |
80 | 80 |
81 SubprocessMetricsProvider* provider() { return &provider_; } | 81 SubprocessMetricsProvider* provider() { return &provider_; } |
82 | 82 |
83 std::unique_ptr<base::PersistentHistogramAllocator> GetDuplicateAllocator() { | 83 std::unique_ptr<base::PersistentHistogramAllocator> CreateDuplicateAllocator( |
84 base::GlobalHistogramAllocator* global_allocator = | 84 base::PersistentHistogramAllocator* allocator) { |
85 base::GlobalHistogramAllocator::Get(); | 85 // Just wrap around the data segment in-use by the passed allocator. |
86 | |
87 // Just wrap around the data segment in-use by the global allocator. | |
88 return WrapUnique(new base::PersistentHistogramAllocator( | 86 return WrapUnique(new base::PersistentHistogramAllocator( |
89 WrapUnique(new base::PersistentMemoryAllocator( | 87 WrapUnique(new base::PersistentMemoryAllocator( |
90 const_cast<void*>(global_allocator->data()), | 88 const_cast<void*>(allocator->data()), allocator->length(), |
91 global_allocator->length(), 0, 0, "", false)))); | 89 0, 0, "", false)))); |
92 } | 90 } |
93 | 91 |
94 size_t GetSnapshotHistogramCount() { | 92 size_t GetSnapshotHistogramCount() { |
| 93 // Merge the data from the allocator into the StatisticsRecorder. |
| 94 provider_.MergeHistogramDeltas(); |
| 95 |
| 96 // Flatten what is known to see what has changed since the last time. |
95 HistogramFlattenerDeltaRecorder flattener; | 97 HistogramFlattenerDeltaRecorder flattener; |
96 base::HistogramSnapshotManager snapshot_manager(&flattener); | 98 base::HistogramSnapshotManager snapshot_manager(&flattener); |
97 snapshot_manager.StartDeltas(); | 99 // "true" to the begin() includes histograms held in persistent storage. |
98 provider_.RecordHistogramSnapshots(&snapshot_manager); | 100 snapshot_manager.PrepareDeltas( |
99 snapshot_manager.FinishDeltas(); | 101 base::StatisticsRecorder::begin(true), base::StatisticsRecorder::end(), |
100 provider_.OnDidCreateMetricsLog(); | 102 base::Histogram::kNoFlags, base::Histogram::kNoFlags); |
101 return flattener.GetRecordedDeltaHistogramNames().size(); | 103 return flattener.GetRecordedDeltaHistogramNames().size(); |
102 } | 104 } |
103 | 105 |
104 void EnableRecording() { provider_.OnRecordingEnabled(); } | 106 void EnableRecording() { provider_.OnRecordingEnabled(); } |
105 void DisableRecording() { provider_.OnRecordingDisabled(); } | 107 void DisableRecording() { provider_.OnRecordingDisabled(); } |
106 | 108 |
107 void RegisterSubprocessAllocator( | 109 void RegisterSubprocessAllocator( |
108 int id, | 110 int id, |
109 std::unique_ptr<base::PersistentHistogramAllocator> allocator) { | 111 std::unique_ptr<base::PersistentHistogramAllocator> allocator) { |
110 provider_.RegisterSubprocessAllocator(id, std::move(allocator)); | 112 provider_.RegisterSubprocessAllocator(id, std::move(allocator)); |
111 } | 113 } |
112 | 114 |
113 void DeregisterSubprocessAllocator(int id) { | 115 void DeregisterSubprocessAllocator(int id) { |
114 provider_.DeregisterSubprocessAllocator(id); | 116 provider_.DeregisterSubprocessAllocator(id); |
115 } | 117 } |
116 | 118 |
117 private: | 119 private: |
118 SubprocessMetricsProvider provider_; | 120 SubprocessMetricsProvider provider_; |
| 121 std::unique_ptr<base::StatisticsRecorder> test_recorder_; |
119 | 122 |
120 DISALLOW_COPY_AND_ASSIGN(SubprocessMetricsProviderTest); | 123 DISALLOW_COPY_AND_ASSIGN(SubprocessMetricsProviderTest); |
121 }; | 124 }; |
122 | 125 |
123 TEST_F(SubprocessMetricsProviderTest, SnapshotMetrics) { | 126 TEST_F(SubprocessMetricsProviderTest, SnapshotMetrics) { |
124 base::HistogramBase* foo = base::Histogram::FactoryGet("foo", 1, 100, 10, 0); | 127 base::HistogramBase* foo = base::Histogram::FactoryGet("foo", 1, 100, 10, 0); |
125 base::HistogramBase* bar = base::Histogram::FactoryGet("bar", 1, 100, 10, 0); | 128 base::HistogramBase* bar = base::Histogram::FactoryGet("bar", 1, 100, 10, 0); |
| 129 base::HistogramBase* baz = base::Histogram::FactoryGet("baz", 1, 100, 10, 0); |
126 foo->Add(42); | 130 foo->Add(42); |
127 bar->Add(84); | 131 bar->Add(84); |
128 | 132 |
129 // Register an allocator that duplicates the global allocator. | 133 // Detach the global allocator but keep it around until this method exits |
130 RegisterSubprocessAllocator(123, GetDuplicateAllocator()); | 134 // so that the memory holding histogram data doesn't get released. Register |
| 135 // a new allocator that duplicates the global one. |
| 136 std::unique_ptr<base::GlobalHistogramAllocator> global_allocator( |
| 137 base::GlobalHistogramAllocator::ReleaseForTesting()); |
| 138 RegisterSubprocessAllocator(123, |
| 139 CreateDuplicateAllocator(global_allocator.get())); |
131 | 140 |
132 // Recording should find the two histograms created in persistent memory. | 141 // Recording should find the two histograms created in persistent memory. |
133 EXPECT_EQ(2U, GetSnapshotHistogramCount()); | 142 EXPECT_EQ(2U, GetSnapshotHistogramCount()); |
134 | 143 |
135 // A second run should have nothing to produce. | 144 // A second run should have nothing to produce. |
136 EXPECT_EQ(0U, GetSnapshotHistogramCount()); | 145 EXPECT_EQ(0U, GetSnapshotHistogramCount()); |
137 | 146 |
138 // Create a new histogram and update existing ones. Should now report 3 items. | 147 // Create a new histogram and update existing ones. Should now report 3 items. |
139 base::HistogramBase* baz = base::Histogram::FactoryGet("baz", 1, 100, 10, 0); | |
140 baz->Add(1969); | 148 baz->Add(1969); |
141 foo->Add(10); | 149 foo->Add(10); |
142 bar->Add(20); | 150 bar->Add(20); |
143 EXPECT_EQ(3U, GetSnapshotHistogramCount()); | 151 EXPECT_EQ(3U, GetSnapshotHistogramCount()); |
144 | 152 |
145 // Ensure that deregistering still keeps allocator around for final report. | 153 // Ensure that deregistering does a final merge of the data. |
146 foo->Add(10); | 154 foo->Add(10); |
147 bar->Add(20); | 155 bar->Add(20); |
148 DeregisterSubprocessAllocator(123); | 156 DeregisterSubprocessAllocator(123); |
149 EXPECT_EQ(2U, GetSnapshotHistogramCount()); | 157 EXPECT_EQ(2U, GetSnapshotHistogramCount()); |
150 | 158 |
151 // Further snapshots should be empty even if things have changed. | 159 // Further snapshots should be empty even if things have changed. |
152 foo->Add(10); | 160 foo->Add(10); |
153 bar->Add(20); | 161 bar->Add(20); |
154 EXPECT_EQ(0U, GetSnapshotHistogramCount()); | 162 EXPECT_EQ(0U, GetSnapshotHistogramCount()); |
155 } | 163 } |
156 | |
157 TEST_F(SubprocessMetricsProviderTest, EnableDisable) { | |
158 base::HistogramBase* foo = base::Histogram::FactoryGet("foo", 1, 100, 10, 0); | |
159 base::HistogramBase* bar = base::Histogram::FactoryGet("bar", 1, 100, 10, 0); | |
160 | |
161 // Simulate some "normal" operation... | |
162 RegisterSubprocessAllocator(123, GetDuplicateAllocator()); | |
163 foo->Add(42); | |
164 bar->Add(84); | |
165 EXPECT_EQ(2U, GetSnapshotHistogramCount()); | |
166 foo->Add(42); | |
167 bar->Add(84); | |
168 EXPECT_EQ(2U, GetSnapshotHistogramCount()); | |
169 | |
170 // Ensure that disable/enable reporting won't affect "live" allocators. | |
171 DisableRecording(); | |
172 EnableRecording(); | |
173 foo->Add(42); | |
174 bar->Add(84); | |
175 EXPECT_EQ(2U, GetSnapshotHistogramCount()); | |
176 | |
177 // Ensure that allocators are released when reporting is disabled. | |
178 DisableRecording(); | |
179 DeregisterSubprocessAllocator(123); | |
180 EnableRecording(); | |
181 foo->Add(42); | |
182 bar->Add(84); | |
183 EXPECT_EQ(0U, GetSnapshotHistogramCount()); | |
184 | |
185 // Ensure that allocators added when reporting disabled will work if enabled. | |
186 DisableRecording(); | |
187 RegisterSubprocessAllocator(123, GetDuplicateAllocator()); | |
188 EnableRecording(); | |
189 foo->Add(42); | |
190 bar->Add(84); | |
191 EXPECT_EQ(2U, GetSnapshotHistogramCount()); | |
192 | |
193 // Ensure that last-chance allocators are released if reporting is disabled. | |
194 DeregisterSubprocessAllocator(123); | |
195 DisableRecording(); | |
196 EnableRecording(); | |
197 foo->Add(42); | |
198 bar->Add(84); | |
199 EXPECT_EQ(0U, GetSnapshotHistogramCount()); | |
200 } | |
OLD | NEW |