| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/process_memory_metrics_emitter.h" | 5 #include "chrome/browser/metrics/process_memory_metrics_emitter.h" |
| 6 | 6 |
| 7 #include "base/memory/ref_counted.h" | |
| 8 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
| 9 #include "base/test/histogram_tester.h" | |
| 10 #include "base/test/trace_event_analyzer.h" | |
| 11 #include "base/trace_event/memory_dump_manager.h" | |
| 12 #include "base/trace_event/trace_config_memory_test_util.h" | |
| 13 #include "chrome/test/base/in_process_browser_test.h" | 8 #include "chrome/test/base/in_process_browser_test.h" |
| 14 #include "chrome/test/base/tracing.h" | |
| 15 #include "chrome/test/base/ui_test_utils.h" | |
| 16 #include "content/public/test/test_utils.h" | 9 #include "content/public/test/test_utils.h" |
| 17 #include "url/gurl.h" | |
| 18 | 10 |
| 19 namespace { | 11 namespace { |
| 20 | 12 |
| 21 using base::trace_event::MemoryDumpType; | |
| 22 | |
| 23 void RequestGlobalDumpCallback(base::Closure quit_closure, | |
| 24 uint64_t, | |
| 25 bool success) { | |
| 26 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); | |
| 27 ASSERT_TRUE(success); | |
| 28 } | |
| 29 | |
| 30 void OnStartTracingDoneCallback( | |
| 31 base::trace_event::MemoryDumpLevelOfDetail explicit_dump_type, | |
| 32 base::Closure quit_closure) { | |
| 33 base::trace_event::MemoryDumpManager::GetInstance()->RequestGlobalDump( | |
| 34 MemoryDumpType::EXPLICITLY_TRIGGERED, explicit_dump_type, | |
| 35 Bind(&RequestGlobalDumpCallback, quit_closure)); | |
| 36 } | |
| 37 | |
| 38 class ProcessMemoryMetricsEmitterFake : public ProcessMemoryMetricsEmitter { | 13 class ProcessMemoryMetricsEmitterFake : public ProcessMemoryMetricsEmitter { |
| 39 public: | 14 public: |
| 40 explicit ProcessMemoryMetricsEmitterFake(base::RunLoop* run_loop) | 15 ProcessMemoryMetricsEmitterFake() {} |
| 41 : run_loop_(run_loop) {} | |
| 42 | 16 |
| 43 private: | 17 private: |
| 44 ~ProcessMemoryMetricsEmitterFake() override {} | 18 ~ProcessMemoryMetricsEmitterFake() override {} |
| 45 | 19 |
| 46 void ReceivedMemoryDump( | 20 void ReceivedMemoryDump( |
| 47 uint64_t dump_guid, | 21 uint64_t dump_guid, |
| 48 bool success, | 22 bool success, |
| 49 memory_instrumentation::mojom::GlobalMemoryDumpPtr ptr) override { | 23 memory_instrumentation::mojom::GlobalMemoryDumpPtr ptr) override { |
| 50 EXPECT_TRUE(success); | 24 EXPECT_TRUE(success); |
| 51 ProcessMemoryMetricsEmitter::ReceivedMemoryDump(dump_guid, success, | 25 base::MessageLoop::current()->QuitWhenIdle(); |
| 52 std::move(ptr)); | |
| 53 if (run_loop_) | |
| 54 run_loop_->Quit(); | |
| 55 } | 26 } |
| 56 | 27 |
| 57 base::RunLoop* run_loop_; | |
| 58 | |
| 59 DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterFake); | 28 DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterFake); |
| 60 }; | 29 }; |
| 61 | 30 |
| 62 void CheckMemoryMetric(const std::string& name, | |
| 63 const base::HistogramTester& histogram_tester, | |
| 64 int count, | |
| 65 bool check_minimum) { | |
| 66 histogram_tester.ExpectTotalCount(name, count); | |
| 67 std::unique_ptr<base::HistogramSamples> samples( | |
| 68 histogram_tester.GetHistogramSamplesSinceCreation(name)); | |
| 69 ASSERT_TRUE(samples); | |
| 70 if (check_minimum) | |
| 71 EXPECT_GT(samples->sum(), 0u) << name; | |
| 72 | |
| 73 // As a sanity check, no memory stat should exceed 1 GB. | |
| 74 int64_t maximum_expected_size = 1ll << 30; | |
| 75 EXPECT_LT(samples->sum(), maximum_expected_size) << name; | |
| 76 } | |
| 77 | |
| 78 void CheckAllMemoryMetrics(const base::HistogramTester& histogram_tester, | |
| 79 int count) { | |
| 80 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_LINUX) || \ | |
| 81 defined(OS_ANDROID) | |
| 82 bool private_footprint_implemented = true; | |
| 83 #else | |
| 84 bool private_footprint_implemented = false; | |
| 85 #endif | |
| 86 | |
| 87 CheckMemoryMetric("Memory.Experimental.Browser2.Malloc", histogram_tester, | |
| 88 count, true); | |
| 89 CheckMemoryMetric("Memory.Experimental.Browser2.Resident", histogram_tester, | |
| 90 count, true); | |
| 91 CheckMemoryMetric("Memory.Experimental.Browser2.PrivateMemoryFootprint", | |
| 92 histogram_tester, count, private_footprint_implemented); | |
| 93 CheckMemoryMetric("Memory.Experimental.Renderer2.Malloc", histogram_tester, | |
| 94 count, true); | |
| 95 CheckMemoryMetric("Memory.Experimental.Renderer2.Resident", histogram_tester, | |
| 96 count, true); | |
| 97 CheckMemoryMetric("Memory.Experimental.Renderer2.BlinkGC", histogram_tester, | |
| 98 count, false); | |
| 99 CheckMemoryMetric("Memory.Experimental.Renderer2.PartitionAlloc", | |
| 100 histogram_tester, count, false); | |
| 101 CheckMemoryMetric("Memory.Experimental.Renderer2.V8", histogram_tester, count, | |
| 102 true); | |
| 103 CheckMemoryMetric("Memory.Experimental.Renderer2.PrivateMemoryFootprint", | |
| 104 histogram_tester, count, private_footprint_implemented); | |
| 105 } | |
| 106 | |
| 107 } // namespace | 31 } // namespace |
| 108 | 32 |
| 109 class ProcessMemoryMetricsEmitterTest : public InProcessBrowserTest { | 33 class ProcessMemoryMetricsEmitterTest : public InProcessBrowserTest { |
| 110 public: | 34 public: |
| 111 ProcessMemoryMetricsEmitterTest() {} | 35 ProcessMemoryMetricsEmitterTest() {} |
| 112 ~ProcessMemoryMetricsEmitterTest() override {} | 36 ~ProcessMemoryMetricsEmitterTest() override {} |
| 113 | 37 |
| 114 private: | 38 private: |
| 115 DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterTest); | 39 DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterTest); |
| 116 }; | 40 }; |
| 117 | 41 |
| 118 #if defined(ADDRESS_SANITIZER) | 42 IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, FetchAndEmitMetrics) { |
| 119 #define MAYBE_FetchAndEmitMetrics DISABLED_FetchAndEmitMetrics | |
| 120 #else | |
| 121 #define MAYBE_FetchAndEmitMetrics FetchAndEmitMetrics | |
| 122 #endif | |
| 123 IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, | |
| 124 MAYBE_FetchAndEmitMetrics) { | |
| 125 base::HistogramTester histogram_tester; | |
| 126 base::RunLoop run_loop; | |
| 127 | |
| 128 // Intentionally let emitter leave scope to check that it correctly keeps | 43 // Intentionally let emitter leave scope to check that it correctly keeps |
| 129 // itself alive. | 44 // itself alive. |
| 130 { | 45 { |
| 131 scoped_refptr<ProcessMemoryMetricsEmitterFake> emitter( | 46 scoped_refptr<ProcessMemoryMetricsEmitterFake> emitter( |
| 132 new ProcessMemoryMetricsEmitterFake(&run_loop)); | 47 new ProcessMemoryMetricsEmitterFake); |
| 133 emitter->FetchAndEmitProcessMemoryMetrics(); | 48 emitter->FetchAndEmitProcessMemoryMetrics(); |
| 134 } | 49 } |
| 135 | 50 |
| 136 run_loop.Run(); | 51 content::RunMessageLoop(); |
| 137 | |
| 138 CheckAllMemoryMetrics(histogram_tester, 1); | |
| 139 } | 52 } |
| 140 | |
| 141 #if defined(ADDRESS_SANITIZER) | |
| 142 #define MAYBE_FetchDuringTrace DISABLED_FetchDuringTrace | |
| 143 #else | |
| 144 #define MAYBE_FetchDuringTrace FetchDuringTrace | |
| 145 #endif | |
| 146 IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, | |
| 147 MAYBE_FetchDuringTrace) { | |
| 148 base::HistogramTester histogram_tester; | |
| 149 base::RunLoop run_loop; | |
| 150 | |
| 151 base::trace_event::TraceConfig trace_config( | |
| 152 base::trace_event::TraceConfigMemoryTestUtil:: | |
| 153 GetTraceConfig_EmptyTriggers()); | |
| 154 ASSERT_TRUE(tracing::BeginTracingWithTraceConfig( | |
| 155 trace_config, Bind(&OnStartTracingDoneCallback, | |
| 156 base::trace_event::MemoryDumpLevelOfDetail::DETAILED, | |
| 157 run_loop.QuitClosure()))); | |
| 158 | |
| 159 // Intentionally let emitter leave scope to check that it correctly keeps | |
| 160 // itself alive. | |
| 161 { | |
| 162 scoped_refptr<ProcessMemoryMetricsEmitterFake> emitter( | |
| 163 new ProcessMemoryMetricsEmitterFake(&run_loop)); | |
| 164 emitter->FetchAndEmitProcessMemoryMetrics(); | |
| 165 } | |
| 166 | |
| 167 GURL url1("about:blank"); | |
| 168 ui_test_utils::NavigateToURLWithDisposition( | |
| 169 browser(), url1, WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 170 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 171 run_loop.Run(); | |
| 172 | |
| 173 std::string json_events; | |
| 174 ASSERT_TRUE(tracing::EndTracing(&json_events)); | |
| 175 | |
| 176 trace_analyzer::TraceEventVector events; | |
| 177 std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer( | |
| 178 trace_analyzer::TraceAnalyzer::Create(json_events)); | |
| 179 analyzer->FindEvents( | |
| 180 trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_MEMORY_DUMP), | |
| 181 &events); | |
| 182 | |
| 183 ASSERT_GT(events.size(), 1u); | |
| 184 ASSERT_TRUE(trace_analyzer::CountMatches( | |
| 185 events, trace_analyzer::Query::EventNameIs(MemoryDumpTypeToString( | |
| 186 MemoryDumpType::EXPLICITLY_TRIGGERED)))); | |
| 187 | |
| 188 CheckAllMemoryMetrics(histogram_tester, 1); | |
| 189 } | |
| 190 | |
| 191 #if defined(ADDRESS_SANITIZER) | |
| 192 #define MAYBE_FetchThreeTimes DISABLED_FetchThreeTimes | |
| 193 #else | |
| 194 #define MAYBE_FetchThreeTimes FetchThreeTimes | |
| 195 #endif | |
| 196 IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, MAYBE_FetchThreeTimes) { | |
| 197 base::HistogramTester histogram_tester; | |
| 198 base::RunLoop run_loop; | |
| 199 | |
| 200 int count = 3; | |
| 201 for (int i = 0; i < count; ++i) { | |
| 202 // Only the last emitter should stop the run loop. | |
| 203 auto emitter = base::MakeShared<ProcessMemoryMetricsEmitterFake>( | |
| 204 (i == count - 1) ? &run_loop : nullptr); | |
| 205 emitter->FetchAndEmitProcessMemoryMetrics(); | |
| 206 } | |
| 207 | |
| 208 run_loop.Run(); | |
| 209 | |
| 210 CheckAllMemoryMetrics(histogram_tester, count); | |
| 211 } | |
| OLD | NEW |