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

Side by Side Diff: components/scheduler/renderer/renderer_scheduler_impl.h

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 2014 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 #ifndef COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_
6 #define COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_
7
8 #include "base/atomicops.h"
9 #include "base/macros.h"
10 #include "base/synchronization/lock.h"
11 #include "components/scheduler/base/pollable_thread_safe_flag.h"
12 #include "components/scheduler/base/queueing_time_estimator.h"
13 #include "components/scheduler/base/task_time_tracker.h"
14 #include "components/scheduler/child/idle_helper.h"
15 #include "components/scheduler/child/scheduler_helper.h"
16 #include "components/scheduler/renderer/deadline_task_runner.h"
17 #include "components/scheduler/renderer/idle_time_estimator.h"
18 #include "components/scheduler/renderer/render_widget_signals.h"
19 #include "components/scheduler/renderer/renderer_scheduler.h"
20 #include "components/scheduler/renderer/task_cost_estimator.h"
21 #include "components/scheduler/renderer/throttling_helper.h"
22 #include "components/scheduler/renderer/user_model.h"
23 #include "components/scheduler/renderer/web_view_scheduler_impl.h"
24 #include "components/scheduler/scheduler_export.h"
25
26 namespace base {
27 namespace trace_event {
28 class ConvertableToTraceFormat;
29 }
30 }
31
32 namespace scheduler {
33 class RenderWidgetSchedulingState;
34 class WebViewSchedulerImpl;
35 class ThrottlingHelper;
36
37 class SCHEDULER_EXPORT RendererSchedulerImpl
38 : public RendererScheduler,
39 public IdleHelper::Delegate,
40 public SchedulerHelper::Observer,
41 public RenderWidgetSignals::Observer,
42 public TaskTimeTracker,
43 public QueueingTimeEstimator::Client {
44 public:
45 // Keep RendererScheduler::UseCaseToString in sync with this enum.
46 enum class UseCase {
47 // No active use case detected.
48 NONE,
49 // A continuous gesture (e.g., scroll, pinch) which is being driven by the
50 // compositor thread.
51 COMPOSITOR_GESTURE,
52 // An unspecified touch gesture which is being handled by the main thread.
53 // Note that since we don't have a full view of the use case, we should be
54 // careful to prioritize all work equally.
55 MAIN_THREAD_CUSTOM_INPUT_HANDLING,
56 // A continuous gesture (e.g., scroll, pinch) which is being driven by the
57 // compositor thread but also observed by the main thread. An example is
58 // synchronized scrolling where a scroll listener on the main thread changes
59 // page layout based on the current scroll position.
60 SYNCHRONIZED_GESTURE,
61 // A gesture has recently started and we are about to run main thread touch
62 // listeners to find out the actual gesture type. To minimize touch latency,
63 // only input handling work should run in this state.
64 TOUCHSTART,
65 // The page is loading.
66 LOADING,
67 // A continuous gesture (e.g., scroll) which is being handled by the main
68 // thread.
69 MAIN_THREAD_GESTURE,
70 // Must be the last entry.
71 USE_CASE_COUNT,
72 FIRST_USE_CASE = NONE,
73 };
74 static const char* UseCaseToString(UseCase use_case);
75 static const char* RAILModeToString(v8::RAILMode rail_mode);
76
77 RendererSchedulerImpl(scoped_refptr<SchedulerTqmDelegate> main_task_runner);
78 ~RendererSchedulerImpl() override;
79
80 // RendererScheduler implementation:
81 std::unique_ptr<blink::WebThread> CreateMainThread() override;
82 scoped_refptr<TaskQueue> DefaultTaskRunner() override;
83 scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner() override;
84 scoped_refptr<TaskQueue> CompositorTaskRunner() override;
85 scoped_refptr<TaskQueue> LoadingTaskRunner() override;
86 scoped_refptr<TaskQueue> TimerTaskRunner() override;
87 scoped_refptr<TaskQueue> NewLoadingTaskRunner(const char* name) override;
88 scoped_refptr<TaskQueue> NewTimerTaskRunner(const char* name) override;
89 scoped_refptr<TaskQueue> NewUnthrottledTaskRunner(const char* name) override;
90 std::unique_ptr<RenderWidgetSchedulingState> NewRenderWidgetSchedulingState()
91 override;
92 void WillBeginFrame(const cc::BeginFrameArgs& args) override;
93 void BeginFrameNotExpectedSoon() override;
94 void DidCommitFrameToCompositor() override;
95 void DidHandleInputEventOnCompositorThread(
96 const blink::WebInputEvent& web_input_event,
97 InputEventState event_state) override;
98 void DidHandleInputEventOnMainThread(
99 const blink::WebInputEvent& web_input_event) override;
100 void DidAnimateForInputOnCompositorThread() override;
101 void OnRendererBackgrounded() override;
102 void OnRendererForegrounded() override;
103 void SuspendRenderer() override;
104 void AddPendingNavigation(
105 blink::WebScheduler::NavigatingFrameType type) override;
106 void RemovePendingNavigation(
107 blink::WebScheduler::NavigatingFrameType type) override;
108 void OnNavigationStarted() override;
109 bool IsHighPriorityWorkAnticipated() override;
110 bool ShouldYieldForHighPriorityWork() override;
111 bool CanExceedIdleDeadlineIfRequired() const override;
112 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
113 void RemoveTaskObserver(
114 base::MessageLoop::TaskObserver* task_observer) override;
115 void Shutdown() override;
116 void SuspendTimerQueue() override;
117 void ResumeTimerQueue() override;
118 void SetTimerQueueSuspensionWhenBackgroundedEnabled(bool enabled) override;
119 void SetTopLevelBlameContext(
120 base::trace_event::BlameContext* blame_context) override;
121 void SetRAILModeObserver(RAILModeObserver* observer) override;
122
123 // RenderWidgetSignals::Observer implementation:
124 void SetAllRenderWidgetsHidden(bool hidden) override;
125 void SetHasVisibleRenderWidgetWithTouchHandler(
126 bool has_visible_render_widget_with_touch_handler) override;
127
128 // SchedulerHelper::Observer implementation:
129 void OnUnregisterTaskQueue(const scoped_refptr<TaskQueue>& queue) override;
130 void OnTriedToExecuteBlockedTask(const TaskQueue& queue,
131 const base::PendingTask& task) override;
132
133 // TaskTimeTracker implementation:
134 void ReportTaskTime(base::TimeTicks start_time,
135 base::TimeTicks end_time) override;
136
137 // QueueingTimeEstimator::Client implementation:
138 void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time) override;
139
140 // Returns a task runner where tasks run at the highest possible priority.
141 scoped_refptr<TaskQueue> ControlTaskRunner();
142
143 void RegisterTimeDomain(TimeDomain* time_domain);
144 void UnregisterTimeDomain(TimeDomain* time_domain);
145
146 void SetExpensiveTaskBlockingAllowed(bool allowed);
147
148 void AddWebViewScheduler(WebViewSchedulerImpl* web_view_scheduler);
149 void RemoveWebViewScheduler(WebViewSchedulerImpl* web_view_scheduler);
150
151 // Test helpers.
152 SchedulerHelper* GetSchedulerHelperForTesting();
153 TaskCostEstimator* GetLoadingTaskCostEstimatorForTesting();
154 TaskCostEstimator* GetTimerTaskCostEstimatorForTesting();
155 IdleTimeEstimator* GetIdleTimeEstimatorForTesting();
156 base::TimeTicks CurrentIdleTaskDeadlineForTesting() const;
157 void RunIdleTasksForTesting(const base::Closure& callback);
158 void EndIdlePeriodForTesting(const base::Closure& callback,
159 base::TimeTicks time_remaining);
160 bool PolicyNeedsUpdateForTesting();
161
162 base::TickClock* tick_clock() const;
163
164 RealTimeDomain* real_time_domain() const {
165 return helper_.real_time_domain();
166 }
167
168 ThrottlingHelper* throttling_helper() { return throttling_helper_.get(); }
169
170 private:
171 friend class RendererSchedulerImplTest;
172 friend class RendererSchedulerImplForTest;
173 friend class RenderWidgetSchedulingState;
174
175 enum class ExpensiveTaskPolicy { RUN, BLOCK, THROTTLE };
176
177 enum class TimeDomainType {
178 REAL,
179 THROTTLED,
180 };
181
182 struct TaskQueuePolicy {
183 TaskQueuePolicy()
184 : is_enabled(true),
185 priority(TaskQueue::NORMAL_PRIORITY),
186 time_domain_type(TimeDomainType::REAL) {}
187
188 bool is_enabled;
189 TaskQueue::QueuePriority priority;
190 TimeDomainType time_domain_type;
191
192 bool operator==(const TaskQueuePolicy& other) const {
193 return is_enabled == other.is_enabled && priority == other.priority &&
194 time_domain_type == other.time_domain_type;
195 }
196 };
197
198 struct Policy {
199 TaskQueuePolicy compositor_queue_policy;
200 TaskQueuePolicy loading_queue_policy;
201 TaskQueuePolicy timer_queue_policy;
202 TaskQueuePolicy default_queue_policy;
203 v8::RAILMode rail_mode = v8::PERFORMANCE_ANIMATION;
204
205 bool operator==(const Policy& other) const {
206 return compositor_queue_policy == other.compositor_queue_policy &&
207 loading_queue_policy == other.loading_queue_policy &&
208 timer_queue_policy == other.timer_queue_policy &&
209 default_queue_policy == other.default_queue_policy &&
210 rail_mode == other.rail_mode;
211 }
212 };
213
214 class PollableNeedsUpdateFlag {
215 public:
216 PollableNeedsUpdateFlag(base::Lock* write_lock);
217 ~PollableNeedsUpdateFlag();
218
219 // Set the flag. May only be called if |write_lock| is held.
220 void SetWhileLocked(bool value);
221
222 // Returns true iff the flag is set to true.
223 bool IsSet() const;
224
225 private:
226 base::subtle::Atomic32 flag_;
227 base::Lock* write_lock_; // Not owned.
228
229 DISALLOW_COPY_AND_ASSIGN(PollableNeedsUpdateFlag);
230 };
231
232 // IdleHelper::Delegate implementation:
233 bool CanEnterLongIdlePeriod(
234 base::TimeTicks now,
235 base::TimeDelta* next_long_idle_period_delay_out) override;
236 void IsNotQuiescent() override {}
237 void OnIdlePeriodStarted() override;
238 void OnIdlePeriodEnded() override;
239
240 void EndIdlePeriod();
241
242 // Returns the serialized scheduler state for tracing.
243 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue(
244 base::TimeTicks optional_now) const;
245 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValueLocked(
246 base::TimeTicks optional_now) const;
247
248 static bool ShouldPrioritizeInputEvent(
249 const blink::WebInputEvent& web_input_event);
250
251 // The amount of time which idle periods can continue being scheduled when the
252 // renderer has been hidden, before going to sleep for good.
253 static const int kEndIdleWhenHiddenDelayMillis = 10000;
254
255 // The amount of time for which loading tasks will be prioritized over
256 // other tasks during the initial page load.
257 static const int kRailsInitialLoadingPrioritizationMillis = 1000;
258
259 // The amount of time in milliseconds we have to respond to user input as
260 // defined by RAILS.
261 static const int kRailsResponseTimeMillis = 50;
262
263 // For the purposes of deciding whether or not it's safe to turn timers and
264 // loading tasks on only in idle periods, we regard the system as being as
265 // being "idle period" starved if there hasn't been an idle period in the last
266 // 10 seconds. This was chosen to be long enough to cover most anticipated
267 // user gestures.
268 static const int kIdlePeriodStarvationThresholdMillis = 10000;
269
270 // The amount of time to wait before suspending shared timers after the
271 // renderer has been backgrounded. This is used only if background suspension
272 // of shared timers is enabled.
273 static const int kSuspendTimersWhenBackgroundedDelayMillis = 5 * 60 * 1000;
274
275 // The time we should stay in a priority-escalated mode after a call to
276 // DidAnimateForInputOnCompositorThread().
277 static const int kFlingEscalationLimitMillis = 100;
278
279 // Schedules an immediate PolicyUpdate, if there isn't one already pending and
280 // sets |policy_may_need_update_|. Note |any_thread_lock_| must be
281 // locked.
282 void EnsureUrgentPolicyUpdatePostedOnMainThread(
283 const tracked_objects::Location& from_here);
284
285 // Update the policy if a new signal has arrived. Must be called from the main
286 // thread.
287 void MaybeUpdatePolicy();
288
289 // Locks |any_thread_lock_| and updates the scheduler policy. May early
290 // out if the policy is unchanged. Must be called from the main thread.
291 void UpdatePolicy();
292
293 // Like UpdatePolicy, except it doesn't early out.
294 void ForceUpdatePolicy();
295
296 enum class UpdateType {
297 MAY_EARLY_OUT_IF_POLICY_UNCHANGED,
298 FORCE_UPDATE,
299 };
300
301 // The implelemtation of UpdatePolicy & ForceUpdatePolicy. It is allowed to
302 // early out if |update_type| is MAY_EARLY_OUT_IF_POLICY_UNCHANGED.
303 virtual void UpdatePolicyLocked(UpdateType update_type);
304
305 // Helper for computing the use case. |expected_usecase_duration| will be
306 // filled with the amount of time after which the use case should be updated
307 // again. If the duration is zero, a new use case update should not be
308 // scheduled. Must be called with |any_thread_lock_| held. Can be called from
309 // any thread.
310 UseCase ComputeCurrentUseCase(
311 base::TimeTicks now,
312 base::TimeDelta* expected_use_case_duration) const;
313
314 // An input event of some sort happened, the policy may need updating.
315 void UpdateForInputEventOnCompositorThread(blink::WebInputEvent::Type type,
316 InputEventState input_event_state);
317
318 // Returns true if there has been at least one idle period in the last
319 // |kIdlePeriodStarvationThresholdMillis|.
320 bool HadAnIdlePeriodRecently(base::TimeTicks now) const;
321
322 // Helpers for safely suspending/resuming the timer queue after a
323 // background/foreground signal.
324 void SuspendTimerQueueWhenBackgrounded();
325 void ResumeTimerQueueWhenForegrounded();
326
327 // The task cost estimators and the UserModel need to be reset upon page
328 // nagigation. This function does that. Must be called from the main thread.
329 void ResetForNavigationLocked();
330
331 // Estimates the maximum task length that won't cause a jank based on the
332 // current system state. Must be called from the main thread.
333 base::TimeDelta EstimateLongestJankFreeTaskDuration() const;
334
335 // Log a console warning message to all WebViews in this process.
336 void BroadcastConsoleWarning(const std::string& message);
337
338 void ApplyTaskQueuePolicy(TaskQueue* task_queue,
339 const TaskQueuePolicy& old_task_queue_policy,
340 const TaskQueuePolicy& new_task_queue_policy) const;
341
342 static const char* ExpensiveTaskPolicyToString(
343 ExpensiveTaskPolicy expensive_task_policy);
344
345 SchedulerHelper helper_;
346 IdleHelper idle_helper_;
347 std::unique_ptr<ThrottlingHelper> throttling_helper_;
348 RenderWidgetSignals render_widget_scheduler_signals_;
349
350 const scoped_refptr<TaskQueue> control_task_runner_;
351 const scoped_refptr<TaskQueue> compositor_task_runner_;
352 std::set<scoped_refptr<TaskQueue>> loading_task_runners_;
353 std::set<scoped_refptr<TaskQueue>> timer_task_runners_;
354 scoped_refptr<TaskQueue> default_loading_task_runner_;
355 scoped_refptr<TaskQueue> default_timer_task_runner_;
356
357 base::Closure update_policy_closure_;
358 DeadlineTaskRunner delayed_update_policy_runner_;
359 CancelableClosureHolder end_renderer_hidden_idle_period_closure_;
360 CancelableClosureHolder suspend_timers_when_backgrounded_closure_;
361
362 // We have decided to improve thread safety at the cost of some boilerplate
363 // (the accessors) for the following data members.
364
365 struct MainThreadOnly {
366 MainThreadOnly(RendererSchedulerImpl* renderer_scheduler_impl,
367 const scoped_refptr<TaskQueue>& compositor_task_runner,
368 base::TickClock* time_source);
369 ~MainThreadOnly();
370
371 TaskCostEstimator loading_task_cost_estimator;
372 TaskCostEstimator timer_task_cost_estimator;
373 QueueingTimeEstimator queueing_time_estimator;
374 IdleTimeEstimator idle_time_estimator;
375 UseCase current_use_case;
376 Policy current_policy;
377 base::TimeTicks current_policy_expiration_time;
378 base::TimeTicks estimated_next_frame_begin;
379 base::TimeDelta compositor_frame_interval;
380 base::TimeDelta longest_jank_free_task_duration;
381 int timer_queue_suspend_count; // TIMER_TASK_QUEUE suspended if non-zero.
382 int navigation_task_expected_count;
383 ExpensiveTaskPolicy expensive_task_policy;
384 bool renderer_hidden;
385 bool renderer_backgrounded;
386 bool renderer_suspended;
387 bool timer_queue_suspension_when_backgrounded_enabled;
388 bool timer_queue_suspended_when_backgrounded;
389 bool was_shutdown;
390 bool loading_tasks_seem_expensive;
391 bool timer_tasks_seem_expensive;
392 bool touchstart_expected_soon;
393 bool have_seen_a_begin_main_frame;
394 bool have_reported_blocking_intervention_in_current_policy;
395 bool have_reported_blocking_intervention_since_navigation;
396 bool has_visible_render_widget_with_touch_handler;
397 bool begin_frame_not_expected_soon;
398 bool expensive_task_blocking_allowed;
399 bool in_idle_period_for_testing;
400 std::set<WebViewSchedulerImpl*> web_view_schedulers; // Not owned.
401 RAILModeObserver* rail_mode_observer; // Not owned.
402 };
403
404 struct AnyThread {
405 AnyThread();
406 ~AnyThread();
407
408 base::TimeTicks last_idle_period_end_time;
409 base::TimeTicks rails_loading_priority_deadline;
410 base::TimeTicks fling_compositor_escalation_deadline;
411 UserModel user_model;
412 bool awaiting_touch_start_response;
413 bool in_idle_period;
414 bool begin_main_frame_on_critical_path;
415 bool last_gesture_was_compositor_driven;
416 bool default_gesture_prevented;
417 bool have_seen_touchstart;
418 };
419
420 struct CompositorThreadOnly {
421 CompositorThreadOnly();
422 ~CompositorThreadOnly();
423
424 blink::WebInputEvent::Type last_input_type;
425 std::unique_ptr<base::ThreadChecker> compositor_thread_checker;
426
427 void CheckOnValidThread() {
428 #if DCHECK_IS_ON()
429 // We don't actually care which thread this called from, just so long as
430 // its consistent.
431 if (!compositor_thread_checker)
432 compositor_thread_checker.reset(new base::ThreadChecker());
433 DCHECK(compositor_thread_checker->CalledOnValidThread());
434 #endif
435 }
436 };
437
438 // Don't access main_thread_only_, instead use MainThreadOnly().
439 MainThreadOnly main_thread_only_;
440 MainThreadOnly& MainThreadOnly() {
441 helper_.CheckOnValidThread();
442 return main_thread_only_;
443 }
444 const struct MainThreadOnly& MainThreadOnly() const {
445 helper_.CheckOnValidThread();
446 return main_thread_only_;
447 }
448
449 mutable base::Lock any_thread_lock_;
450 // Don't access any_thread_, instead use AnyThread().
451 AnyThread any_thread_;
452 AnyThread& AnyThread() {
453 any_thread_lock_.AssertAcquired();
454 return any_thread_;
455 }
456 const struct AnyThread& AnyThread() const {
457 any_thread_lock_.AssertAcquired();
458 return any_thread_;
459 }
460
461 // Don't access compositor_thread_only_, instead use CompositorThreadOnly().
462 CompositorThreadOnly compositor_thread_only_;
463 CompositorThreadOnly& CompositorThreadOnly() {
464 compositor_thread_only_.CheckOnValidThread();
465 return compositor_thread_only_;
466 }
467
468 PollableThreadSafeFlag policy_may_need_update_;
469 base::WeakPtrFactory<RendererSchedulerImpl> weak_factory_;
470
471 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImpl);
472 };
473
474 } // namespace scheduler
475
476 #endif // COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698