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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/renderer/throttling_helper.cc

Issue 2276353002: Remove after wakeup logic and replace PumpTask with Fences (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make TestLongIdlePeriodTimeline test quiescence again! Created 4 years, 3 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "platform/scheduler/renderer/throttling_helper.h" 5 #include "platform/scheduler/renderer/throttling_helper.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "platform/scheduler/base/real_time_domain.h" 8 #include "platform/scheduler/base/real_time_domain.h"
9 #include "platform/scheduler/child/scheduler_tqm_delegate.h" 9 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
10 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" 10 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
11 #include "platform/scheduler/renderer/renderer_scheduler_impl.h" 11 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
12 #include "platform/scheduler/renderer/throttled_time_domain.h" 12 #include "platform/scheduler/renderer/throttled_time_domain.h"
13 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h" 13 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
14 #include "public/platform/WebFrameScheduler.h" 14 #include "public/platform/WebFrameScheduler.h"
15 15
16 namespace blink { 16 namespace blink {
17 namespace scheduler { 17 namespace scheduler {
18 18
19 ThrottlingHelper::ThrottlingHelper(RendererSchedulerImpl* renderer_scheduler, 19 ThrottlingHelper::ThrottlingHelper(RendererSchedulerImpl* renderer_scheduler,
20 const char* tracing_category) 20 const char* tracing_category)
21 : task_runner_(renderer_scheduler->ControlTaskRunner()), 21 : task_runner_(renderer_scheduler->ControlTaskRunner()),
22 renderer_scheduler_(renderer_scheduler), 22 renderer_scheduler_(renderer_scheduler),
23 tick_clock_(renderer_scheduler->tick_clock()), 23 tick_clock_(renderer_scheduler->tick_clock()),
24 tracing_category_(tracing_category), 24 tracing_category_(tracing_category),
25 time_domain_(new ThrottledTimeDomain(this, tracing_category)), 25 time_domain_(new ThrottledTimeDomain(this, tracing_category)),
26 virtual_time_(false), 26 virtual_time_(false),
27 ignore_incoming_immediate_work_(false),
27 weak_factory_(this) { 28 weak_factory_(this) {
28 pump_throttled_tasks_closure_.Reset(base::Bind( 29 pump_throttled_tasks_closure_.Reset(base::Bind(
29 &ThrottlingHelper::PumpThrottledTasks, weak_factory_.GetWeakPtr())); 30 &ThrottlingHelper::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
30 forward_immediate_work_closure_ = 31 forward_immediate_work_closure_ =
31 base::Bind(&ThrottlingHelper::OnTimeDomainHasImmediateWork, 32 base::Bind(&ThrottlingHelper::OnTimeDomainHasImmediateWork,
32 weak_factory_.GetWeakPtr()); 33 weak_factory_.GetWeakPtr());
33 34
34 renderer_scheduler_->RegisterTimeDomain(time_domain_.get()); 35 renderer_scheduler_->RegisterTimeDomain(time_domain_.get());
35 } 36 }
36 37
37 ThrottlingHelper::~ThrottlingHelper() { 38 ThrottlingHelper::~ThrottlingHelper() {
38 // It's possible for queues to be still throttled, so we need to tidy up 39 // It's possible for queues to be still throttled, so we need to tidy up
39 // before unregistering the time domain. 40 // before unregistering the time domain.
40 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) { 41 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
41 TaskQueue* task_queue = map_entry.first; 42 TaskQueue* task_queue = map_entry.first;
42 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 43 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
43 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO);
44 } 44 }
45 45
46 renderer_scheduler_->UnregisterTimeDomain(time_domain_.get()); 46 renderer_scheduler_->UnregisterTimeDomain(time_domain_.get());
47 } 47 }
48 48
49 void ThrottlingHelper::SetQueueEnabled(TaskQueue* task_queue, bool enabled) { 49 void ThrottlingHelper::SetQueueEnabled(TaskQueue* task_queue, bool enabled) {
50 TaskQueueMap::iterator find_it = throttled_queues_.find(task_queue); 50 TaskQueueMap::iterator find_it = throttled_queues_.find(task_queue);
51 51
52 if (find_it == throttled_queues_.end()) { 52 if (find_it == throttled_queues_.end()) {
53 task_queue->SetQueueEnabled(enabled); 53 task_queue->SetQueueEnabled(enabled);
(...skipping 15 matching lines...) Expand all
69 if (virtual_time_) 69 if (virtual_time_)
70 return; 70 return;
71 71
72 std::pair<TaskQueueMap::iterator, bool> insert_result = 72 std::pair<TaskQueueMap::iterator, bool> insert_result =
73 throttled_queues_.insert(std::make_pair( 73 throttled_queues_.insert(std::make_pair(
74 task_queue, Metadata(1, task_queue->IsQueueEnabled()))); 74 task_queue, Metadata(1, task_queue->IsQueueEnabled())));
75 75
76 if (insert_result.second) { 76 if (insert_result.second) {
77 // The insert was succesful so we need to throttle the queue. 77 // The insert was succesful so we need to throttle the queue.
78 task_queue->SetTimeDomain(time_domain_.get()); 78 task_queue->SetTimeDomain(time_domain_.get());
79 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL);
80 task_queue->SetQueueEnabled(false); 79 task_queue->SetQueueEnabled(false);
81 80
82 if (!task_queue->IsEmpty()) { 81 if (!task_queue->IsEmpty()) {
83 if (task_queue->HasPendingImmediateWork()) { 82 if (task_queue->HasPendingImmediateWork()) {
84 OnTimeDomainHasImmediateWork(); 83 OnTimeDomainHasImmediateWork();
85 } else { 84 } else {
86 OnTimeDomainHasDelayedWork(); 85 OnTimeDomainHasDelayedWork();
87 } 86 }
88 } 87 }
89 } else { 88 } else {
90 // An entry already existed in the map so we need to increment the refcount. 89 // An entry already existed in the map so we need to increment the refcount.
91 insert_result.first->second.throttling_ref_count++; 90 insert_result.first->second.throttling_ref_count++;
92 } 91 }
93 } 92 }
94 93
95 void ThrottlingHelper::DecreaseThrottleRefCount(TaskQueue* task_queue) { 94 void ThrottlingHelper::DecreaseThrottleRefCount(TaskQueue* task_queue) {
96 if (virtual_time_) 95 if (virtual_time_)
97 return; 96 return;
98 97
99 TaskQueueMap::iterator iter = throttled_queues_.find(task_queue); 98 TaskQueueMap::iterator iter = throttled_queues_.find(task_queue);
100 99
101 if (iter != throttled_queues_.end() && 100 if (iter != throttled_queues_.end() &&
102 --iter->second.throttling_ref_count == 0) { 101 --iter->second.throttling_ref_count == 0) {
103 bool enabled = iter->second.enabled; 102 bool enabled = iter->second.enabled;
104 // The refcount has become zero, we need to unthrottle the queue. 103 // The refcount has become zero, we need to unthrottle the queue.
105 throttled_queues_.erase(iter); 104 throttled_queues_.erase(iter);
106 105
107 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 106 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
108 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO);
109 task_queue->SetQueueEnabled(enabled); 107 task_queue->SetQueueEnabled(enabled);
110 } 108 }
111 } 109 }
112 110
111 bool ThrottlingHelper::IsThrottled(TaskQueue* task_queue) const {
112 return throttled_queues_.find(task_queue) != throttled_queues_.end();
113 }
114
113 void ThrottlingHelper::UnregisterTaskQueue(TaskQueue* task_queue) { 115 void ThrottlingHelper::UnregisterTaskQueue(TaskQueue* task_queue) {
114 throttled_queues_.erase(task_queue); 116 throttled_queues_.erase(task_queue);
115 } 117 }
116 118
117 void ThrottlingHelper::OnTimeDomainHasImmediateWork() { 119 void ThrottlingHelper::OnTimeDomainHasImmediateWork() {
118 // Forward to the main thread if called from another thread. 120 // Forward to the main thread if called from another thread.
119 if (!task_runner_->RunsTasksOnCurrentThread()) { 121 if (!task_runner_->RunsTasksOnCurrentThread()) {
120 task_runner_->PostTask(FROM_HERE, forward_immediate_work_closure_); 122 task_runner_->PostTask(FROM_HERE, forward_immediate_work_closure_);
121 return; 123 return;
122 } 124 }
125 // Posting ThrottlingHelper::MaybeDisableQueue doesn't count!
Sami 2016/08/25 15:54:13 Isn't OnTimeDomainHasImmediateWork is only called
alex clarke (OOO till 29th) 2016/08/26 13:29:09 This has gone away.
126 if (ignore_incoming_immediate_work_)
127 return;
123 TRACE_EVENT0(tracing_category_, 128 TRACE_EVENT0(tracing_category_,
124 "ThrottlingHelper::OnTimeDomainHasImmediateWork"); 129 "ThrottlingHelper::OnTimeDomainHasImmediateWork");
125 base::TimeTicks now = tick_clock_->NowTicks(); 130 base::TimeTicks now = tick_clock_->NowTicks();
126 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now, now); 131 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now, now);
127 } 132 }
128 133
129 void ThrottlingHelper::OnTimeDomainHasDelayedWork() { 134 void ThrottlingHelper::OnTimeDomainHasDelayedWork() {
130 TRACE_EVENT0(tracing_category_, 135 TRACE_EVENT0(tracing_category_,
131 "ThrottlingHelper::OnTimeDomainHasDelayedWork"); 136 "ThrottlingHelper::OnTimeDomainHasDelayedWork");
132 base::TimeTicks next_scheduled_delayed_task; 137 base::TimeTicks next_scheduled_delayed_task;
133 bool has_delayed_task = 138 bool has_delayed_task =
134 time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task); 139 time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task);
135 DCHECK(has_delayed_task); 140 DCHECK(has_delayed_task);
136 base::TimeTicks now = tick_clock_->NowTicks(); 141 base::TimeTicks now = tick_clock_->NowTicks();
137 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now, 142 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now,
138 next_scheduled_delayed_task); 143 next_scheduled_delayed_task);
139 } 144 }
140 145
141 void ThrottlingHelper::PumpThrottledTasks() { 146 void ThrottlingHelper::PumpThrottledTasks() {
142 TRACE_EVENT0(tracing_category_, "ThrottlingHelper::PumpThrottledTasks"); 147 TRACE_EVENT0(tracing_category_, "ThrottlingHelper::PumpThrottledTasks");
143 pending_pump_throttled_tasks_runtime_ = base::TimeTicks(); 148 pending_pump_throttled_tasks_runtime_ = base::TimeTicks();
144 149
145 LazyNow lazy_low(tick_clock_); 150 LazyNow lazy_low(tick_clock_);
151 // Make sure posting MaybeDisableQueue doesn't trigger another pump.
152 ignore_incoming_immediate_work_ = true;
Sami 2016/08/25 15:54:13 nit: base::AutoReset?
alex clarke (OOO till 29th) 2016/08/26 13:29:08 This has gone away.
146 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) { 153 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
147 TaskQueue* task_queue = map_entry.first; 154 TaskQueue* task_queue = map_entry.first;
148 if (task_queue->IsEmpty()) 155 if (task_queue->IsEmpty() || !map_entry.second.enabled) {
Sami 2016/08/25 15:54:13 nit: might want to short-circuit .enabled first si
alex clarke (OOO till 29th) 2016/08/26 13:29:09 Done.
149 continue; 156 continue;
157 }
150 158
151 task_queue->SetQueueEnabled(map_entry.second.enabled); 159 // Post a task to disable |task_queue|, which ensures that no tasks posted
152 task_queue->PumpQueue(&lazy_low, false); 160 // after this point will be run until next time.
161 task_queue->PostTask(FROM_HERE,
Sami 2016/08/25 15:54:13 Could IsEmpty() above get fooled by this task that
alex clarke (OOO till 29th) 2016/08/26 13:29:09 This has gone away.
162 base::Bind(&ThrottlingHelper::MaybeDisableQueue,
163 weak_factory_.GetWeakPtr(), task_queue));
164 task_queue->SetQueueEnabled(true);
153 } 165 }
166 ignore_incoming_immediate_work_ = false;
167
154 // Make sure NextScheduledRunTime gives us an up-to date result. 168 // Make sure NextScheduledRunTime gives us an up-to date result.
155 time_domain_->ClearExpiredWakeups(); 169 time_domain_->ClearExpiredWakeups();
156 170
157 base::TimeTicks next_scheduled_delayed_task; 171 base::TimeTicks next_scheduled_delayed_task;
158 // Maybe schedule a call to ThrottlingHelper::PumpThrottledTasks if there is 172 // Maybe schedule a call to ThrottlingHelper::PumpThrottledTasks if there is
159 // a pending delayed task. NOTE posting a non-delayed task in the future will 173 // a pending delayed task. NOTE posting a non-delayed task in the future will
160 // result in ThrottlingHelper::OnTimeDomainHasImmediateWork being called. 174 // result in ThrottlingHelper::OnTimeDomainHasImmediateWork being called.
161 if (time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task)) { 175 if (time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task)) {
162 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, lazy_low.Now(), 176 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, lazy_low.Now(),
163 next_scheduled_delayed_task); 177 next_scheduled_delayed_task);
164 } 178 }
165 } 179 }
166 180
181 void ThrottlingHelper::MaybeDisableQueue(TaskQueue* task_queue) {
182 // It's quite possible the queue is no longer throttled in which case we
183 // should bail out.
184 if (throttled_queues_.find(task_queue) == throttled_queues_.end())
Sami 2016/08/25 15:54:13 nit: Could call IsThrottled()
alex clarke (OOO till 29th) 2016/08/26 13:29:09 This has gone away.
185 return;
186
187 task_queue->SetQueueEnabled(false);
188
189 // Normally ThrottlingHelper::OnTimeDomainHasImmediateWork would detect
190 // extra work, but that call only happens if the queue was empty. So
191 // We need an extra check here to determine if there's more work to do.
192 if (task_queue->HasPendingImmediateWork()) {
193 base::TimeTicks now = tick_clock_->NowTicks();
194 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now, now);
195 }
196 }
197
167 /* static */ 198 /* static */
168 base::TimeTicks ThrottlingHelper::ThrottledRunTime( 199 base::TimeTicks ThrottlingHelper::ThrottledRunTime(
169 base::TimeTicks unthrottled_runtime) { 200 base::TimeTicks unthrottled_runtime) {
170 const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); 201 const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1);
171 return unthrottled_runtime + one_second - 202 return unthrottled_runtime + one_second -
172 ((unthrottled_runtime - base::TimeTicks()) % one_second); 203 ((unthrottled_runtime - base::TimeTicks()) % one_second);
173 } 204 }
174 205
175 void ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked( 206 void ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked(
176 const tracked_objects::Location& from_here, 207 const tracked_objects::Location& from_here,
(...skipping 28 matching lines...) Expand all
205 236
206 pump_throttled_tasks_closure_.Cancel(); 237 pump_throttled_tasks_closure_.Cancel();
207 238
208 while (!throttled_queues_.empty()) { 239 while (!throttled_queues_.empty()) {
209 TaskQueue* task_queue = throttled_queues_.begin()->first; 240 TaskQueue* task_queue = throttled_queues_.begin()->first;
210 bool enabled = throttled_queues_.begin()->second.enabled; 241 bool enabled = throttled_queues_.begin()->second.enabled;
211 242
212 throttled_queues_.erase(throttled_queues_.begin()); 243 throttled_queues_.erase(throttled_queues_.begin());
213 244
214 task_queue->SetTimeDomain(renderer_scheduler_->GetVirtualTimeDomain()); 245 task_queue->SetTimeDomain(renderer_scheduler_->GetVirtualTimeDomain());
215 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO);
216 task_queue->SetQueueEnabled(enabled); 246 task_queue->SetQueueEnabled(enabled);
217 } 247 }
218 } 248 }
219 249
220 } // namespace scheduler 250 } // namespace scheduler
221 } // namespace blink 251 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698