| 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 |