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

Side by Side Diff: base/trace_event/memory_peak_detector_unittest.cc

Issue 2793023002: memory-infra: port peak detection logic to MemoryPeakDetector (Closed)
Patch Set: fix uint64_t cast Created 3 years, 8 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/trace_event/memory_peak_detector.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 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 "base/trace_event/memory_peak_detector.h" 5 #include "base/trace_event/memory_peak_detector.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/run_loop.h" 11 #include "base/run_loop.h"
12 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/threading/platform_thread.h" 13 #include "base/threading/platform_thread.h"
15 #include "base/threading/thread.h" 14 #include "base/threading/thread.h"
16 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
17 #include "base/trace_event/memory_dump_provider.h" 16 #include "base/trace_event/memory_dump_provider.h"
18 #include "base/trace_event/memory_dump_provider_info.h" 17 #include "base/trace_event/memory_dump_provider_info.h"
19 #include "testing/gmock/include/gmock/gmock.h" 18 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h" 19 #include "testing/gtest/include/gtest/gtest.h"
21 20
22 using ::testing::_; 21 using ::testing::_;
23 using ::testing::Invoke; 22 using ::testing::Invoke;
24 using ::testing::Return; 23 using ::testing::Return;
25 24
26 namespace base { 25 namespace base {
27 namespace trace_event { 26 namespace trace_event {
28 27
29 namespace { 28 namespace {
30 29
30 const TimeDelta kMs = TimeDelta::FromMilliseconds(1);
31 const MemoryPeakDetector::Config kConfigNoCallbacks = {
32 1 /* polling_interval_ms */, 60000 /* min_time_between_peaks_ms */,
33 false /* enable_verbose_poll_tracing */
34 };
35
31 class MockMemoryDumpProvider : public MemoryDumpProvider { 36 class MockMemoryDumpProvider : public MemoryDumpProvider {
32 public: 37 public:
33 bool OnMemoryDump(const MemoryDumpArgs&, ProcessMemoryDump*) override { 38 bool OnMemoryDump(const MemoryDumpArgs&, ProcessMemoryDump*) override {
34 NOTREACHED(); 39 NOTREACHED();
35 return true; 40 return true;
36 } 41 }
37 42
38 MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t*)); 43 MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t*));
39 }; 44 };
40 45
41 // Wrapper to use gmock on a callback. 46 // Wrapper to use gmock on a callback.
42 struct OnPeakDetectedWrapper { 47 struct OnPeakDetectedWrapper {
43 MOCK_METHOD0(OnPeak, void()); 48 MOCK_METHOD0(OnPeak, void());
44 }; 49 };
45 50
46 } // namespace 51 } // namespace
47 52
48 class MemoryPeakDetectorTest : public testing::Test { 53 class MemoryPeakDetectorTest : public testing::Test {
49 public: 54 public:
50 struct FriendDeleter { 55 struct FriendDeleter {
51 void operator()(MemoryPeakDetector* inst) { delete inst; } 56 void operator()(MemoryPeakDetector* inst) { delete inst; }
52 }; 57 };
53 58
54 MemoryPeakDetectorTest() : testing::Test() {} 59 MemoryPeakDetectorTest() : testing::Test() {}
60 static const uint64_t kSlidingWindowNumSamples =
61 MemoryPeakDetector::kSlidingWindowNumSamples;
55 62
56 std::unique_ptr<MemoryPeakDetector, FriendDeleter> NewInstance() { 63 std::unique_ptr<MemoryPeakDetector, FriendDeleter> NewInstance() {
57 return std::unique_ptr<MemoryPeakDetector, FriendDeleter>( 64 return std::unique_ptr<MemoryPeakDetector, FriendDeleter>(
58 new MemoryPeakDetector()); 65 new MemoryPeakDetector());
59 } 66 }
60 67
61 void RestartThreadAndReinitializePeakDetector() { 68 void RestartThreadAndReinitializePeakDetector() {
62 bg_thread_.reset(new Thread("Peak Detector Test Thread")); 69 bg_thread_.reset(new Thread("Peak Detector Test Thread"));
63 bg_thread_->Start(); 70 bg_thread_->Start();
64 peak_detector_ = NewInstance(); 71 peak_detector_ = NewInstance();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 117
111 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, 118 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
112 WaitableEvent::InitialState::NOT_SIGNALED); 119 WaitableEvent::InitialState::NOT_SIGNALED);
113 bg_thread_->task_runner()->PostTask( 120 bg_thread_->task_runner()->PostTask(
114 FROM_HERE, Bind(get_fn, Unretained(&*peak_detector_), Unretained(&evt), 121 FROM_HERE, Bind(get_fn, Unretained(&*peak_detector_), Unretained(&evt),
115 Unretained(&res))); 122 Unretained(&res)));
116 evt.Wait(); 123 evt.Wait();
117 return res; 124 return res;
118 } 125 }
119 126
127 // Runs the peak detector with a mock MDP with the given
128 // |config|. The mock MDP will invoke the |poll_function| on any call to
129 // PollFastMemoryTotal(), until |num_samples| have been polled.
130 // It returns the number of peaks detected.
131 uint32_t RunWithCustomPollFunction(
132 MemoryPeakDetector::Config config,
133 uint32_t num_samples,
134 RepeatingCallback<uint64_t(uint32_t)> poll_function) {
135 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
136 WaitableEvent::InitialState::NOT_SIGNALED);
137 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
138 dump_providers_.push_back(mdp);
139 uint32_t cur_sample_idx = 0;
140 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
141 .WillRepeatedly(Invoke(
142 [&cur_sample_idx, &evt, poll_function, num_samples](uint64_t* mem) {
143 if (cur_sample_idx >= num_samples) {
144 *mem = 1;
145 evt.Signal();
146 } else {
147 *mem = poll_function.Run(cur_sample_idx++);
148 }
149 }));
150
151 uint32_t num_peaks = 0;
152 EXPECT_CALL(on_peak_callback_, OnPeak())
153 .WillRepeatedly(Invoke([&num_peaks] { num_peaks++; }));
154 peak_detector_->Start(config);
155 evt.Wait(); // Wait for |num_samples| invocations of PollFastMemoryTotal().
156 peak_detector_->Stop();
157 EXPECT_EQ(num_samples, cur_sample_idx);
158 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
159 return num_peaks;
160 }
161
120 // Called on the |bg_thread_|. 162 // Called on the |bg_thread_|.
121 void MockGetDumpProviders(MemoryPeakDetector::DumpProvidersList* mdps) { 163 void MockGetDumpProviders(MemoryPeakDetector::DumpProvidersList* mdps) {
122 get_mdp_call_count_++; 164 get_mdp_call_count_++;
123 *mdps = dump_providers_; 165 *mdps = dump_providers_;
124 } 166 }
125 167
126 uint32_t GetNumGetDumpProvidersCalls() { 168 uint32_t GetNumGetDumpProvidersCalls() {
127 bg_thread_->FlushForTesting(); 169 bg_thread_->FlushForTesting();
128 return get_mdp_call_count_; 170 return get_mdp_call_count_;
129 } 171 }
130 172
131 scoped_refptr<MemoryDumpProviderInfo> CreateMockDumpProvider() { 173 scoped_refptr<MemoryDumpProviderInfo> CreateMockDumpProvider() {
132 std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider()); 174 std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider());
133 MemoryDumpProvider::Options opt; 175 MemoryDumpProvider::Options opt;
134 opt.is_fast_polling_supported = true; 176 opt.is_fast_polling_supported = true;
135 scoped_refptr<MemoryDumpProviderInfo> mdp_info( 177 scoped_refptr<MemoryDumpProviderInfo> mdp_info(
136 new MemoryDumpProviderInfo(mdp.get(), "Mock MDP", nullptr, opt, false)); 178 new MemoryDumpProviderInfo(mdp.get(), "Mock MDP", nullptr, opt, false));
137 179
138 // The |mdp| instance will be destroyed together with the |mdp_info|. 180 // The |mdp| instance will be destroyed together with the |mdp_info|.
139 mdp_info->owned_dump_provider = std::move(mdp); 181 mdp_info->owned_dump_provider = std::move(mdp);
140 return mdp_info; 182 return mdp_info;
141 } 183 }
142 184
143 static MockMemoryDumpProvider& GetMockMDP( 185 static MockMemoryDumpProvider& GetMockMDP(
144 const scoped_refptr<MemoryDumpProviderInfo>& mdp_info) { 186 const scoped_refptr<MemoryDumpProviderInfo>& mdp_info) {
145 return *static_cast<MockMemoryDumpProvider*>(mdp_info->dump_provider); 187 return *static_cast<MockMemoryDumpProvider*>(mdp_info->dump_provider);
146 } 188 }
147 189
190 static uint64_t PollFunctionThatCausesPeakViaStdDev(uint32_t sample_idx) {
191 // Start with a baseline of 50 MB.
192 if (sample_idx < kSlidingWindowNumSamples)
193 return 50000 + (sample_idx % 3) * 100;
194
195 // Then 10 samples around 80 MB
196 if (sample_idx < 10 + kSlidingWindowNumSamples)
197 return 80000 + (sample_idx % 3) * 200;
198
199 // Than back to 60 MB.
200 if (sample_idx < 2 * kSlidingWindowNumSamples)
201 return 60000 + (sample_idx % 3) * 100;
202
203 // Then 20 samples around 120 MB.
204 if (sample_idx < 20 + 2 * kSlidingWindowNumSamples)
205 return 120000 + (sample_idx % 3) * 200;
206
207 // Then back to idle to around 50 MB until the end.
208 return 50000 + (sample_idx % 3) * 100;
209 }
210
148 protected: 211 protected:
149 MemoryPeakDetector::DumpProvidersList dump_providers_; 212 MemoryPeakDetector::DumpProvidersList dump_providers_;
150 uint32_t get_mdp_call_count_; 213 uint32_t get_mdp_call_count_;
151 std::unique_ptr<MemoryPeakDetector, FriendDeleter> peak_detector_; 214 std::unique_ptr<MemoryPeakDetector, FriendDeleter> peak_detector_;
152 std::unique_ptr<Thread> bg_thread_; 215 std::unique_ptr<Thread> bg_thread_;
153 OnPeakDetectedWrapper on_peak_callback_; 216 OnPeakDetectedWrapper on_peak_callback_;
154 }; 217 };
155 218
219 const uint64_t MemoryPeakDetectorTest::kSlidingWindowNumSamples;
220
156 TEST_F(MemoryPeakDetectorTest, GetDumpProvidersFunctionCalled) { 221 TEST_F(MemoryPeakDetectorTest, GetDumpProvidersFunctionCalled) {
157 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 222 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
158 peak_detector_->Start(); 223 peak_detector_->Start(kConfigNoCallbacks);
159 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls()); 224 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
160 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState()); 225 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
161 226
162 peak_detector_->Stop(); 227 peak_detector_->Stop();
163 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 228 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
164 EXPECT_EQ(0u, GetNumPollingTasksRan()); 229 EXPECT_EQ(0u, GetNumPollingTasksRan());
165 } 230 }
166 231
167 TEST_F(MemoryPeakDetectorTest, NotifyBeforeInitialize) { 232 TEST_F(MemoryPeakDetectorTest, ThrottleAndNotifyBeforeInitialize) {
168 peak_detector_->TearDown(); 233 peak_detector_->TearDown();
169 234
170 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, 235 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
171 WaitableEvent::InitialState::NOT_SIGNALED); 236 WaitableEvent::InitialState::NOT_SIGNALED);
172 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(); 237 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
173 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_)) 238 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
174 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); })); 239 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
175 dump_providers_.push_back(mdp); 240 dump_providers_.push_back(mdp);
241 peak_detector_->Throttle();
176 peak_detector_->NotifyMemoryDumpProvidersChanged(); 242 peak_detector_->NotifyMemoryDumpProvidersChanged();
177 EXPECT_EQ(MemoryPeakDetector::NOT_INITIALIZED, GetPeakDetectorState()); 243 EXPECT_EQ(MemoryPeakDetector::NOT_INITIALIZED, GetPeakDetectorState());
178 RestartThreadAndReinitializePeakDetector(); 244 RestartThreadAndReinitializePeakDetector();
179 245
180 peak_detector_->Start(); 246 peak_detector_->Start(kConfigNoCallbacks);
181 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState()); 247 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
182 evt.Wait(); // Wait for a PollFastMemoryTotal() call. 248 evt.Wait(); // Wait for a PollFastMemoryTotal() call.
183 249
184 peak_detector_->Stop(); 250 peak_detector_->Stop();
185 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 251 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
186 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls()); 252 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
187 EXPECT_GE(GetNumPollingTasksRan(), 1u); 253 EXPECT_GE(GetNumPollingTasksRan(), 1u);
188 } 254 }
189 255
190 TEST_F(MemoryPeakDetectorTest, DoubleStop) { 256 TEST_F(MemoryPeakDetectorTest, DoubleStop) {
191 peak_detector_->Start(); 257 peak_detector_->Start(kConfigNoCallbacks);
192 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState()); 258 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
193 259
194 peak_detector_->Stop(); 260 peak_detector_->Stop();
195 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 261 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
196 262
197 peak_detector_->Stop(); 263 peak_detector_->Stop();
198 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 264 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
199 265
200 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls()); 266 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
201 EXPECT_EQ(0u, GetNumPollingTasksRan()); 267 EXPECT_EQ(0u, GetNumPollingTasksRan());
202 } 268 }
203 269
204 TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredBeforeStart) { 270 TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredBeforeStart) {
205 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, 271 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
206 WaitableEvent::InitialState::NOT_SIGNALED); 272 WaitableEvent::InitialState::NOT_SIGNALED);
207 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(); 273 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
208 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_)) 274 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
209 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); })); 275 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
210 dump_providers_.push_back(mdp); 276 dump_providers_.push_back(mdp);
211 277
212 peak_detector_->Start(); 278 peak_detector_->Start(kConfigNoCallbacks);
213 evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP. 279 evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP.
214 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState()); 280 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
215 281
216 peak_detector_->Stop(); 282 peak_detector_->Stop();
217 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 283 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
218 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls()); 284 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
219 EXPECT_GT(GetNumPollingTasksRan(), 0u); 285 EXPECT_GT(GetNumPollingTasksRan(), 0u);
220 } 286 }
221 287
222 TEST_F(MemoryPeakDetectorTest, ReInitializeAndRebindToNewThread) { 288 TEST_F(MemoryPeakDetectorTest, ReInitializeAndRebindToNewThread) {
223 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, 289 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
224 WaitableEvent::InitialState::NOT_SIGNALED); 290 WaitableEvent::InitialState::NOT_SIGNALED);
225 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(); 291 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
226 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_)) 292 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
227 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); })); 293 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
228 dump_providers_.push_back(mdp); 294 dump_providers_.push_back(mdp);
229 295
230 for (int i = 0; i < 5; ++i) { 296 for (int i = 0; i < 5; ++i) {
231 evt.Reset(); 297 evt.Reset();
232 peak_detector_->Start(); 298 peak_detector_->Start(kConfigNoCallbacks);
233 evt.Wait(); // Wait for a PollFastMemoryTotal() call. 299 evt.Wait(); // Wait for a PollFastMemoryTotal() call.
234 // Check that calling TearDown implicitly does a Stop(). 300 // Check that calling TearDown implicitly does a Stop().
235 peak_detector_->TearDown(); 301 peak_detector_->TearDown();
236 302
237 // Reinitialize and re-bind to a new task runner. 303 // Reinitialize and re-bind to a new task runner.
238 RestartThreadAndReinitializePeakDetector(); 304 RestartThreadAndReinitializePeakDetector();
239 } 305 }
240 } 306 }
241 307
242 TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredOutOfBand) { 308 TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredOutOfBand) {
243 peak_detector_->Start(); 309 peak_detector_->Start(kConfigNoCallbacks);
244 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState()); 310 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
245 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls()); 311 EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
246 312
247 // Check that no poll tasks are posted before any dump provider is registered. 313 // Check that no poll tasks are posted before any dump provider is registered.
248 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); 314 PlatformThread::Sleep(5 * kConfigNoCallbacks.polling_interval_ms * kMs);
249 EXPECT_EQ(0u, GetNumPollingTasksRan()); 315 EXPECT_EQ(0u, GetNumPollingTasksRan());
250 316
251 // Registed the MDP After Start() has been issued and expect that the 317 // Registed the MDP After Start() has been issued and expect that the
252 // PeakDetector transitions ENABLED -> RUNNING on the next 318 // PeakDetector transitions ENABLED -> RUNNING on the next
253 // NotifyMemoryDumpProvidersChanged() call. 319 // NotifyMemoryDumpProvidersChanged() call.
254 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, 320 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
255 WaitableEvent::InitialState::NOT_SIGNALED); 321 WaitableEvent::InitialState::NOT_SIGNALED);
256 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(); 322 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
257 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_)) 323 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
258 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); })); 324 .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
259 dump_providers_.push_back(mdp); 325 dump_providers_.push_back(mdp);
260 peak_detector_->NotifyMemoryDumpProvidersChanged(); 326 peak_detector_->NotifyMemoryDumpProvidersChanged();
261 327
262 evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP. 328 evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP.
263 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState()); 329 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
264 EXPECT_EQ(2u, GetNumGetDumpProvidersCalls()); 330 EXPECT_EQ(2u, GetNumGetDumpProvidersCalls());
265 331
266 // Now simulate the unregisration and expect that the PeakDetector transitions 332 // Now simulate the unregisration and expect that the PeakDetector transitions
267 // back to ENABLED. 333 // back to ENABLED.
268 dump_providers_.clear(); 334 dump_providers_.clear();
269 peak_detector_->NotifyMemoryDumpProvidersChanged(); 335 peak_detector_->NotifyMemoryDumpProvidersChanged();
270 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState()); 336 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
271 EXPECT_EQ(3u, GetNumGetDumpProvidersCalls()); 337 EXPECT_EQ(3u, GetNumGetDumpProvidersCalls());
272 uint32_t num_poll_tasks = GetNumPollingTasksRan(); 338 uint32_t num_poll_tasks = GetNumPollingTasksRan();
273 EXPECT_GT(num_poll_tasks, 0u); 339 EXPECT_GT(num_poll_tasks, 0u);
274 340
275 // At this point, no more polling tasks should be posted. 341 // At this point, no more polling tasks should be posted.
276 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); 342 PlatformThread::Sleep(5 * kConfigNoCallbacks.polling_interval_ms * kMs);
277 peak_detector_->Stop(); 343 peak_detector_->Stop();
278 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 344 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
279 EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan()); 345 EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan());
280 } 346 }
281 347
282 // Test that a sequence of Start()/Stop() back-to-back doesn't end up creating 348 // Test that a sequence of Start()/Stop() back-to-back doesn't end up creating
283 // several outstanding timer tasks and instead respects the polling_interval_ms. 349 // several outstanding timer tasks and instead respects the polling_interval_ms.
284 TEST_F(MemoryPeakDetectorTest, StartStopQuickly) { 350 TEST_F(MemoryPeakDetectorTest, StartStopQuickly) {
285 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, 351 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
286 WaitableEvent::InitialState::NOT_SIGNALED); 352 WaitableEvent::InitialState::NOT_SIGNALED);
287 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(); 353 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
288 dump_providers_.push_back(mdp); 354 dump_providers_.push_back(mdp);
289 const uint32_t kNumPolls = 20; 355 const uint32_t kNumPolls = 20;
290 uint32_t polls_done = 0; 356 uint32_t polls_done = 0;
291 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_)) 357 EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
292 .WillRepeatedly(Invoke([&polls_done, &evt, kNumPolls](uint64_t*) { 358 .WillRepeatedly(Invoke([&polls_done, &evt, kNumPolls](uint64_t*) {
293 if (++polls_done == kNumPolls) 359 if (++polls_done == kNumPolls)
294 evt.Signal(); 360 evt.Signal();
295 })); 361 }));
296 362
297 const TimeTicks tstart = TimeTicks::Now(); 363 const TimeTicks tstart = TimeTicks::Now();
298 for (int i = 0; i < 5; i++) { 364 for (int i = 0; i < 5; i++) {
299 peak_detector_->Start(); 365 peak_detector_->Start(kConfigNoCallbacks);
300 peak_detector_->Stop(); 366 peak_detector_->Stop();
301 } 367 }
302 peak_detector_->Start(); 368 peak_detector_->Start(kConfigNoCallbacks);
303 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState()); 369 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
304 evt.Wait(); // Wait for kNumPolls. 370 evt.Wait(); // Wait for kNumPolls.
305 const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF(); 371 const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF();
306 372
307 // TODO(primiano): this will become config.polling_interval_ms in the next CL. 373 EXPECT_GE(time_ms, kNumPolls * kConfigNoCallbacks.polling_interval_ms);
308 const uint32_t polling_interval_ms = 1;
309 EXPECT_GE(time_ms, kNumPolls * polling_interval_ms);
310 peak_detector_->Stop(); 374 peak_detector_->Stop();
311 } 375 }
312 376
313 TEST_F(MemoryPeakDetectorTest, RegisterAndUnregisterTwoDumpProviders) { 377 TEST_F(MemoryPeakDetectorTest, RegisterAndUnregisterTwoDumpProviders) {
314 WaitableEvent evt1(WaitableEvent::ResetPolicy::MANUAL, 378 WaitableEvent evt1(WaitableEvent::ResetPolicy::MANUAL,
315 WaitableEvent::InitialState::NOT_SIGNALED); 379 WaitableEvent::InitialState::NOT_SIGNALED);
316 WaitableEvent evt2(WaitableEvent::ResetPolicy::MANUAL, 380 WaitableEvent evt2(WaitableEvent::ResetPolicy::MANUAL,
317 WaitableEvent::InitialState::NOT_SIGNALED); 381 WaitableEvent::InitialState::NOT_SIGNALED);
318 scoped_refptr<MemoryDumpProviderInfo> mdp1 = CreateMockDumpProvider(); 382 scoped_refptr<MemoryDumpProviderInfo> mdp1 = CreateMockDumpProvider();
319 scoped_refptr<MemoryDumpProviderInfo> mdp2 = CreateMockDumpProvider(); 383 scoped_refptr<MemoryDumpProviderInfo> mdp2 = CreateMockDumpProvider();
320 EXPECT_CALL(GetMockMDP(mdp1), PollFastMemoryTotal(_)) 384 EXPECT_CALL(GetMockMDP(mdp1), PollFastMemoryTotal(_))
321 .WillRepeatedly(Invoke([&evt1](uint64_t*) { evt1.Signal(); })); 385 .WillRepeatedly(Invoke([&evt1](uint64_t*) { evt1.Signal(); }));
322 EXPECT_CALL(GetMockMDP(mdp2), PollFastMemoryTotal(_)) 386 EXPECT_CALL(GetMockMDP(mdp2), PollFastMemoryTotal(_))
323 .WillRepeatedly(Invoke([&evt2](uint64_t*) { evt2.Signal(); })); 387 .WillRepeatedly(Invoke([&evt2](uint64_t*) { evt2.Signal(); }));
324 388
325 // Register only one MDP and start the detector. 389 // Register only one MDP and start the detector.
326 dump_providers_.push_back(mdp1); 390 dump_providers_.push_back(mdp1);
327 peak_detector_->Start(); 391 peak_detector_->Start(kConfigNoCallbacks);
328 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState()); 392 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
329 393
330 // Wait for one poll task and then register also the other one. 394 // Wait for one poll task and then register also the other one.
331 evt1.Wait(); 395 evt1.Wait();
332 dump_providers_.push_back(mdp2); 396 dump_providers_.push_back(mdp2);
333 peak_detector_->NotifyMemoryDumpProvidersChanged(); 397 peak_detector_->NotifyMemoryDumpProvidersChanged();
334 evt2.Wait(); 398 evt2.Wait();
335 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState()); 399 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
336 400
337 // Now unregister the first MDP and check that everything is still running. 401 // Now unregister the first MDP and check that everything is still running.
(...skipping 21 matching lines...) Expand all
359 423
360 // Stop everything, tear down the MDPs, restart the detector and check that 424 // Stop everything, tear down the MDPs, restart the detector and check that
361 // it detector doesn't accidentally try to re-access them. 425 // it detector doesn't accidentally try to re-access them.
362 peak_detector_->Stop(); 426 peak_detector_->Stop();
363 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 427 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
364 dump_providers_.clear(); 428 dump_providers_.clear();
365 mdp1 = nullptr; 429 mdp1 = nullptr;
366 mdp2 = nullptr; 430 mdp2 = nullptr;
367 431
368 num_poll_tasks = GetNumPollingTasksRan(); 432 num_poll_tasks = GetNumPollingTasksRan();
369 peak_detector_->Start(); 433 peak_detector_->Start(kConfigNoCallbacks);
370 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState()); 434 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
371 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); 435 PlatformThread::Sleep(5 * kConfigNoCallbacks.polling_interval_ms * kMs);
372 436
373 peak_detector_->Stop(); 437 peak_detector_->Stop();
374 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState()); 438 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
375 EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan()); 439 EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan());
376 440
377 EXPECT_EQ(6u, GetNumGetDumpProvidersCalls()); 441 EXPECT_EQ(6u, GetNumGetDumpProvidersCalls());
378 } 442 }
379 443
444 // Tests the behavior of the static threshold detector, which is supposed to
445 // detect a peak whenever an increase >= threshold is detected.
446 TEST_F(MemoryPeakDetectorTest, StaticThreshold) {
447 const uint32_t kNumSamples = 2 * kSlidingWindowNumSamples;
448 constexpr uint32_t kNumSamplesPerStep = 10;
449 constexpr uint64_t kThreshold = 1000000;
450 peak_detector_->SetStaticThresholdForTesting(kThreshold);
451 const MemoryPeakDetector::Config kConfig = {
452 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
453 false /* enable_verbose_poll_tracing */
454 };
455
456 // The mocked PollFastMemoryTotal() will return a step function,
457 // e.g. (1, 1, 1, 5, 5, 5, ...) where the steps are 2x threshold, in order to
458 // trigger only the static threshold logic.
459 auto poll_fn = Bind(
460 [](const uint32_t kNumSamplesPerStep, const uint64_t kThreshold,
461 uint32_t sample_idx) -> uint64_t {
462 return (1 + sample_idx / kNumSamplesPerStep) * 2 * kThreshold;
463 },
464 kNumSamplesPerStep, kThreshold);
465 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
466 EXPECT_EQ(kNumSamples / kNumSamplesPerStep - 1, num_peaks);
467 }
468
469 // Checks the throttling logic of Config's |min_time_between_peaks_ms|.
470 TEST_F(MemoryPeakDetectorTest, PeakCallbackThrottling) {
471 const size_t kNumSamples = 2 * kSlidingWindowNumSamples;
472 constexpr uint64_t kThreshold = 1000000;
473 peak_detector_->SetStaticThresholdForTesting(kThreshold);
474 const MemoryPeakDetector::Config kConfig = {
475 1 /* polling_interval_ms */, 4 /* min_time_between_peaks_ms */,
476 false /* enable_verbose_poll_tracing */
477 };
478
479 // Each mock value returned is N * 2 * threshold, so all of them would be
480 // eligible to be a peak if throttling wasn't enabled.
481 auto poll_fn = Bind(
482 [](uint64_t kThreshold, uint32_t sample_idx) -> uint64_t {
483 return (sample_idx + 1) * 2 * kThreshold;
484 },
485 kThreshold);
486 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
487 const uint32_t kExpectedThrottlingRate =
488 kConfig.min_time_between_peaks_ms / kConfig.polling_interval_ms;
489 EXPECT_LT(num_peaks, kNumSamples / kExpectedThrottlingRate);
490 }
491
492 TEST_F(MemoryPeakDetectorTest, StdDev) {
493 // Set the threshold to some arbitrarily high value, so that the static
494 // threshold logic is not hit in this test.
495 constexpr uint64_t kThreshold = 1024 * 1024 * 1024;
496 peak_detector_->SetStaticThresholdForTesting(kThreshold);
497 const size_t kNumSamples = 3 * kSlidingWindowNumSamples;
498 const MemoryPeakDetector::Config kConfig = {
499 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
500 false /* enable_verbose_poll_tracing */
501 };
502
503 auto poll_fn = Bind(&PollFunctionThatCausesPeakViaStdDev);
504 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
505 EXPECT_EQ(2u, num_peaks); // 80 MB, 120 MB.
506 }
507
508 // Tests that Throttle() actually holds back peak notifications.
509 TEST_F(MemoryPeakDetectorTest, Throttle) {
510 constexpr uint64_t kThreshold = 1024 * 1024 * 1024;
511 const uint32_t kNumSamples = 3 * kSlidingWindowNumSamples;
512 peak_detector_->SetStaticThresholdForTesting(kThreshold);
513 const MemoryPeakDetector::Config kConfig = {
514 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
515 false /* enable_verbose_poll_tracing */
516 };
517
518 auto poll_fn = Bind(
519 [](MemoryPeakDetector* peak_detector, uint32_t sample_idx) -> uint64_t {
520 if (sample_idx % 20 == 20 - 1)
521 peak_detector->Throttle();
522 return PollFunctionThatCausesPeakViaStdDev(sample_idx);
523 },
524 Unretained(&*peak_detector_));
525 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
526 EXPECT_EQ(0u, num_peaks);
527 }
528
529 // Tests that the windows stddev state is not carried over through
530 // Stop() -> Start() sequences.
531 TEST_F(MemoryPeakDetectorTest, RestartClearsState) {
532 constexpr uint64_t kThreshold = 1024 * 1024 * 1024;
533 peak_detector_->SetStaticThresholdForTesting(kThreshold);
534 const size_t kNumSamples = 3 * kSlidingWindowNumSamples;
535 const MemoryPeakDetector::Config kConfig = {
536 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
537 false /* enable_verbose_poll_tracing */
538 };
539 auto poll_fn = Bind(
540 [](MemoryPeakDetector* peak_detector,
541 const uint32_t kSlidingWindowNumSamples,
542 MemoryPeakDetector::Config kConfig, uint32_t sample_idx) -> uint64_t {
543 if (sample_idx % kSlidingWindowNumSamples ==
544 kSlidingWindowNumSamples - 1) {
545 peak_detector->Stop();
546 peak_detector->Start(kConfig);
547 }
548 return PollFunctionThatCausesPeakViaStdDev(sample_idx);
549 },
550 Unretained(&*peak_detector_), kSlidingWindowNumSamples, kConfig);
551 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
552 EXPECT_EQ(0u, num_peaks);
553 }
554
380 } // namespace trace_event 555 } // namespace trace_event
381 } // namespace base 556 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/memory_peak_detector.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698