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

Side by Side Diff: components/scheduler/renderer/throttling_helper.cc

Issue 2118903002: scheduler: Move the Blink scheduler into Blink (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Another GYP fix Created 4 years, 5 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/scheduler/renderer/throttling_helper.h"
6
7 #include "base/logging.h"
8 #include "components/scheduler/base/real_time_domain.h"
9 #include "components/scheduler/child/scheduler_tqm_delegate.h"
10 #include "components/scheduler/renderer/renderer_scheduler_impl.h"
11 #include "components/scheduler/renderer/throttled_time_domain.h"
12 #include "components/scheduler/renderer/web_frame_scheduler_impl.h"
13 #include "third_party/WebKit/public/platform/WebFrameScheduler.h"
14
15 namespace scheduler {
16
17 ThrottlingHelper::ThrottlingHelper(RendererSchedulerImpl* renderer_scheduler,
18 const char* tracing_category)
19 : task_runner_(renderer_scheduler->ControlTaskRunner()),
20 renderer_scheduler_(renderer_scheduler),
21 tick_clock_(renderer_scheduler->tick_clock()),
22 tracing_category_(tracing_category),
23 time_domain_(new ThrottledTimeDomain(this, tick_clock_)),
24 weak_factory_(this) {
25 suspend_timers_when_backgrounded_closure_.Reset(base::Bind(
26 &ThrottlingHelper::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
27 forward_immediate_work_closure_ =
28 base::Bind(&ThrottlingHelper::OnTimeDomainHasImmediateWork,
29 weak_factory_.GetWeakPtr());
30
31 renderer_scheduler_->RegisterTimeDomain(time_domain_.get());
32 }
33
34 ThrottlingHelper::~ThrottlingHelper() {
35 // It's possible for queues to be still throttled, so we need to tidy up
36 // before unregistering the time domain.
37 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
38 TaskQueue* task_queue = map_entry.first;
39 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
40 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO);
41 }
42
43 renderer_scheduler_->UnregisterTimeDomain(time_domain_.get());
44 }
45
46 void ThrottlingHelper::SetQueueEnabled(TaskQueue* task_queue, bool enabled) {
47 TaskQueueMap::iterator find_it = throttled_queues_.find(task_queue);
48
49 if (find_it == throttled_queues_.end()) {
50 task_queue->SetQueueEnabled(enabled);
51 return;
52 }
53
54 find_it->second.enabled = enabled;
55
56 // We don't enable the queue here because it's throttled and there might be
57 // tasks in it's work queue that would execute immediatly rather than after
58 // PumpThrottledTasks runs.
59 if (!enabled)
60 task_queue->SetQueueEnabled(false);
61 }
62
63 void ThrottlingHelper::IncreaseThrottleRefCount(TaskQueue* task_queue) {
64 DCHECK_NE(task_queue, task_runner_.get());
65
66 std::pair<TaskQueueMap::iterator, bool> insert_result =
67 throttled_queues_.insert(std::make_pair(
68 task_queue, Metadata(1, task_queue->IsQueueEnabled())));
69
70 if (insert_result.second) {
71 // The insert was succesful so we need to throttle the queue.
72 task_queue->SetTimeDomain(time_domain_.get());
73 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL);
74 task_queue->SetQueueEnabled(false);
75
76 if (!task_queue->IsEmpty()) {
77 if (task_queue->HasPendingImmediateWork()) {
78 OnTimeDomainHasImmediateWork();
79 } else {
80 OnTimeDomainHasDelayedWork();
81 }
82 }
83 } else {
84 // An entry already existed in the map so we need to increment the refcount.
85 insert_result.first->second.throttling_ref_count++;
86 }
87 }
88
89 void ThrottlingHelper::DecreaseThrottleRefCount(TaskQueue* task_queue) {
90 TaskQueueMap::iterator iter = throttled_queues_.find(task_queue);
91
92 if (iter != throttled_queues_.end() &&
93 --iter->second.throttling_ref_count == 0) {
94 bool enabled = iter->second.enabled;
95 // The refcount has become zero, we need to unthrottle the queue.
96 throttled_queues_.erase(iter);
97
98 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
99 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO);
100 task_queue->SetQueueEnabled(enabled);
101 }
102 }
103
104 void ThrottlingHelper::UnregisterTaskQueue(TaskQueue* task_queue) {
105 throttled_queues_.erase(task_queue);
106 }
107
108 void ThrottlingHelper::OnTimeDomainHasImmediateWork() {
109 // Forward to the main thread if called from another thread.
110 if (!task_runner_->RunsTasksOnCurrentThread()) {
111 task_runner_->PostTask(FROM_HERE, forward_immediate_work_closure_);
112 return;
113 }
114 TRACE_EVENT0(tracing_category_,
115 "ThrottlingHelper::OnTimeDomainHasImmediateWork");
116 base::TimeTicks now = tick_clock_->NowTicks();
117 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now, now);
118 }
119
120 void ThrottlingHelper::OnTimeDomainHasDelayedWork() {
121 TRACE_EVENT0(tracing_category_,
122 "ThrottlingHelper::OnTimeDomainHasDelayedWork");
123 base::TimeTicks next_scheduled_delayed_task;
124 bool has_delayed_task =
125 time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task);
126 DCHECK(has_delayed_task);
127 base::TimeTicks now = tick_clock_->NowTicks();
128 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now,
129 next_scheduled_delayed_task);
130 }
131
132 void ThrottlingHelper::PumpThrottledTasks() {
133 TRACE_EVENT0(tracing_category_, "ThrottlingHelper::PumpThrottledTasks");
134 pending_pump_throttled_tasks_runtime_ = base::TimeTicks();
135
136 base::TimeTicks now = tick_clock_->NowTicks();
137 time_domain_->AdvanceTo(now);
138 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
139 TaskQueue* task_queue = map_entry.first;
140 if (task_queue->IsEmpty())
141 continue;
142
143 task_queue->SetQueueEnabled(map_entry.second.enabled);
144 task_queue->PumpQueue(false);
145 }
146 // Make sure NextScheduledRunTime gives us an up-to date result.
147 time_domain_->ClearExpiredWakeups();
148
149 base::TimeTicks next_scheduled_delayed_task;
150 // Maybe schedule a call to ThrottlingHelper::PumpThrottledTasks if there is
151 // a pending delayed task. NOTE posting a non-delayed task in the future will
152 // result in ThrottlingHelper::OnTimeDomainHasImmediateWork being called.
153 if (time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task)) {
154 MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now,
155 next_scheduled_delayed_task);
156 }
157 }
158
159 /* static */
160 base::TimeTicks ThrottlingHelper::ThrottledRunTime(
161 base::TimeTicks unthrottled_runtime) {
162 const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1);
163 return unthrottled_runtime + one_second -
164 ((unthrottled_runtime - base::TimeTicks()) % one_second);
165 }
166
167 void ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked(
168 const tracked_objects::Location& from_here,
169 base::TimeTicks now,
170 base::TimeTicks unthrottled_runtime) {
171 base::TimeTicks throttled_runtime =
172 ThrottledRunTime(std::max(now, unthrottled_runtime));
173 // If there is a pending call to PumpThrottledTasks and it's sooner than
174 // |unthrottled_runtime| then return.
175 if (!pending_pump_throttled_tasks_runtime_.is_null() &&
176 throttled_runtime >= pending_pump_throttled_tasks_runtime_) {
177 return;
178 }
179
180 pending_pump_throttled_tasks_runtime_ = throttled_runtime;
181
182 suspend_timers_when_backgrounded_closure_.Cancel();
183
184 base::TimeDelta delay = pending_pump_throttled_tasks_runtime_ - now;
185 TRACE_EVENT1(tracing_category_,
186 "ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked",
187 "delay_till_next_pump_ms", delay.InMilliseconds());
188 task_runner_->PostDelayedTask(
189 from_here, suspend_timers_when_backgrounded_closure_.callback(), delay);
190 }
191
192 } // namespace scheduler
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698