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

Side by Side Diff: content/renderer/scheduler/task_queue_manager.cc

Issue 972473004: EXPERIMENTAL, Trying Ross's suggestion (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
« no previous file with comments | « content/content_tests.gypi ('k') | content/renderer/scheduler/task_queue_manager_perftest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/task_queue_manager.h" 5 #include "content/renderer/scheduler/task_queue_manager.h"
6 6
7 #include <queue> 7 #include <queue>
8 #include <set>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
11 #include "base/trace_event/trace_event_argument.h" 12 #include "base/trace_event/trace_event_argument.h"
12 #include "cc/test/test_now_source.h" 13 #include "cc/test/test_now_source.h"
13 #include "content/renderer/scheduler/task_queue_selector.h" 14 #include "content/renderer/scheduler/task_queue_selector.h"
14 15
15 namespace { 16 namespace {
16 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max(); 17 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max();
17 } 18 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 NON_NESTABLE, 61 NON_NESTABLE,
61 }; 62 };
62 63
63 ~TaskQueue() override; 64 ~TaskQueue() override;
64 65
65 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, 66 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here,
66 const base::Closure& task, 67 const base::Closure& task,
67 base::TimeDelta delay, 68 base::TimeDelta delay,
68 TaskType task_type); 69 TaskType task_type);
69 70
70 // Adds a task at the end of the incoming task queue and schedules a call to 71 // Adds delayed_task_queue_.top() at the end of the incoming task queue and
71 // TaskQueueManager::DoWork() if the incoming queue was empty and automatic 72 // schedules a call to TaskQueueManager::DoWork() if the incoming queue was
72 // pumping is enabled. Can be called on an arbitrary thread. 73 // empty and automatic pumping is enabled. Can be called on an arbitrary
73 void EnqueueTask(const base::PendingTask& pending_task); 74 // thread.
75 void EnqueueNextPendingTask();
74 76
75 void PumpQueueLocked(); 77 void PumpQueueLocked();
76 bool ShouldAutoPumpQueueLocked( 78 bool ShouldAutoPumpQueueLocked(
77 TaskQueueManager::WorkQueueUpdateEventType event_type); 79 TaskQueueManager::WorkQueueUpdateEventType event_type);
78 void EnqueueTaskLocked(const base::PendingTask& pending_task); 80 void EnqueueTaskLocked(const base::PendingTask& pending_task);
79 81
80 void TraceQueueSize(bool is_locked) const; 82 void TraceQueueSize(bool is_locked) const;
81 static const char* PumpPolicyToString( 83 static const char* PumpPolicyToString(
82 TaskQueueManager::PumpPolicy pump_policy); 84 TaskQueueManager::PumpPolicy pump_policy);
83 static void QueueAsValueInto(const base::TaskQueue& queue, 85 static void QueueAsValueInto(const base::TaskQueue& queue,
84 base::trace_event::TracedValue* state); 86 base::trace_event::TracedValue* state);
85 static void TaskAsValueInto(const base::PendingTask& task, 87 static void TaskAsValueInto(const base::PendingTask& task,
86 base::trace_event::TracedValue* state); 88 base::trace_event::TracedValue* state);
87 89
88 // This lock protects all members except the work queue. 90 // This lock protects all members except the work queue.
89 mutable base::Lock lock_; 91 mutable base::Lock lock_;
90 TaskQueueManager* task_queue_manager_; 92 TaskQueueManager* task_queue_manager_;
91 base::TaskQueue incoming_queue_; 93 base::TaskQueue incoming_queue_;
92 TaskQueueManager::PumpPolicy pump_policy_; 94 TaskQueueManager::PumpPolicy pump_policy_;
93 const char* name_; 95 const char* name_;
94 std::priority_queue<base::TimeTicks, 96 base::DelayedTaskQueue delayed_task_queue_;
95 std::vector<base::TimeTicks>,
96 std::greater<base::TimeTicks>> delayed_task_run_times_;
97 97
98 base::TaskQueue work_queue_; 98 base::TaskQueue work_queue_;
99 99
100 DISALLOW_COPY_AND_ASSIGN(TaskQueue); 100 DISALLOW_COPY_AND_ASSIGN(TaskQueue);
101 }; 101 };
102 102
103 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) 103 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager)
104 : task_queue_manager_(task_queue_manager), 104 : task_queue_manager_(task_queue_manager),
105 pump_policy_(TaskQueueManager::PumpPolicy::AUTO), 105 pump_policy_(TaskQueueManager::PumpPolicy::AUTO),
106 name_(nullptr) { 106 name_(nullptr) {
107 } 107 }
108 108
109 TaskQueue::~TaskQueue() { 109 TaskQueue::~TaskQueue() {
110 } 110 }
111 111
112 void TaskQueue::WillDeleteTaskQueueManager() { 112 void TaskQueue::WillDeleteTaskQueueManager() {
113 base::AutoLock lock(lock_); 113 base::AutoLock lock(lock_);
114 task_queue_manager_ = nullptr; 114 task_queue_manager_ = nullptr;
115
116 // Clear all delayed tasks because we need them to be deleted before the blink
117 // heap goes away.
118 while (!delayed_task_queue_.empty())
119 delayed_task_queue_.pop();
115 } 120 }
116 121
117 bool TaskQueue::RunsTasksOnCurrentThread() const { 122 bool TaskQueue::RunsTasksOnCurrentThread() const {
118 base::AutoLock lock(lock_); 123 base::AutoLock lock(lock_);
119 if (!task_queue_manager_) 124 if (!task_queue_manager_)
120 return false; 125 return false;
121 return task_queue_manager_->RunsTasksOnCurrentThread(); 126 return task_queue_manager_->RunsTasksOnCurrentThread();
122 } 127 }
123 128
124 bool TaskQueue::PostDelayedTaskImpl(const tracked_objects::Location& from_here, 129 bool TaskQueue::PostDelayedTaskImpl(const tracked_objects::Location& from_here,
125 const base::Closure& task, 130 const base::Closure& task,
126 base::TimeDelta delay, 131 base::TimeDelta delay,
127 TaskType task_type) { 132 TaskType task_type) {
128 base::AutoLock lock(lock_); 133 base::AutoLock lock(lock_);
129 if (!task_queue_manager_) 134 if (!task_queue_manager_)
130 return false; 135 return false;
131 136
132 base::PendingTask pending_task(from_here, task, base::TimeTicks(), 137 base::PendingTask pending_task(from_here, task, base::TimeTicks(),
133 task_type != TaskType::NON_NESTABLE); 138 task_type != TaskType::NON_NESTABLE);
134 task_queue_manager_->DidQueueTask(&pending_task); 139 task_queue_manager_->DidQueueTask(&pending_task);
135 140
136 if (delay > base::TimeDelta()) { 141 if (delay > base::TimeDelta()) {
137 pending_task.delayed_run_time = task_queue_manager_->Now() + delay; 142 pending_task.delayed_run_time = task_queue_manager_->Now() + delay;
138 delayed_task_run_times_.push(pending_task.delayed_run_time); 143 delayed_task_queue_.push(pending_task);
139 return task_queue_manager_->PostDelayedTask( 144 return task_queue_manager_->PostDelayedTask(
140 FROM_HERE, Bind(&TaskQueue::EnqueueTask, this, pending_task), delay); 145 FROM_HERE, Bind(&TaskQueue::EnqueueNextPendingTask, this), delay);
141 } 146 }
142 EnqueueTaskLocked(pending_task); 147 EnqueueTaskLocked(pending_task);
143 return true; 148 return true;
144 } 149 }
145 150
146 bool TaskQueue::IsQueueEmpty() const { 151 bool TaskQueue::IsQueueEmpty() const {
147 if (!work_queue_.empty()) 152 if (!work_queue_.empty())
148 return false; 153 return false;
149 154
150 { 155 {
(...skipping 16 matching lines...) Expand all
167 } 172 }
168 173
169 bool TaskQueue::UpdateWorkQueue( 174 bool TaskQueue::UpdateWorkQueue(
170 base::TimeTicks* next_pending_delayed_task, 175 base::TimeTicks* next_pending_delayed_task,
171 TaskQueueManager::WorkQueueUpdateEventType event_type) { 176 TaskQueueManager::WorkQueueUpdateEventType event_type) {
172 if (!work_queue_.empty()) 177 if (!work_queue_.empty())
173 return true; 178 return true;
174 179
175 { 180 {
176 base::AutoLock lock(lock_); 181 base::AutoLock lock(lock_);
177 if (!delayed_task_run_times_.empty()) { 182 if (!delayed_task_queue_.empty()) {
178 *next_pending_delayed_task = 183 *next_pending_delayed_task =
179 std::min(*next_pending_delayed_task, delayed_task_run_times_.top()); 184 std::min(*next_pending_delayed_task,
185 delayed_task_queue_.top().delayed_run_time);
180 } 186 }
181 if (!ShouldAutoPumpQueueLocked(event_type)) 187 if (!ShouldAutoPumpQueueLocked(event_type))
182 return false; 188 return false;
183 work_queue_.Swap(&incoming_queue_); 189 work_queue_.Swap(&incoming_queue_);
184 TraceQueueSize(true); 190 TraceQueueSize(true);
185 return true; 191 return true;
186 } 192 }
187 } 193 }
188 194
189 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() { 195 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() {
(...skipping 12 matching lines...) Expand all
202 if (!is_locked) 208 if (!is_locked)
203 lock_.Acquire(); 209 lock_.Acquire();
204 else 210 else
205 lock_.AssertAcquired(); 211 lock_.AssertAcquired();
206 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), name_, 212 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), name_,
207 incoming_queue_.size() + work_queue_.size()); 213 incoming_queue_.size() + work_queue_.size());
208 if (!is_locked) 214 if (!is_locked)
209 lock_.Release(); 215 lock_.Release();
210 } 216 }
211 217
212 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) { 218 void TaskQueue::EnqueueNextPendingTask() {
213 base::AutoLock lock(lock_); 219 base::AutoLock lock(lock_);
214 EnqueueTaskLocked(pending_task); 220 if (!task_queue_manager_)
221 return;
222
223 if (delayed_task_queue_.empty())
224 return;
225
226 EnqueueTaskLocked(delayed_task_queue_.top());
227 delayed_task_queue_.pop();
215 } 228 }
216 229
217 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { 230 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) {
218 lock_.AssertAcquired(); 231 lock_.AssertAcquired();
219 if (!task_queue_manager_) 232 if (!task_queue_manager_)
220 return; 233 return;
221 if (pump_policy_ == TaskQueueManager::PumpPolicy::AUTO && 234 if (pump_policy_ == TaskQueueManager::PumpPolicy::AUTO &&
222 incoming_queue_.empty()) 235 incoming_queue_.empty())
223 task_queue_manager_->MaybePostDoWorkOnMainRunner(); 236 task_queue_manager_->MaybePostDoWorkOnMainRunner();
224 incoming_queue_.push(pending_task); 237 incoming_queue_.push(pending_task);
225 238
226 if (!pending_task.delayed_run_time.is_null()) { 239 if (!pending_task.delayed_run_time.is_null()) {
227 // Update the time of the next pending delayed task.
228 while (!delayed_task_run_times_.empty() &&
229 delayed_task_run_times_.top() <= pending_task.delayed_run_time) {
230 delayed_task_run_times_.pop();
231 }
232 // Clear the delayed run time because we've already applied the delay 240 // Clear the delayed run time because we've already applied the delay
233 // before getting here. 241 // before getting here.
234 incoming_queue_.back().delayed_run_time = base::TimeTicks(); 242 incoming_queue_.back().delayed_run_time = base::TimeTicks();
235 } 243 }
236 TraceQueueSize(true); 244 TraceQueueSize(true);
237 } 245 }
238 246
239 void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) { 247 void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) {
240 base::AutoLock lock(lock_); 248 base::AutoLock lock(lock_);
241 if (pump_policy == TaskQueueManager::PumpPolicy::AUTO && 249 if (pump_policy == TaskQueueManager::PumpPolicy::AUTO &&
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 state->EndArray(); 562 state->EndArray();
555 state->BeginDictionary("selector"); 563 state->BeginDictionary("selector");
556 selector_->AsValueInto(state.get()); 564 selector_->AsValueInto(state.get());
557 state->EndDictionary(); 565 state->EndDictionary();
558 if (should_run) 566 if (should_run)
559 state->SetInteger("selected_queue", selected_queue); 567 state->SetInteger("selected_queue", selected_queue);
560 return state; 568 return state;
561 } 569 }
562 570
563 } // namespace content 571 } // namespace content
OLDNEW
« no previous file with comments | « content/content_tests.gypi ('k') | content/renderer/scheduler/task_queue_manager_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698