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

Side by Side Diff: content/child/scheduler/prioritizing_task_queue_selector.cc

Issue 1025323003: Introduce a SchedulerHelper in content/child/scheduler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/renderer/scheduler/renderer_task_queue_selector.h" 5 #include "content/child/scheduler/prioritizing_task_queue_selector.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/pending_task.h" 8 #include "base/pending_task.h"
9 #include "base/trace_event/trace_event_argument.h" 9 #include "base/trace_event/trace_event_argument.h"
10 10
11 namespace content { 11 namespace content {
12 12
13 RendererTaskQueueSelector::RendererTaskQueueSelector() : starvation_count_(0) { 13 PrioritizingTaskQueueSelector::PrioritizingTaskQueueSelector()
14 : starvation_count_(0) {
14 } 15 }
15 16
16 RendererTaskQueueSelector::~RendererTaskQueueSelector() { 17 PrioritizingTaskQueueSelector::~PrioritizingTaskQueueSelector() {
17 } 18 }
18 19
19 void RendererTaskQueueSelector::RegisterWorkQueues( 20 void PrioritizingTaskQueueSelector::RegisterWorkQueues(
20 const std::vector<const base::TaskQueue*>& work_queues) { 21 const std::vector<const base::TaskQueue*>& work_queues) {
21 DCHECK(main_thread_checker_.CalledOnValidThread()); 22 DCHECK(main_thread_checker_.CalledOnValidThread());
22 work_queues_ = work_queues; 23 work_queues_ = work_queues;
23 for (auto& queue_priority : queue_priorities_) { 24 for (auto& queue_priority : queue_priorities_) {
24 queue_priority.clear(); 25 queue_priority.clear();
25 } 26 }
26 27
27 // By default, all work queues are set to normal priority. 28 // By default, all work queues are set to normal priority.
28 for (size_t i = 0; i < work_queues.size(); i++) { 29 for (size_t i = 0; i < work_queues.size(); i++) {
29 queue_priorities_[NORMAL_PRIORITY].insert(i); 30 queue_priorities_[NORMAL_PRIORITY].insert(i);
30 } 31 }
31 } 32 }
32 33
33 void RendererTaskQueueSelector::SetQueuePriority(size_t queue_index, 34 void PrioritizingTaskQueueSelector::SetQueuePriority(size_t queue_index,
34 QueuePriority priority) { 35 QueuePriority priority) {
35 DCHECK(main_thread_checker_.CalledOnValidThread()); 36 DCHECK(main_thread_checker_.CalledOnValidThread());
36 DCHECK_LT(queue_index, work_queues_.size()); 37 DCHECK_LT(queue_index, work_queues_.size());
37 DCHECK_LT(priority, QUEUE_PRIORITY_COUNT); 38 DCHECK_LT(priority, QUEUE_PRIORITY_COUNT);
38 DisableQueue(queue_index); 39 DisableQueue(queue_index);
39 queue_priorities_[priority].insert(queue_index); 40 queue_priorities_[priority].insert(queue_index);
40 } 41 }
41 42
42 void RendererTaskQueueSelector::EnableQueue(size_t queue_index, 43 void PrioritizingTaskQueueSelector::EnableQueue(size_t queue_index,
43 QueuePriority priority) { 44 QueuePriority priority) {
44 SetQueuePriority(queue_index, priority); 45 SetQueuePriority(queue_index, priority);
45 } 46 }
46 47
47 void RendererTaskQueueSelector::DisableQueue(size_t queue_index) { 48 void PrioritizingTaskQueueSelector::DisableQueue(size_t queue_index) {
48 DCHECK(main_thread_checker_.CalledOnValidThread()); 49 DCHECK(main_thread_checker_.CalledOnValidThread());
49 DCHECK_LT(queue_index, work_queues_.size()); 50 DCHECK_LT(queue_index, work_queues_.size());
50 for (auto& queue_priority : queue_priorities_) { 51 for (auto& queue_priority : queue_priorities_) {
51 queue_priority.erase(queue_index); 52 queue_priority.erase(queue_index);
52 } 53 }
53 } 54 }
54 55
55 bool RendererTaskQueueSelector::IsQueueEnabled(size_t queue_index) const { 56 bool PrioritizingTaskQueueSelector::IsQueueEnabled(size_t queue_index) const {
56 DCHECK(main_thread_checker_.CalledOnValidThread()); 57 DCHECK(main_thread_checker_.CalledOnValidThread());
57 DCHECK_LT(queue_index, work_queues_.size()); 58 DCHECK_LT(queue_index, work_queues_.size());
58 for (const auto& queue_priority : queue_priorities_) { 59 for (const auto& queue_priority : queue_priorities_) {
59 if (queue_priority.find(queue_index) != queue_priority.end()) 60 if (queue_priority.find(queue_index) != queue_priority.end())
60 return true; 61 return true;
61 } 62 }
62 return false; 63 return false;
63 } 64 }
64 65
65 bool RendererTaskQueueSelector::IsOlder(const base::TaskQueue* queueA, 66 bool PrioritizingTaskQueueSelector::IsOlder(const base::TaskQueue* queueA,
66 const base::TaskQueue* queueB) { 67 const base::TaskQueue* queueB) {
67 // Note: the comparison is correct due to the fact that the PendingTask 68 // Note: the comparison is correct due to the fact that the PendingTask
68 // operator inverts its comparison operation in order to work well in a heap 69 // operator inverts its comparison operation in order to work well in a heap
69 // based priority queue. 70 // based priority queue.
70 return queueB->front() < queueA->front(); 71 return queueB->front() < queueA->front();
71 } 72 }
72 73
73 RendererTaskQueueSelector::QueuePriority 74 PrioritizingTaskQueueSelector::QueuePriority
74 RendererTaskQueueSelector::NextPriority(QueuePriority priority) { 75 PrioritizingTaskQueueSelector::NextPriority(QueuePriority priority) {
75 DCHECK(priority < QUEUE_PRIORITY_COUNT); 76 DCHECK(priority < QUEUE_PRIORITY_COUNT);
76 return static_cast<QueuePriority>(static_cast<int>(priority) + 1); 77 return static_cast<QueuePriority>(static_cast<int>(priority) + 1);
77 } 78 }
78 79
79 bool RendererTaskQueueSelector::ChooseOldestWithPriority( 80 bool PrioritizingTaskQueueSelector::ChooseOldestWithPriority(
80 QueuePriority priority, 81 QueuePriority priority,
81 size_t* out_queue_index) const { 82 size_t* out_queue_index) const {
82 bool found_non_empty_queue = false; 83 bool found_non_empty_queue = false;
83 size_t chosen_queue = 0; 84 size_t chosen_queue = 0;
84 for (int queue_index : queue_priorities_[priority]) { 85 for (int queue_index : queue_priorities_[priority]) {
85 if (work_queues_[queue_index]->empty()) { 86 if (work_queues_[queue_index]->empty()) {
86 continue; 87 continue;
87 } 88 }
88 if (!found_non_empty_queue || 89 if (!found_non_empty_queue ||
89 IsOlder(work_queues_[queue_index], work_queues_[chosen_queue])) { 90 IsOlder(work_queues_[queue_index], work_queues_[chosen_queue])) {
90 found_non_empty_queue = true; 91 found_non_empty_queue = true;
91 chosen_queue = queue_index; 92 chosen_queue = queue_index;
92 } 93 }
93 } 94 }
94 95
95 if (found_non_empty_queue) { 96 if (found_non_empty_queue) {
96 *out_queue_index = chosen_queue; 97 *out_queue_index = chosen_queue;
97 } 98 }
98 return found_non_empty_queue; 99 return found_non_empty_queue;
99 } 100 }
100 101
101 bool RendererTaskQueueSelector::SelectWorkQueueToService( 102 bool PrioritizingTaskQueueSelector::SelectWorkQueueToService(
102 size_t* out_queue_index) { 103 size_t* out_queue_index) {
103 DCHECK(main_thread_checker_.CalledOnValidThread()); 104 DCHECK(main_thread_checker_.CalledOnValidThread());
104 DCHECK(work_queues_.size()); 105 DCHECK(work_queues_.size());
105 // Always service the control queue if it has any work. 106 // Always service the control queue if it has any work.
106 if (ChooseOldestWithPriority(CONTROL_PRIORITY, out_queue_index)) { 107 if (ChooseOldestWithPriority(CONTROL_PRIORITY, out_queue_index)) {
107 DidSelectQueueWithPriority(CONTROL_PRIORITY); 108 DidSelectQueueWithPriority(CONTROL_PRIORITY);
108 return true; 109 return true;
109 } 110 }
110 // Select from the normal priority queue if we are starving it. 111 // Select from the normal priority queue if we are starving it.
111 if (starvation_count_ >= kMaxStarvationTasks && 112 if (starvation_count_ >= kMaxStarvationTasks &&
112 ChooseOldestWithPriority(NORMAL_PRIORITY, out_queue_index)) { 113 ChooseOldestWithPriority(NORMAL_PRIORITY, out_queue_index)) {
113 DidSelectQueueWithPriority(NORMAL_PRIORITY); 114 DidSelectQueueWithPriority(NORMAL_PRIORITY);
114 return true; 115 return true;
115 } 116 }
116 // Otherwise choose in priority order. 117 // Otherwise choose in priority order.
117 for (QueuePriority priority = HIGH_PRIORITY; priority < QUEUE_PRIORITY_COUNT; 118 for (QueuePriority priority = HIGH_PRIORITY; priority < QUEUE_PRIORITY_COUNT;
118 priority = NextPriority(priority)) { 119 priority = NextPriority(priority)) {
119 if (ChooseOldestWithPriority(priority, out_queue_index)) { 120 if (ChooseOldestWithPriority(priority, out_queue_index)) {
120 DidSelectQueueWithPriority(priority); 121 DidSelectQueueWithPriority(priority);
121 return true; 122 return true;
122 } 123 }
123 } 124 }
124 return false; 125 return false;
125 } 126 }
126 127
127 void RendererTaskQueueSelector::DidSelectQueueWithPriority( 128 void PrioritizingTaskQueueSelector::DidSelectQueueWithPriority(
128 QueuePriority priority) { 129 QueuePriority priority) {
129 switch (priority) { 130 switch (priority) {
130 case CONTROL_PRIORITY: 131 case CONTROL_PRIORITY:
131 break; 132 break;
132 case HIGH_PRIORITY: 133 case HIGH_PRIORITY:
133 starvation_count_++; 134 starvation_count_++;
134 break; 135 break;
135 case NORMAL_PRIORITY: 136 case NORMAL_PRIORITY:
136 case BEST_EFFORT_PRIORITY: 137 case BEST_EFFORT_PRIORITY:
137 starvation_count_ = 0; 138 starvation_count_ = 0;
138 break; 139 break;
139 default: 140 default:
140 NOTREACHED(); 141 NOTREACHED();
141 } 142 }
142 } 143 }
143 144
144 // static 145 // static
145 const char* RendererTaskQueueSelector::PriorityToString( 146 const char* PrioritizingTaskQueueSelector::PriorityToString(
146 QueuePriority priority) { 147 QueuePriority priority) {
147 switch (priority) { 148 switch (priority) {
148 case CONTROL_PRIORITY: 149 case CONTROL_PRIORITY:
149 return "control"; 150 return "control";
150 case HIGH_PRIORITY: 151 case HIGH_PRIORITY:
151 return "high"; 152 return "high";
152 case NORMAL_PRIORITY: 153 case NORMAL_PRIORITY:
153 return "normal"; 154 return "normal";
154 case BEST_EFFORT_PRIORITY: 155 case BEST_EFFORT_PRIORITY:
155 return "best_effort"; 156 return "best_effort";
156 default: 157 default:
157 NOTREACHED(); 158 NOTREACHED();
158 return nullptr; 159 return nullptr;
159 } 160 }
160 } 161 }
161 162
162 void RendererTaskQueueSelector::AsValueInto( 163 void PrioritizingTaskQueueSelector::AsValueInto(
163 base::trace_event::TracedValue* state) const { 164 base::trace_event::TracedValue* state) const {
164 DCHECK(main_thread_checker_.CalledOnValidThread()); 165 DCHECK(main_thread_checker_.CalledOnValidThread());
165 state->BeginDictionary("priorities"); 166 state->BeginDictionary("priorities");
166 for (QueuePriority priority = FIRST_QUEUE_PRIORITY; 167 for (QueuePriority priority = FIRST_QUEUE_PRIORITY;
167 priority < QUEUE_PRIORITY_COUNT; priority = NextPriority(priority)) { 168 priority < QUEUE_PRIORITY_COUNT; priority = NextPriority(priority)) {
168 state->BeginArray(PriorityToString(priority)); 169 state->BeginArray(PriorityToString(priority));
169 for (size_t queue_index : queue_priorities_[priority]) 170 for (size_t queue_index : queue_priorities_[priority])
170 state->AppendInteger(queue_index); 171 state->AppendInteger(queue_index);
171 state->EndArray(); 172 state->EndArray();
172 } 173 }
173 state->EndDictionary(); 174 state->EndDictionary();
174 state->SetInteger("starvation_count", starvation_count_); 175 state->SetInteger("starvation_count", starvation_count_);
175 } 176 }
176 177
177 } // namespace content 178 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698