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

Side by Side Diff: components/scheduler/child/idle_helper.h

Issue 1151353003: [scheduler]: Avoid waking up the scheduler to end long idle periods. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@end_idle_sync_2
Patch Set: Fix tests and update for review. Created 5 years, 6 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 #ifndef COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_ 5 #ifndef COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_
6 #define COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_ 6 #define COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_
7 7
8 #include "base/message_loop/message_loop.h"
8 #include "components/scheduler/child/cancelable_closure_holder.h" 9 #include "components/scheduler/child/cancelable_closure_holder.h"
10 #include "components/scheduler/child/pollable_thread_safe_flag.h"
9 #include "components/scheduler/child/prioritizing_task_queue_selector.h" 11 #include "components/scheduler/child/prioritizing_task_queue_selector.h"
10 #include "components/scheduler/child/single_thread_idle_task_runner.h" 12 #include "components/scheduler/child/single_thread_idle_task_runner.h"
11 #include "components/scheduler/scheduler_export.h" 13 #include "components/scheduler/scheduler_export.h"
12 14
13 namespace scheduler { 15 namespace scheduler {
14 16
15 class SchedulerHelper; 17 class SchedulerHelper;
16 18
17 // Common scheduler functionality for Idle tasks. 19 // Common scheduler functionality for Idle tasks.
18 class SCHEDULER_EXPORT IdleHelper { 20 class SCHEDULER_EXPORT IdleHelper
21 : public base::MessageLoop::TaskObserver,
22 public SingleThreadIdleTaskRunner::Delegate {
19 public: 23 public:
20 // Used to by scheduler implementations to customize idle behaviour. 24 // Used to by scheduler implementations to customize idle behaviour.
21 class SCHEDULER_EXPORT Delegate { 25 class SCHEDULER_EXPORT Delegate {
22 public: 26 public:
23 Delegate(); 27 Delegate();
24 virtual ~Delegate(); 28 virtual ~Delegate();
25 29
26 // If it's ok to enter a long idle period, return true. Otherwise return 30 // If it's ok to enter a long idle period, return true. Otherwise return
27 // false and set next_long_idle_period_delay_out so we know when to try 31 // false and set next_long_idle_period_delay_out so we know when to try
28 // again. 32 // again.
29 virtual bool CanEnterLongIdlePeriod( 33 virtual bool CanEnterLongIdlePeriod(
30 base::TimeTicks now, 34 base::TimeTicks now,
31 base::TimeDelta* next_long_idle_period_delay_out) = 0; 35 base::TimeDelta* next_long_idle_period_delay_out) = 0;
32 36
33 // Signals that the Long Idle Period hasn't started yet because the system 37 // Signals that the Long Idle Period hasn't started yet because the system
34 // isn't quiescent. 38 // isn't quiescent.
35 virtual void IsNotQuiescent() = 0; 39 virtual void IsNotQuiescent() = 0;
36 40
37 private: 41 private:
38 DISALLOW_COPY_AND_ASSIGN(Delegate); 42 DISALLOW_COPY_AND_ASSIGN(Delegate);
39 }; 43 };
40 44
41 // Keep IdleHelper::IdlePeriodStateToString in sync with this enum. 45 // Keep IdleHelper::IdlePeriodStateToString in sync with this enum.
42 enum class IdlePeriodState { 46 enum class IdlePeriodState {
43 NOT_IN_IDLE_PERIOD, 47 NOT_IN_IDLE_PERIOD,
44 IN_SHORT_IDLE_PERIOD, 48 IN_SHORT_IDLE_PERIOD,
45 IN_LONG_IDLE_PERIOD, 49 IN_LONG_IDLE_PERIOD,
46 IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE, 50 IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE,
47 ENDING_LONG_IDLE_PERIOD, 51 IN_LONG_IDLE_PERIOD_PAUSED,
48 // Must be the last entry. 52 // Must be the last entry.
49 IDLE_PERIOD_STATE_COUNT, 53 IDLE_PERIOD_STATE_COUNT,
50 FIRST_IDLE_PERIOD_STATE = NOT_IN_IDLE_PERIOD, 54 FIRST_IDLE_PERIOD_STATE = NOT_IN_IDLE_PERIOD,
51 }; 55 };
52 56
53 // The maximum length of an idle period. 57 // The maximum length of an idle period.
54 static const int kMaximumIdlePeriodMillis = 50; 58 static const int kMaximumIdlePeriodMillis = 50;
55 59
56 // |helper| and |delegate| are not owned by IdleHelper object and must 60 // |helper| and |delegate| are not owned by IdleHelper object and must
57 // outlive it. 61 // outlive it.
58 IdleHelper( 62 IdleHelper(
59 SchedulerHelper* helper, 63 SchedulerHelper* helper,
60 Delegate* delegate, 64 Delegate* delegate,
61 size_t idle_queue_index, 65 size_t idle_queue_index,
62 const char* tracing_category, 66 const char* tracing_category,
63 const char* disabled_by_default_tracing_category, 67 const char* disabled_by_default_tracing_category,
64 const char* idle_period_tracing_name, 68 const char* idle_period_tracing_name,
65 base::TimeDelta required_quiescence_duration_before_long_idle_period); 69 base::TimeDelta required_quiescence_duration_before_long_idle_period);
66 ~IdleHelper(); 70 ~IdleHelper() override;
67 71
68 // Returns the idle task runner. Tasks posted to this runner may be reordered 72 // Returns the idle task runner. Tasks posted to this runner may be reordered
69 // relative to other task types and may be starved for an arbitrarily long 73 // relative to other task types and may be starved for an arbitrarily long
70 // time if no idle time is available. 74 // time if no idle time is available.
71 scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner(); 75 scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner();
72 76
73 // If |required_quiescence_duration_before_long_idle_period_| is zero then 77 // If |required_quiescence_duration_before_long_idle_period_| is zero then
74 // immediately initiate a long idle period, otherwise check if any tasks have 78 // immediately initiate a long idle period, otherwise check if any tasks have
75 // run recently and if so, check again after a delay of 79 // run recently and if so, check again after a delay of
76 // |required_quiescence_duration_before_long_idle_period_|. 80 // |required_quiescence_duration_before_long_idle_period_|.
77 // Calling this function will end any previous idle period immediately, and 81 // Calling this function will end any previous idle period immediately, and
78 // potentially again later if 82 // potentially again later if
79 // |required_quiescence_duration_before_long_idle_period_| is non-zero. 83 // |required_quiescence_duration_before_long_idle_period_| is non-zero.
80 // NOTE EndIdlePeriod will disable the long idle periods. 84 // NOTE EndIdlePeriod will disable the long idle periods.
81 void EnableLongIdlePeriod(); 85 void EnableLongIdlePeriod();
82 86
83 // Start and end an idle period. If |post_end_idle_period| is true, it will 87 // Start an idle period with a given idle period deadline.
84 // post a delayed EndIdlePeriod scheduled to occur at |idle_period_deadline|.
85 void StartIdlePeriod(IdlePeriodState new_idle_period_state, 88 void StartIdlePeriod(IdlePeriodState new_idle_period_state,
86 base::TimeTicks now, 89 base::TimeTicks now,
87 base::TimeTicks idle_period_deadline, 90 base::TimeTicks idle_period_deadline);
88 bool post_end_idle_period);
89 91
90 // This will end an idle period either started with StartIdlePeriod or 92 // This will end an idle period either started with StartIdlePeriod or
91 // EnableLongIdlePeriod. 93 // EnableLongIdlePeriod.
92 void EndIdlePeriod(); 94 void EndIdlePeriod();
93 95
94 // Returns true if a currently running idle task could exceed its deadline 96 // Returns true if a currently running idle task could exceed its deadline
95 // without impacting user experience too much. This should only be used if 97 // without impacting user experience too much. This should only be used if
96 // there is a task which cannot be pre-empted and is likely to take longer 98 // there is a task which cannot be pre-empted and is likely to take longer
97 // than the largest expected idle task deadline. It should NOT be polled to 99 // than the largest expected idle task deadline. It should NOT be polled to
98 // check whether more work can be performed on the current idle task after 100 // check whether more work can be performed on the current idle task after
99 // its deadline has expired - post a new idle task for the continuation of the 101 // its deadline has expired - post a new idle task for the continuation of the
100 // work in this case. 102 // work in this case.
101 // Must be called from the thread this class was created on. 103 // Must be called from the thread this class was created on.
102 bool CanExceedIdleDeadlineIfRequired() const; 104 bool CanExceedIdleDeadlineIfRequired() const;
103 105
106 // Returns the deadline for the current idle task.
107 base::TimeTicks CurrentIdleTaskDeadline() const;
108
109 // SingleThreadIdleTaskRunner::Delegate implementation:
110 void OnIdleTaskPosted() override;
111 base::TimeTicks WillProcessIdleTask() const override;
112 void DidProcessIdleTask() override;
113
114 // base::MessageLoop::TaskObserver implementation:
115 void WillProcessTask(const base::PendingTask& pending_task) override;
116 void DidProcessTask(const base::PendingTask& pending_task) override;
117
104 IdlePeriodState SchedulerIdlePeriodState() const; 118 IdlePeriodState SchedulerIdlePeriodState() const;
105
106 // IdleTaskDeadlineSupplier Implementation:
107 void CurrentIdleTaskDeadlineCallback(base::TimeTicks* deadline_out) const;
108
109 static const char* IdlePeriodStateToString(IdlePeriodState state); 119 static const char* IdlePeriodStateToString(IdlePeriodState state);
110 120
111 private: 121 private:
122 friend class BaseIdleHelperTest;
112 friend class IdleHelperTest; 123 friend class IdleHelperTest;
113 124
125 class State {
126 public:
127 State(SchedulerHelper* helper,
128 const char* tracing_category,
129 const char* disabled_by_default_tracing_category,
130 const char* idle_period_tracing_name);
131 virtual ~State();
132
133 void TraceIdleIdleTaskStart() const;
134 void TraceIdleIdleTaskEnd() const;
135 void UpdateState(IdlePeriodState new_state,
136 base::TimeTicks new_deadline,
137 base::TimeTicks optional_now);
138 void TraceEventIdlePeriodStateChange(IdlePeriodState new_state,
139 base::TimeTicks new_deadline,
140 base::TimeTicks optional_now) const;
141
142 IdlePeriodState idle_period_state() const;
143 base::TimeTicks idle_period_deadline() const;
144 bool idle_period_paused_flag() const;
Sami 2015/06/01 17:11:57 nit: Since this involves a little more than just r
rmcilroy 2015/06/01 19:12:43 Ack (doesn't exist any longer).
145
146 private:
147 SchedulerHelper* helper_; // NOT OWNED
148
149 base::Lock write_lock_;
150 IdlePeriodState idle_period_state_;
151 base::TimeTicks idle_period_deadline_;
152 PollableThreadSafeFlag idle_period_paused_flag_;
153
154 base::TimeTicks idle_period_deadline_for_tracing_;
155 mutable base::TimeTicks last_idle_task_trace_time_;
Sami 2015/06/01 17:11:57 Rather than make these mutable, how about just mak
rmcilroy 2015/06/01 19:12:43 Ok. This makes WillProcessIdleTask non-const thoug
Sami 2015/06/02 10:33:15 Right, that seems fine since it's meant to be an a
156 mutable bool nestable_events_started_;
157 const char* tracing_category_;
158 const char* disabled_by_default_tracing_category_;
159 const char* idle_period_tracing_name_;
160
161 DISALLOW_COPY_AND_ASSIGN(State);
162 };
163
114 // The minimum delay to wait between retrying to initiate a long idle time. 164 // The minimum delay to wait between retrying to initiate a long idle time.
115 static const int kRetryEnableLongIdlePeriodDelayMillis = 1; 165 static const int kRetryEnableLongIdlePeriodDelayMillis = 1;
116 166
117 // Returns the new idle period state for the next long idle period. Fills in 167 // Returns the new idle period state for the next long idle period. Fills in
118 // |next_long_idle_period_delay_out| with the next time we should try to 168 // |next_long_idle_period_delay_out| with the next time we should try to
119 // initiate the next idle period. 169 // initiate the next idle period.
120 IdlePeriodState ComputeNewLongIdlePeriodState( 170 IdlePeriodState ComputeNewLongIdlePeriodState(
121 const base::TimeTicks now, 171 const base::TimeTicks now,
122 base::TimeDelta* next_long_idle_period_delay_out); 172 base::TimeDelta* next_long_idle_period_delay_out);
123 173
124 bool ShouldWaitForQuiescence(); 174 bool ShouldWaitForQuiescence();
125 void EnableLongIdlePeriodAfterWakeup(); 175 void UpdateLongIdlePeriodStateAfterIdleTask();
176
177 void SetIdlePeriodState(IdlePeriodState new_state,
178 base::TimeTicks new_deadline,
179 base::TimeTicks optional_now);
126 180
127 // Returns true if |state| represents being within an idle period state. 181 // Returns true if |state| represents being within an idle period state.
128 static bool IsInIdlePeriod(IdlePeriodState state); 182 static bool IsInIdlePeriod(IdlePeriodState state);
183 // Returns true if |state| represents being within a long idle period state.
184 static bool IsInLongIdlePeriod(IdlePeriodState state);
129 185
130 SchedulerHelper* helper_; // NOT OWNED 186 SchedulerHelper* helper_; // NOT OWNED
131 Delegate* delegate_; // NOT OWNED 187 Delegate* delegate_; // NOT OWNED
132 size_t idle_queue_index_; 188 size_t idle_queue_index_;
133 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; 189 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
134 190
135 CancelableClosureHolder end_idle_period_closure_;
136 CancelableClosureHolder enable_next_long_idle_period_closure_; 191 CancelableClosureHolder enable_next_long_idle_period_closure_;
137 CancelableClosureHolder enable_next_long_idle_period_after_wakeup_closure_;
138 192
139 IdlePeriodState idle_period_state_; 193 State state_;
140 194
141 // A bitmap which controls the set of queues that are checked for quiescence 195 // A bitmap which controls the set of queues that are checked for quiescence
142 // before triggering a long idle period. 196 // before triggering a long idle period.
143 uint64 quiescence_monitored_task_queue_mask_; 197 uint64 quiescence_monitored_task_queue_mask_;
144 base::TimeDelta required_quiescence_duration_before_long_idle_period_; 198 base::TimeDelta required_quiescence_duration_before_long_idle_period_;
145 199
146 base::TimeTicks idle_period_deadline_;
147
148 const char* tracing_category_;
149 const char* disabled_by_default_tracing_category_; 200 const char* disabled_by_default_tracing_category_;
150 const char* idle_period_tracing_name_;
151 201
152 base::WeakPtr<IdleHelper> weak_idle_helper_ptr_; 202 base::WeakPtr<IdleHelper> weak_idle_helper_ptr_;
153 base::WeakPtrFactory<IdleHelper> weak_factory_; 203 base::WeakPtrFactory<IdleHelper> weak_factory_;
154 204
155 DISALLOW_COPY_AND_ASSIGN(IdleHelper); 205 DISALLOW_COPY_AND_ASSIGN(IdleHelper);
156 }; 206 };
157 207
158 } // namespace scheduler 208 } // namespace scheduler
159 209
160 #endif // COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_ 210 #endif // COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698