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