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

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

Powered by Google App Engine
This is Rietveld 408576698