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 "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" |
(...skipping 10 matching lines...) Expand all Loading... |
21 using ::testing::_; | 21 using ::testing::_; |
22 using ::testing::Invoke; | 22 using ::testing::Invoke; |
23 using ::testing::Return; | 23 using ::testing::Return; |
24 | 24 |
25 namespace base { | 25 namespace base { |
26 namespace trace_event { | 26 namespace trace_event { |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 const TimeDelta kMs = TimeDelta::FromMilliseconds(1); | 30 const TimeDelta kMs = TimeDelta::FromMilliseconds(1); |
31 const MemoryPeakDetector::Config kConfigNoCallbacks = { | 31 const MemoryPeakDetector::Config kConfigNoCallbacks( |
32 1 /* polling_interval_ms */, 60000 /* min_time_between_peaks_ms */, | 32 1 /* polling_interval_ms */, |
| 33 60000 /* min_time_between_peaks_ms */, |
33 false /* enable_verbose_poll_tracing */ | 34 false /* enable_verbose_poll_tracing */ |
34 }; | 35 ); |
35 | 36 |
36 class MockMemoryDumpProvider : public MemoryDumpProvider { | 37 class MockMemoryDumpProvider : public MemoryDumpProvider { |
37 public: | 38 public: |
38 bool OnMemoryDump(const MemoryDumpArgs&, ProcessMemoryDump*) override { | 39 bool OnMemoryDump(const MemoryDumpArgs&, ProcessMemoryDump*) override { |
39 NOTREACHED(); | 40 NOTREACHED(); |
40 return true; | 41 return true; |
41 } | 42 } |
42 | 43 |
43 MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t*)); | 44 MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t*)); |
44 }; | 45 }; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 | 78 |
78 void SetUp() override { | 79 void SetUp() override { |
79 get_mdp_call_count_ = 0; | 80 get_mdp_call_count_ = 0; |
80 RestartThreadAndReinitializePeakDetector(); | 81 RestartThreadAndReinitializePeakDetector(); |
81 } | 82 } |
82 | 83 |
83 void TearDown() override { | 84 void TearDown() override { |
84 peak_detector_->TearDown(); | 85 peak_detector_->TearDown(); |
85 bg_thread_->FlushForTesting(); | 86 bg_thread_->FlushForTesting(); |
86 EXPECT_EQ(MemoryPeakDetector::NOT_INITIALIZED, GetPeakDetectorState()); | 87 EXPECT_EQ(MemoryPeakDetector::NOT_INITIALIZED, GetPeakDetectorState()); |
| 88 bg_thread_.reset(); |
87 dump_providers_.clear(); | 89 dump_providers_.clear(); |
88 } | 90 } |
89 | 91 |
90 // Calls MemoryPeakDetector::state_for_testing() on the bg thread and returns | 92 // Calls MemoryPeakDetector::state_for_testing() on the bg thread and returns |
91 // the result on the current thread. | 93 // the result on the current thread. |
92 MemoryPeakDetector::State GetPeakDetectorState() { | 94 MemoryPeakDetector::State GetPeakDetectorState() { |
93 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, | 95 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, |
94 WaitableEvent::InitialState::NOT_SIGNALED); | 96 WaitableEvent::InitialState::NOT_SIGNALED); |
95 MemoryPeakDetector::State res = MemoryPeakDetector::NOT_INITIALIZED; | 97 MemoryPeakDetector::State res = MemoryPeakDetector::NOT_INITIALIZED; |
96 auto get_fn = [](MemoryPeakDetector* peak_detector, WaitableEvent* evt, | 98 auto get_fn = [](MemoryPeakDetector* peak_detector, WaitableEvent* evt, |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 EXPECT_EQ(6u, GetNumGetDumpProvidersCalls()); | 443 EXPECT_EQ(6u, GetNumGetDumpProvidersCalls()); |
442 } | 444 } |
443 | 445 |
444 // Tests the behavior of the static threshold detector, which is supposed to | 446 // Tests the behavior of the static threshold detector, which is supposed to |
445 // detect a peak whenever an increase >= threshold is detected. | 447 // detect a peak whenever an increase >= threshold is detected. |
446 TEST_F(MemoryPeakDetectorTest, StaticThreshold) { | 448 TEST_F(MemoryPeakDetectorTest, StaticThreshold) { |
447 const uint32_t kNumSamples = 2 * kSlidingWindowNumSamples; | 449 const uint32_t kNumSamples = 2 * kSlidingWindowNumSamples; |
448 constexpr uint32_t kNumSamplesPerStep = 10; | 450 constexpr uint32_t kNumSamplesPerStep = 10; |
449 constexpr uint64_t kThreshold = 1000000; | 451 constexpr uint64_t kThreshold = 1000000; |
450 peak_detector_->SetStaticThresholdForTesting(kThreshold); | 452 peak_detector_->SetStaticThresholdForTesting(kThreshold); |
451 const MemoryPeakDetector::Config kConfig = { | 453 const MemoryPeakDetector::Config kConfig( |
452 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, | 454 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, |
453 false /* enable_verbose_poll_tracing */ | 455 false /* enable_verbose_poll_tracing */ |
454 }; | 456 ); |
455 | 457 |
456 // The mocked PollFastMemoryTotal() will return a step function, | 458 // 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 | 459 // e.g. (1, 1, 1, 5, 5, 5, ...) where the steps are 2x threshold, in order to |
458 // trigger only the static threshold logic. | 460 // trigger only the static threshold logic. |
459 auto poll_fn = Bind( | 461 auto poll_fn = Bind( |
460 [](const uint32_t kNumSamplesPerStep, const uint64_t kThreshold, | 462 [](const uint32_t kNumSamplesPerStep, const uint64_t kThreshold, |
461 uint32_t sample_idx) -> uint64_t { | 463 uint32_t sample_idx) -> uint64_t { |
462 return (1 + sample_idx / kNumSamplesPerStep) * 2 * kThreshold; | 464 return (1 + sample_idx / kNumSamplesPerStep) * 2 * kThreshold; |
463 }, | 465 }, |
464 kNumSamplesPerStep, kThreshold); | 466 kNumSamplesPerStep, kThreshold); |
465 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); | 467 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); |
466 EXPECT_EQ(kNumSamples / kNumSamplesPerStep - 1, num_peaks); | 468 EXPECT_EQ(kNumSamples / kNumSamplesPerStep - 1, num_peaks); |
467 } | 469 } |
468 | 470 |
469 // Checks the throttling logic of Config's |min_time_between_peaks_ms|. | 471 // Checks the throttling logic of Config's |min_time_between_peaks_ms|. |
470 TEST_F(MemoryPeakDetectorTest, PeakCallbackThrottling) { | 472 TEST_F(MemoryPeakDetectorTest, PeakCallbackThrottling) { |
471 const size_t kNumSamples = 2 * kSlidingWindowNumSamples; | 473 const size_t kNumSamples = 2 * kSlidingWindowNumSamples; |
472 constexpr uint64_t kThreshold = 1000000; | 474 constexpr uint64_t kThreshold = 1000000; |
473 peak_detector_->SetStaticThresholdForTesting(kThreshold); | 475 peak_detector_->SetStaticThresholdForTesting(kThreshold); |
474 const MemoryPeakDetector::Config kConfig = { | 476 const MemoryPeakDetector::Config kConfig( |
475 1 /* polling_interval_ms */, 4 /* min_time_between_peaks_ms */, | 477 1 /* polling_interval_ms */, 4 /* min_time_between_peaks_ms */, |
476 false /* enable_verbose_poll_tracing */ | 478 false /* enable_verbose_poll_tracing */ |
477 }; | 479 ); |
478 | 480 |
479 // Each mock value returned is N * 2 * threshold, so all of them would be | 481 // 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. | 482 // eligible to be a peak if throttling wasn't enabled. |
481 auto poll_fn = Bind( | 483 auto poll_fn = Bind( |
482 [](uint64_t kThreshold, uint32_t sample_idx) -> uint64_t { | 484 [](uint64_t kThreshold, uint32_t sample_idx) -> uint64_t { |
483 return (sample_idx + 1) * 2 * kThreshold; | 485 return (sample_idx + 1) * 2 * kThreshold; |
484 }, | 486 }, |
485 kThreshold); | 487 kThreshold); |
486 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); | 488 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); |
487 const uint32_t kExpectedThrottlingRate = | 489 const uint32_t kExpectedThrottlingRate = |
488 kConfig.min_time_between_peaks_ms / kConfig.polling_interval_ms; | 490 kConfig.min_time_between_peaks_ms / kConfig.polling_interval_ms; |
489 EXPECT_LT(num_peaks, kNumSamples / kExpectedThrottlingRate); | 491 EXPECT_LT(num_peaks, kNumSamples / kExpectedThrottlingRate); |
490 } | 492 } |
491 | 493 |
492 TEST_F(MemoryPeakDetectorTest, StdDev) { | 494 TEST_F(MemoryPeakDetectorTest, StdDev) { |
493 // Set the threshold to some arbitrarily high value, so that the static | 495 // Set the threshold to some arbitrarily high value, so that the static |
494 // threshold logic is not hit in this test. | 496 // threshold logic is not hit in this test. |
495 constexpr uint64_t kThreshold = 1024 * 1024 * 1024; | 497 constexpr uint64_t kThreshold = 1024 * 1024 * 1024; |
496 peak_detector_->SetStaticThresholdForTesting(kThreshold); | 498 peak_detector_->SetStaticThresholdForTesting(kThreshold); |
497 const size_t kNumSamples = 3 * kSlidingWindowNumSamples; | 499 const size_t kNumSamples = 3 * kSlidingWindowNumSamples; |
498 const MemoryPeakDetector::Config kConfig = { | 500 const MemoryPeakDetector::Config kConfig( |
499 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, | 501 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, |
500 false /* enable_verbose_poll_tracing */ | 502 false /* enable_verbose_poll_tracing */ |
501 }; | 503 ); |
502 | 504 |
503 auto poll_fn = Bind(&PollFunctionThatCausesPeakViaStdDev); | 505 auto poll_fn = Bind(&PollFunctionThatCausesPeakViaStdDev); |
504 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); | 506 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); |
505 EXPECT_EQ(2u, num_peaks); // 80 MB, 120 MB. | 507 EXPECT_EQ(2u, num_peaks); // 80 MB, 120 MB. |
506 } | 508 } |
507 | 509 |
508 // Tests that Throttle() actually holds back peak notifications. | 510 // Tests that Throttle() actually holds back peak notifications. |
509 TEST_F(MemoryPeakDetectorTest, Throttle) { | 511 TEST_F(MemoryPeakDetectorTest, Throttle) { |
510 constexpr uint64_t kThreshold = 1024 * 1024 * 1024; | 512 constexpr uint64_t kThreshold = 1024 * 1024 * 1024; |
511 const uint32_t kNumSamples = 3 * kSlidingWindowNumSamples; | 513 const uint32_t kNumSamples = 3 * kSlidingWindowNumSamples; |
512 peak_detector_->SetStaticThresholdForTesting(kThreshold); | 514 peak_detector_->SetStaticThresholdForTesting(kThreshold); |
513 const MemoryPeakDetector::Config kConfig = { | 515 const MemoryPeakDetector::Config kConfig( |
514 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, | 516 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, |
515 false /* enable_verbose_poll_tracing */ | 517 false /* enable_verbose_poll_tracing */ |
516 }; | 518 ); |
517 | 519 |
518 auto poll_fn = Bind( | 520 auto poll_fn = Bind( |
519 [](MemoryPeakDetector* peak_detector, uint32_t sample_idx) -> uint64_t { | 521 [](MemoryPeakDetector* peak_detector, uint32_t sample_idx) -> uint64_t { |
520 if (sample_idx % 20 == 20 - 1) | 522 if (sample_idx % 20 == 20 - 1) |
521 peak_detector->Throttle(); | 523 peak_detector->Throttle(); |
522 return PollFunctionThatCausesPeakViaStdDev(sample_idx); | 524 return PollFunctionThatCausesPeakViaStdDev(sample_idx); |
523 }, | 525 }, |
524 Unretained(&*peak_detector_)); | 526 Unretained(&*peak_detector_)); |
525 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); | 527 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); |
526 EXPECT_EQ(0u, num_peaks); | 528 EXPECT_EQ(0u, num_peaks); |
527 } | 529 } |
528 | 530 |
529 // Tests that the windows stddev state is not carried over through | 531 // Tests that the windows stddev state is not carried over through |
530 // Stop() -> Start() sequences. | 532 // Stop() -> Start() sequences. |
531 TEST_F(MemoryPeakDetectorTest, RestartClearsState) { | 533 TEST_F(MemoryPeakDetectorTest, RestartClearsState) { |
532 constexpr uint64_t kThreshold = 1024 * 1024 * 1024; | 534 constexpr uint64_t kThreshold = 1024 * 1024 * 1024; |
533 peak_detector_->SetStaticThresholdForTesting(kThreshold); | 535 peak_detector_->SetStaticThresholdForTesting(kThreshold); |
534 const size_t kNumSamples = 3 * kSlidingWindowNumSamples; | 536 const size_t kNumSamples = 3 * kSlidingWindowNumSamples; |
535 const MemoryPeakDetector::Config kConfig = { | 537 const MemoryPeakDetector::Config kConfig( |
536 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, | 538 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */, |
537 false /* enable_verbose_poll_tracing */ | 539 false /* enable_verbose_poll_tracing */ |
538 }; | 540 ); |
539 auto poll_fn = Bind( | 541 auto poll_fn = Bind( |
540 [](MemoryPeakDetector* peak_detector, | 542 [](MemoryPeakDetector* peak_detector, |
541 const uint32_t kSlidingWindowNumSamples, | 543 const uint32_t kSlidingWindowNumSamples, |
542 MemoryPeakDetector::Config kConfig, uint32_t sample_idx) -> uint64_t { | 544 MemoryPeakDetector::Config kConfig, uint32_t sample_idx) -> uint64_t { |
543 if (sample_idx % kSlidingWindowNumSamples == | 545 if (sample_idx % kSlidingWindowNumSamples == |
544 kSlidingWindowNumSamples - 1) { | 546 kSlidingWindowNumSamples - 1) { |
545 peak_detector->Stop(); | 547 peak_detector->Stop(); |
546 peak_detector->Start(kConfig); | 548 peak_detector->Start(kConfig); |
547 } | 549 } |
548 return PollFunctionThatCausesPeakViaStdDev(sample_idx); | 550 return PollFunctionThatCausesPeakViaStdDev(sample_idx); |
549 }, | 551 }, |
550 Unretained(&*peak_detector_), kSlidingWindowNumSamples, kConfig); | 552 Unretained(&*peak_detector_), kSlidingWindowNumSamples, kConfig); |
551 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); | 553 uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn); |
552 EXPECT_EQ(0u, num_peaks); | 554 EXPECT_EQ(0u, num_peaks); |
553 } | 555 } |
554 | 556 |
555 } // namespace trace_event | 557 } // namespace trace_event |
556 } // namespace base | 558 } // namespace base |
OLD | NEW |