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

Side by Side Diff: Source/platform/scheduler/Scheduler.cpp

Issue 439923006: Prioritizing input and compositor tasks in the blink scheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Responding to Sami's comments Created 6 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 #include "config.h" 5 #include "config.h"
6 #include "platform/scheduler/Scheduler.h" 6 #include "platform/scheduler/Scheduler.h"
7 7
8 #include "platform/PlatformThreadData.h"
8 #include "platform/Task.h" 9 #include "platform/Task.h"
10 #include "platform/ThreadTimers.h"
9 #include "platform/TraceEvent.h" 11 #include "platform/TraceEvent.h"
10 #include "platform/TraceLocation.h"
11 #include "public/platform/Platform.h" 12 #include "public/platform/Platform.h"
12 #include "public/platform/WebThread.h" 13 #include "wtf/ThreadingPrimitives.h"
13 14
14 namespace blink { 15 namespace blink {
15 16
16 namespace { 17 namespace {
17 18
18 class MainThreadTaskAdapter : public blink::WebThread::Task {
19 public:
20 explicit MainThreadTaskAdapter(const TraceLocation& location, const Schedule r::Task& task)
21 : m_location(location)
22 , m_task(task)
23 {
24 }
25
26 // WebThread::Task implementation.
27 virtual void run() OVERRIDE
28 {
29 TRACE_EVENT2("blink", "MainThreadTaskAdapter::run",
30 "src_file", m_location.fileName(),
31 "src_func", m_location.functionName());
32 m_task();
33 }
34
35 private:
36 const TraceLocation m_location;
37 Scheduler::Task m_task;
38 };
39
40 class MainThreadIdleTaskAdapter : public blink::WebThread::Task { 19 class MainThreadIdleTaskAdapter : public blink::WebThread::Task {
41 public: 20 public:
42 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs) 21 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs)
43 : m_idleTask(idleTask) 22 : m_idleTask(idleTask)
44 , m_allottedTimeMs(allottedTimeMs) 23 , m_allottedTimeMs(allottedTimeMs)
45 { 24 {
46 } 25 }
47 26
48 // WebThread::Task implementation. 27 // WebThread::Task implementation.
49 virtual void run() OVERRIDE 28 virtual void run() OVERRIDE
50 { 29 {
51 TRACE_EVENT1("blink", "MainThreadIdleTaskAdapter::run", "allottedTime", m_allottedTimeMs); 30 TRACE_EVENT1("blink", "MainThreadIdleTaskAdapter::run", "allottedTime", m_allottedTimeMs);
52 m_idleTask(m_allottedTimeMs); 31 m_idleTask(m_allottedTimeMs);
53 } 32 }
54 33
55 private: 34 private:
56 Scheduler::IdleTask m_idleTask; 35 Scheduler::IdleTask m_idleTask;
eseidel 2014/08/08 17:31:06 Why are idle tasks different from tasks?
alexclarke 2014/08/12 11:37:01 Done.
57 double m_allottedTimeMs; 36 double m_allottedTimeMs;
eseidel 2014/08/08 17:31:06 Filed cbug.com/402027 about having real types for
alexclarke 2014/08/12 11:37:01 Acknowledged.
58 }; 37 };
59 38
60 } 39 } // namespace
40
41 class Scheduler::MainThreadPendingHighPriorityTaskRunner : public blink::WebThre ad::Task {
eseidel 2014/08/08 17:31:06 Don't need blink::
alexclarke 2014/08/12 11:37:01 Done.
42 public:
43 MainThreadPendingHighPriorityTaskRunner()
44 {
45 ASSERT(Scheduler::shared());
46 atomicIncrement(&Scheduler::shared()->m_mainThreadTaskRunnerCount);
eseidel 2014/08/08 17:31:06 Why are we grabbing at a m_? Instead of using a f
alexclarke 2014/08/12 11:37:01 Done.
47 }
48
49 ~MainThreadPendingHighPriorityTaskRunner()
50 {
51 Scheduler* scheduler = Scheduler::shared();
52 if (!scheduler)
53 return;
54 atomicDecrement(&scheduler->m_mainThreadTaskRunnerCount);
55 }
56
57 // WebThread::Task implementation.
58 virtual void run() OVERRIDE
59 {
60 Scheduler* scheduler = Scheduler::shared();
61 if (!scheduler)
62 return;
63 scheduler->runHighPriorityTasks();
64 }
65 };
66
67 class Scheduler::MainThreadPendingTaskRunner : public blink::WebThread::Task {
68 public:
69 MainThreadPendingTaskRunner(
70 const Scheduler::Task& task, const TraceLocation& location)
71 : m_task(task)
72 , m_location(location)
73 {
74 ASSERT(Scheduler::shared());
75 atomicIncrement(&Scheduler::shared()->m_mainThreadTaskRunnerCount);
76 }
77
78 ~MainThreadPendingTaskRunner()
79 {
80 Scheduler* scheduler = Scheduler::shared();
81 if (!scheduler)
82 return;
83 atomicDecrement(&scheduler->m_mainThreadTaskRunnerCount);
84 }
85
86 // WebThread::Task implementation.
87 virtual void run() OVERRIDE
88 {
89 TRACE_EVENT2("blink", "MainThreadPendingTaskRunner::run",
90 "src_file", m_location.fileName(),
91 "src_func", m_location.functionName());
92 Scheduler* scheduler = Scheduler::shared();
93 if (scheduler)
94 Scheduler::shared()->runHighPriorityTasks();
95 m_task();
96 }
97
98 Scheduler::Task m_task;
99 TraceLocation m_location;
100 };
61 101
62 Scheduler* Scheduler::s_sharedScheduler = nullptr; 102 Scheduler* Scheduler::s_sharedScheduler = nullptr;
63 103
64 void Scheduler::initializeOnMainThread() 104 void Scheduler::initializeOnMainThread()
65 { 105 {
66 s_sharedScheduler = new Scheduler(); 106 s_sharedScheduler = new Scheduler();
67 } 107 }
68 108
69 void Scheduler::shutdown() 109 void Scheduler::shutdown()
70 { 110 {
71 delete s_sharedScheduler; 111 delete s_sharedScheduler;
72 s_sharedScheduler = nullptr; 112 s_sharedScheduler = nullptr;
73 } 113 }
74 114
75 Scheduler* Scheduler::shared() 115 Scheduler* Scheduler::shared()
76 { 116 {
77 return s_sharedScheduler; 117 return s_sharedScheduler;
78 } 118 }
79 119
80 Scheduler::Scheduler() 120 Scheduler::Scheduler()
81 : m_mainThread(blink::Platform::current()->currentThread()) 121 : m_mainThread(blink::Platform::current()->currentThread())
82 , m_sharedTimerFunction(nullptr) 122 , m_sharedTimerFunction(nullptr)
123 , m_mainThreadTaskRunnerCount(0)
83 { 124 {
84 } 125 }
85 126
86 Scheduler::~Scheduler() 127 Scheduler::~Scheduler()
87 { 128 {
88 } 129 while (!m_pendingInputTasks.isEmpty() || !m_pendingCompositorTasks.isEmpty() ) {
89 130 runHighPriorityTasks();
90 void Scheduler::scheduleTask(const TraceLocation& location, const Task& task) 131 }
91 {
92 m_mainThread->postTask(new MainThreadTaskAdapter(location, task));
93 } 132 }
94 133
95 void Scheduler::scheduleIdleTask(const IdleTask& idleTask) 134 void Scheduler::scheduleIdleTask(const IdleTask& idleTask)
96 { 135 {
97 // TODO: send a real allottedTime here. 136 // TODO: send a real allottedTime here.
98 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0)); 137 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0));
99 } 138 }
100 139
101 void Scheduler::postTask(const TraceLocation& location, const Task& task) 140 void Scheduler::postTask(const TraceLocation& location, const Task& task)
102 { 141 {
103 scheduleTask(location, task); 142 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location));
104 } 143 }
105 144
106 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) 145 void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
107 { 146 {
108 scheduleTask(location, task); 147 m_pendingInputTasks.append(TracedTask(task, location));
eseidel 2014/08/08 17:31:06 I really think we want all tasks to be traced. Tr
alexclarke 2014/08/12 11:37:01 Done.
148 maybePostMainThreadPendingHighPriorityTaskRunner();
109 } 149 }
110 150
111 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) 151 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk)
112 { 152 {
113 scheduleTask(location, task); 153 m_pendingCompositorTasks.append(TracedTask(task, location));
154 maybePostMainThreadPendingHighPriorityTaskRunner();
114 } 155 }
115 156
116 void Scheduler::postIdleTask(const IdleTask& idleTask) 157 void Scheduler::postIdleTask(const IdleTask& idleTask)
117 { 158 {
118 scheduleIdleTask(idleTask); 159 scheduleIdleTask(idleTask);
119 } 160 }
120 161
121 void Scheduler::tickSharedTimer() 162 void Scheduler::tickSharedTimer()
122 { 163 {
123 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer"); 164 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
165
166 runHighPriorityTasks();
124 m_sharedTimerFunction(); 167 m_sharedTimerFunction();
168 runHighPriorityTasks();
eseidel 2014/08/08 17:31:06 Why twice? If the sharedTimer function has chosen
alexclarke 2014/08/12 11:37:01 I've added some comments to explain this.
169 }
170
171 void Scheduler::runHighPriorityTasks()
172 {
173 TRACE_EVENT0("blink", "Scheduler::runHighPriorityTasks");
174
175 WTF::Deque<TracedTask>& inputTasks = m_pendingInputTasks.swapBuffers();
eseidel 2014/08/08 17:31:06 WTF:: should not be needed.
alexclarke 2014/08/12 11:37:02 Done.
176 WTF::Deque<TracedTask>& compositorTasks = m_pendingCompositorTasks.swapBuffe rs();
177
178 for (;;) {
179 if (!inputTasks.isEmpty()) {
180 inputTasks.takeFirst().run();
181 continue;
182 }
183
184 if (compositorTasks.isEmpty())
185 break;
186 compositorTasks.takeFirst().run();
187 }
188 }
189
190 void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
191 {
192 // Only post a task if there isn't a task already in flight.
193 if (acquireLoad(&m_mainThreadTaskRunnerCount))
194 return;
195
196 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner());
125 } 197 }
126 198
127 void Scheduler::sharedTimerAdapter() 199 void Scheduler::sharedTimerAdapter()
128 { 200 {
129 shared()->tickSharedTimer(); 201 shared()->tickSharedTimer();
130 } 202 }
131 203
132 void Scheduler::setSharedTimerFiredFunction(void (*function)()) 204 void Scheduler::setSharedTimerFiredFunction(void (*function)())
133 { 205 {
134 m_sharedTimerFunction = function; 206 m_sharedTimerFunction = function;
135 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr); 207 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr);
136 } 208 }
137 209
138 void Scheduler::setSharedTimerFireInterval(double interval) 210 void Scheduler::setSharedTimerFireInterval(double interval)
139 { 211 {
140 blink::Platform::current()->setSharedTimerFireInterval(interval); 212 blink::Platform::current()->setSharedTimerFireInterval(interval);
141 } 213 }
142 214
143 void Scheduler::stopSharedTimer() 215 void Scheduler::stopSharedTimer()
144 { 216 {
145 blink::Platform::current()->stopSharedTimer(); 217 blink::Platform::current()->stopSharedTimer();
146 } 218 }
147 219
148 bool Scheduler::shouldYieldForHighPriorityWork() 220 bool Scheduler::shouldYieldForHighPriorityWork()
149 { 221 {
150 return false; 222 return !m_pendingInputTasks.isEmpty() || !m_pendingCompositorTasks.isEmpty() ;
223 }
224
225 void Scheduler::TracedTask::run()
226 {
227 TRACE_EVENT2("blink", "TracedTask::run",
228 "src_file", m_location.fileName(),
229 "src_func", m_location.functionName());
230 m_task();
151 } 231 }
152 232
153 } // namespace blink 233 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698