1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
content / browser / scheduler / browser_ui_thread_scheduler.h [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_SCHEDULER_BROWSER_UI_THREAD_SCHEDULER_H_
#define CONTENT_BROWSER_SCHEDULER_BROWSER_UI_THREAD_SCHEDULER_H_
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/task/sequence_manager/task_queue.h"
#include "base/time/time.h"
#include "content/browser/scheduler/browser_task_queues.h"
#include "content/common/content_export.h"
namespace base {
namespace sequence_manager {
class SequenceManager;
} // namespace sequence_manager
} // namespace base
namespace content {
class BrowserTaskExecutor;
// The BrowserUIThreadScheduler vends TaskQueues and manipulates them to
// implement scheduling policy. This class is never deleted in production.
class CONTENT_EXPORT BrowserUIThreadScheduler {
public:
class UserInputActiveHandle {
public:
explicit UserInputActiveHandle(BrowserUIThreadScheduler* scheduler);
~UserInputActiveHandle();
// This is a move only type.
UserInputActiveHandle(const UserInputActiveHandle&) = delete;
UserInputActiveHandle& operator=(const UserInputActiveHandle&) = delete;
UserInputActiveHandle& operator=(UserInputActiveHandle&&);
UserInputActiveHandle(UserInputActiveHandle&& other);
private:
void MoveFrom(UserInputActiveHandle* other);
// Only this constructor actually creates a UserInputActiveHandle that will
// inform scheduling decisions.
raw_ptr<BrowserUIThreadScheduler> scheduler_ = nullptr;
};
enum ScrollState { kGestureScrollActive, kFlingActive, kNone };
using Handle = BrowserTaskQueues::Handle;
BrowserUIThreadScheduler();
BrowserUIThreadScheduler(const BrowserUIThreadScheduler&) = delete;
BrowserUIThreadScheduler& operator=(const BrowserUIThreadScheduler&) = delete;
~BrowserUIThreadScheduler();
static BrowserUIThreadScheduler* Get();
// Setting the DefaultTaskRunner is up to the caller.
static std::unique_ptr<BrowserUIThreadScheduler> CreateForTesting(
base::sequence_manager::SequenceManager* sequence_manager);
using QueueType = BrowserTaskQueues::QueueType;
scoped_refptr<Handle> GetHandle() const { return handle_; }
void OnScrollStateUpdate(ScrollState scroll_state);
private:
friend class BrowserTaskExecutor;
friend class BrowserUIThreadSchedulerTest;
using QueueEnabledVoter =
base::sequence_manager::TaskQueue::QueueEnabledVoter;
explicit BrowserUIThreadScheduler(
base::sequence_manager::SequenceManager* sequence_manager);
void CommonSequenceManagerSetup(
base::sequence_manager::SequenceManager* sequence_manager);
// Called after the feature list is ready and we can set up any policy
// experiments.
void PostFeatureListSetup();
void EnableBrowserPrioritizesNativeWork();
void EnableDeferringBrowserUIThreadTasks();
// Used in the BrowserPrioritizeNativeWork experiment, when we want to
// prioritize yielding to java when user input starts and for a short period
// after it ends.
BrowserUIThreadScheduler::UserInputActiveHandle OnUserInputStart();
void DidStartUserInput();
void DidEndUserInput();
// After user input has ended CancelNativePriority will be called to inform
// the SequenceManager to stop prioritizing yielding to native tasks.
void CancelNativePriority();
// Update the scheduling policy when a scroll becomes active or stops.
void UpdatePolicyOnScrollStateUpdate(ScrollState old_state,
ScrollState new_state);
// Updates task queues' state to allow/disallow some queues from running
// during certain events.
// Can be expanded to modify queue priorities as well.
void UpdateTaskQueueStates();
QueueEnabledVoter& GetBrowserTaskRunnerVoter(QueueType queue_type) {
return *queue_enabled_voters_[static_cast<size_t>(queue_type)].get();
}
// Policy controls the scheduling policy for UI main thread, like which
// queues get to run at what priority, depending on system state.
class Policy {
public:
Policy() = default;
~Policy() = default;
bool operator==(const Policy& other) const {
return should_defer_task_queues_ == other.should_defer_task_queues_ &&
defer_normal_or_lower_priority_tasks_ ==
other.defer_normal_or_lower_priority_tasks_ &&
defer_known_long_running_tasks_ ==
other.defer_known_long_running_tasks_;
}
bool IsQueueEnabled(BrowserTaskQueues::QueueType task_queue) const;
// Currently used to defer task queues during scrolls.
bool should_defer_task_queues_ = false;
// Those are temporary finch flags used to control different experiment
// groups inside the |BrowserDeferUIThreadTasks| finch experiment.
// Each flag signals deferring a different set of task queues.
// For group 1, |defer_normal_or_lower_priority_tasks_| controls deferring
// all tasks queues with normal priority or lower during a scroll.
bool defer_normal_or_lower_priority_tasks_ = false;
// For group 2, |defer_known_long_running_tasks_| means that some tasks
// will be posted to the |kDeferrableUserBlocking| and those are the only
// tasks that should be deferred.
bool defer_known_long_running_tasks_ = false;
};
// In production the BrowserUIThreadScheduler will own its SequenceManager,
// but in tests it may not.
std::unique_ptr<base::sequence_manager::SequenceManager>
owned_sequence_manager_;
BrowserTaskQueues task_queues_;
std::array<std::unique_ptr<QueueEnabledVoter>,
BrowserTaskQueues::kNumQueueTypes>
queue_enabled_voters_;
scoped_refptr<Handle> handle_;
// These three variables are used in the BrowserPrioritizeNativeWork finch
// experiment. False ensures this feature is disabled by default.
int user_input_active_handle_count = 0;
bool browser_prioritize_native_work_ = false;
base::TimeDelta browser_prioritize_native_work_after_input_end_ms_;
ScrollState scroll_state_ = ScrollState::kNone;
Policy current_policy_;
// This variable is used to control the kBrowserDeferUIThreadTasks finch
// experiment, false indicates it is disabled by default.
bool browser_enable_deferring_ui_thread_tasks_ = false;
};
} // namespace content
#endif // CONTENT_BROWSER_SCHEDULER_BROWSER_UI_THREAD_SCHEDULER_H_