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

Side by Side Diff: content/browser/memory/memory_coordinator_impl_unittest.cc

Issue 2763933002: memory coordinator: Purge memory under memory pressure (Closed)
Patch Set: Use int64_t Created 3 years, 9 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
OLDNEW
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 "content/browser/memory/memory_coordinator_impl.h" 5 #include "content/browser/memory/memory_coordinator_impl.h"
6 6
7 #include "base/memory/memory_coordinator_client_registry.h" 7 #include "base/memory/memory_coordinator_client_registry.h"
8 #include "base/memory/memory_coordinator_proxy.h" 8 #include "base/memory/memory_coordinator_proxy.h"
9 #include "base/memory/memory_pressure_monitor.h" 9 #include "base/memory/memory_pressure_monitor.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 59
60 // A mock MemoryCoordinatorClient, for testing interaction between MC and 60 // A mock MemoryCoordinatorClient, for testing interaction between MC and
61 // clients. 61 // clients.
62 class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient { 62 class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient {
63 public: 63 public:
64 void OnMemoryStateChange(base::MemoryState state) override { 64 void OnMemoryStateChange(base::MemoryState state) override {
65 did_state_changed_ = true; 65 did_state_changed_ = true;
66 state_ = state; 66 state_ = state;
67 } 67 }
68 68
69 void OnPurgeMemory() override { ++purge_memory_calls_; }
70
69 bool did_state_changed() const { return did_state_changed_; } 71 bool did_state_changed() const { return did_state_changed_; }
70 base::MemoryState state() const { return state_; } 72 base::MemoryState state() const { return state_; }
73 int purge_memory_calls() const { return purge_memory_calls_; }
71 74
72 private: 75 private:
73 bool did_state_changed_ = false; 76 bool did_state_changed_ = false;
74 base::MemoryState state_ = base::MemoryState::NORMAL; 77 base::MemoryState state_ = base::MemoryState::NORMAL;
78 int purge_memory_calls_ = 0;
75 }; 79 };
76 80
77 class MockMemoryMonitor : public MemoryMonitor { 81 class MockMemoryMonitor : public MemoryMonitor {
78 public: 82 public:
79 MockMemoryMonitor() {} 83 MockMemoryMonitor() {}
80 ~MockMemoryMonitor() override {} 84 ~MockMemoryMonitor() override {}
81 85
82 void SetFreeMemoryUntilCriticalMB(int free_memory) { 86 void SetFreeMemoryUntilCriticalMB(int free_memory) {
83 free_memory_ = free_memory; 87 free_memory_ = free_memory;
84 } 88 }
85 89
86 // MemoryMonitor implementation 90 // MemoryMonitor implementation
87 int GetFreeMemoryUntilCriticalMB() override { return free_memory_; } 91 int GetFreeMemoryUntilCriticalMB() override { return free_memory_; }
88 92
89 private: 93 private:
90 int free_memory_ = 0; 94 int free_memory_ = 0;
91 95
92 DISALLOW_COPY_AND_ASSIGN(MockMemoryMonitor); 96 DISALLOW_COPY_AND_ASSIGN(MockMemoryMonitor);
93 }; 97 };
94 98
95 class TestMemoryCoordinatorDelegate : public MemoryCoordinatorDelegate { 99 class TestMemoryCoordinatorDelegate : public MemoryCoordinatorDelegate {
96 public: 100 public:
97 TestMemoryCoordinatorDelegate() {} 101 TestMemoryCoordinatorDelegate() {}
98 ~TestMemoryCoordinatorDelegate() override {} 102 ~TestMemoryCoordinatorDelegate() override {}
99 103
100 bool CanSuspendBackgroundedRenderer(int render_process_id) override { 104 bool CanSuspendBackgroundedRenderer(int render_process_id) override {
101 return true; 105 return true;
102 } 106 }
103 107
104 void DiscardTab() override { ++discard_tab_count_; } 108 bool DiscardTab() override {
109 const int kMaxDiscardTabCount = 2;
110 if (discard_tab_count_ >= kMaxDiscardTabCount)
111 return false;
112 ++discard_tab_count_;
113 return true;
114 }
105 115
106 int discard_tab_count() const { return discard_tab_count_; } 116 int discard_tab_count() const { return discard_tab_count_; }
107 117
108 private: 118 private:
109 int discard_tab_count_ = 0; 119 int discard_tab_count_ = 0;
110 120
111 DISALLOW_COPY_AND_ASSIGN(TestMemoryCoordinatorDelegate); 121 DISALLOW_COPY_AND_ASSIGN(TestMemoryCoordinatorDelegate);
112 }; 122 };
113 123
114 // A MemoryCoordinatorImpl that can be directly constructed. 124 // A MemoryCoordinatorImpl that can be directly constructed.
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 EXPECT_EQ(2, delegate->discard_tab_count()); 569 EXPECT_EQ(2, delegate->discard_tab_count());
560 570
561 // Back to NORMAL. Tab discarding should stop. 571 // Back to NORMAL. Tab discarding should stop.
562 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50); 572 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50);
563 task_runner_->FastForwardBy(interval); 573 task_runner_->FastForwardBy(interval);
564 EXPECT_EQ(2, delegate->discard_tab_count()); 574 EXPECT_EQ(2, delegate->discard_tab_count());
565 task_runner_->FastForwardBy(interval); 575 task_runner_->FastForwardBy(interval);
566 EXPECT_EQ(2, delegate->discard_tab_count()); 576 EXPECT_EQ(2, delegate->discard_tab_count());
567 } 577 }
568 578
579 TEST_F(MemoryCoordinatorImplTest, OnWarningCondition) {
580 MockMemoryCoordinatorClient client;
581 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
582 auto* child1 = coordinator_->CreateChildMemoryCoordinator(1);
583 auto* child2 = coordinator_->CreateChildMemoryCoordinator(2);
584 base::TimeDelta interval =
585 coordinator_->background_child_purge_candidate_period_ +
586 base::TimeDelta::FromSeconds(1);
587
588 // child1: Foreground, child2: Background
589 coordinator_->OnChildVisibilityChanged(1, true);
590 coordinator_->OnChildVisibilityChanged(2, false);
591
592 // Note: we never ask foreground processes (including the browser process) to
593 // purge memory on WARNING condition.
594
595 // Don't ask the background child to purge until the child remains
596 // backgrounded for a certain period of time.
597 coordinator_->OnWarningCondition();
598 RunUntilIdle();
599 EXPECT_EQ(0, client.purge_memory_calls());
600 EXPECT_EQ(0, child1->purge_memory_calls());
601 EXPECT_EQ(0, child2->purge_memory_calls());
602
603 // After a certain period of time is passed, request the child to purge
604 // memory.
605 task_runner_->FastForwardBy(interval);
606 coordinator_->OnWarningCondition();
607 task_runner_->RunUntilIdle();
608 RunUntilIdle();
609 EXPECT_EQ(0, client.purge_memory_calls());
610 EXPECT_EQ(0, child1->purge_memory_calls());
611 EXPECT_EQ(1, child2->purge_memory_calls());
612
613 // Don't purge memory more than once when the child stays backgrounded.
614 task_runner_->FastForwardBy(interval);
615 coordinator_->OnWarningCondition();
616 RunUntilIdle();
617 EXPECT_EQ(0, client.purge_memory_calls());
618 EXPECT_EQ(0, child1->purge_memory_calls());
619 EXPECT_EQ(1, child2->purge_memory_calls());
620
621 // The background child goes to foreground, goes to background, then a
622 // certain period of time is passed. Another purging request should be sent.
623 coordinator_->OnChildVisibilityChanged(2, true);
624 coordinator_->OnChildVisibilityChanged(2, false);
625 task_runner_->FastForwardBy(interval);
626 coordinator_->OnWarningCondition();
627 RunUntilIdle();
628 EXPECT_EQ(0, client.purge_memory_calls());
629 EXPECT_EQ(0, child1->purge_memory_calls());
630 EXPECT_EQ(2, child2->purge_memory_calls());
631
632 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
633 }
634
635 TEST_F(MemoryCoordinatorImplTest, OnCriticalCondition) {
636 MockMemoryCoordinatorClient client;
637 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
638 auto* child1 = coordinator_->CreateChildMemoryCoordinator(1);
639 auto* child2 = coordinator_->CreateChildMemoryCoordinator(2);
640 auto* delegate = coordinator_->GetDelegate();
641 base::TimeDelta interval =
642 coordinator_->background_child_purge_candidate_period_ +
643 base::TimeDelta::FromSeconds(1);
644
645 // child1: Foreground, child2: Background
646 coordinator_->OnChildVisibilityChanged(1, true);
647 coordinator_->OnChildVisibilityChanged(2, false);
648
649 // Our mocked |delegate| allows discarding tab twice. While tab discarding
650 // succeeds we don't purge memory.
651 coordinator_->OnCriticalCondition();
652 task_runner_->RunUntilIdle();
653 RunUntilIdle();
654 EXPECT_EQ(1, delegate->discard_tab_count());
655 EXPECT_EQ(0, client.purge_memory_calls());
656 EXPECT_EQ(0, child1->purge_memory_calls());
657 EXPECT_EQ(0, child2->purge_memory_calls());
658 task_runner_->FastForwardBy(interval);
659 coordinator_->OnCriticalCondition();
660 RunUntilIdle();
661 EXPECT_EQ(2, delegate->discard_tab_count());
662 EXPECT_EQ(0, client.purge_memory_calls());
663 EXPECT_EQ(0, child1->purge_memory_calls());
664 EXPECT_EQ(0, child2->purge_memory_calls());
665
666 // Purge memory from all children regardless of their visibility.
667 task_runner_->FastForwardBy(interval);
668 coordinator_->OnCriticalCondition();
669 RunUntilIdle();
670 task_runner_->FastForwardBy(interval);
671 coordinator_->OnCriticalCondition();
672 RunUntilIdle();
673 EXPECT_EQ(2, delegate->discard_tab_count());
674 EXPECT_EQ(0, client.purge_memory_calls());
675 EXPECT_EQ(1, child1->purge_memory_calls());
676 EXPECT_EQ(1, child2->purge_memory_calls());
677
678 // Purge memory from browser process only after we asked all children to
679 // purge memory.
680 task_runner_->FastForwardBy(interval);
681 coordinator_->OnCriticalCondition();
682 RunUntilIdle();
683 EXPECT_EQ(2, delegate->discard_tab_count());
684 EXPECT_EQ(1, client.purge_memory_calls());
685 EXPECT_EQ(1, child1->purge_memory_calls());
686 EXPECT_EQ(1, child2->purge_memory_calls());
687
688 // Don't request purging for a certain period of time if we already requested.
689 task_runner_->FastForwardBy(interval);
690 coordinator_->OnCriticalCondition();
691 RunUntilIdle();
692 EXPECT_EQ(2, delegate->discard_tab_count());
693 EXPECT_EQ(1, client.purge_memory_calls());
694 EXPECT_EQ(1, child1->purge_memory_calls());
695 EXPECT_EQ(1, child2->purge_memory_calls());
696
697 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
698 }
699
569 #if defined(OS_ANDROID) 700 #if defined(OS_ANDROID)
570 // TODO(jcivelli): Broken on Android. http://crbug.com/678665 701 // TODO(jcivelli): Broken on Android. http://crbug.com/678665
571 #define MAYBE_GetStateForProcess DISABLED_GetStateForProcess 702 #define MAYBE_GetStateForProcess DISABLED_GetStateForProcess
572 #else 703 #else
573 #define MAYBE_GetStateForProcess GetStateForProcess 704 #define MAYBE_GetStateForProcess GetStateForProcess
574 #endif 705 #endif
575 TEST_F(MemoryCoordinatorImplTest, MAYBE_GetStateForProcess) { 706 TEST_F(MemoryCoordinatorImplTest, MAYBE_GetStateForProcess) {
576 EXPECT_EQ(base::MemoryState::UNKNOWN, 707 EXPECT_EQ(base::MemoryState::UNKNOWN,
577 coordinator_->GetStateForProcess(base::kNullProcessHandle)); 708 coordinator_->GetStateForProcess(base::kNullProcessHandle));
578 EXPECT_EQ(base::MemoryState::NORMAL, 709 EXPECT_EQ(base::MemoryState::NORMAL,
(...skipping 19 matching lines...) Expand all
598 729
599 EXPECT_TRUE( 730 EXPECT_TRUE(
600 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); 731 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED));
601 EXPECT_EQ(base::MemoryState::THROTTLED, 732 EXPECT_EQ(base::MemoryState::THROTTLED,
602 coordinator_->GetStateForProcess(process1.Handle())); 733 coordinator_->GetStateForProcess(process1.Handle()));
603 EXPECT_EQ(base::MemoryState::NORMAL, 734 EXPECT_EQ(base::MemoryState::NORMAL,
604 coordinator_->GetStateForProcess(process2.Handle())); 735 coordinator_->GetStateForProcess(process2.Handle()));
605 } 736 }
606 737
607 } // namespace content 738 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698