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

Unified 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: Adding wtf/DoubleBufferedDeque.h to git 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 side-by-side diff with in-line comments
Download patch
Index: Source/platform/scheduler/Scheduler.cpp
diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp
index 61ae7aef1d486bd618417a2d2d62c14c08db06bc..5bfe8b34c7a9acd128fb8abb5a59f4081083d0e1 100644
--- a/Source/platform/scheduler/Scheduler.cpp
+++ b/Source/platform/scheduler/Scheduler.cpp
@@ -5,59 +5,103 @@
#include "config.h"
#include "platform/scheduler/Scheduler.h"
+#include "platform/PlatformThreadData.h"
#include "platform/Task.h"
+#include "platform/ThreadTimers.h"
#include "platform/TraceEvent.h"
-#include "platform/TraceLocation.h"
#include "public/platform/Platform.h"
-#include "public/platform/WebThread.h"
+#include "wtf/ThreadingPrimitives.h"
namespace blink {
namespace {
-class MainThreadTaskAdapter : public blink::WebThread::Task {
+class MainThreadIdleTaskAdapter : public WebThread::Task {
eseidel 2014/08/11 17:02:36 Might add a comment to note that this can be creat
alexclarke 2014/08/12 11:37:02 Done.
public:
- explicit MainThreadTaskAdapter(const TraceLocation& location, const Scheduler::Task& task)
- : m_location(location)
- , m_task(task)
+ MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs, const TraceLocation& location)
+ : m_idleTask(idleTask)
+ , m_allottedTimeMs(allottedTimeMs)
eseidel 2014/08/11 17:02:36 Might have called this timeout or maxDuration, but
alexclarke 2014/08/12 11:37:02 Acknowledged.
+ , m_location(location)
{
eseidel 2014/08/11 17:02:36 If this can't be created from any thread, we shoul
alexclarke 2014/08/12 11:37:02 It can be called from any thread.
}
// WebThread::Task implementation.
virtual void run() OVERRIDE
{
- TRACE_EVENT2("blink", "MainThreadTaskAdapter::run",
+ TRACE_EVENT2("blink", "MainThreadIdleTaskAdapter::run",
"src_file", m_location.fileName(),
"src_func", m_location.functionName());
- m_task();
+ m_idleTask(m_allottedTimeMs);
}
private:
- const TraceLocation m_location;
- Scheduler::Task m_task;
+ Scheduler::IdleTask m_idleTask;
+ double m_allottedTimeMs;
+ TraceLocation m_location;
};
-class MainThreadIdleTaskAdapter : public blink::WebThread::Task {
+} // namespace
+
+class Scheduler::MainThreadPendingHighPriorityTaskRunner : public WebThread::Task {
public:
- MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs)
- : m_idleTask(idleTask)
- , m_allottedTimeMs(allottedTimeMs)
+ MainThreadPendingHighPriorityTaskRunner()
+ {
+ ASSERT(Scheduler::shared());
+ Scheduler::shared()->incrementMainThreadTaskRunnerCount();
+ }
+
+ ~MainThreadPendingHighPriorityTaskRunner()
{
+ Scheduler* scheduler = Scheduler::shared();
+ if (!scheduler)
+ return;
+ Scheduler::shared()->decrementMainThreadTaskRunnerCount();
}
// WebThread::Task implementation.
virtual void run() OVERRIDE
{
- TRACE_EVENT1("blink", "MainThreadIdleTaskAdapter::run", "allottedTime", m_allottedTimeMs);
- m_idleTask(m_allottedTimeMs);
+ Scheduler* scheduler = Scheduler::shared();
eseidel 2014/08/11 17:02:36 When can this happen? This feels like it should b
alexclarke 2014/08/12 11:37:02 Because a posted MainThreadPendingHighPriorityTask
+ if (!scheduler)
+ return;
+ scheduler->runHighPriorityTasks();
}
-
-private:
- Scheduler::IdleTask m_idleTask;
- double m_allottedTimeMs;
};
-}
+class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task {
+public:
+ MainThreadPendingTaskRunner(
+ const Scheduler::Task& task, const TraceLocation& location)
+ : m_task(task)
+ , m_location(location)
+ {
+ ASSERT(Scheduler::shared());
+ Scheduler::shared()->incrementMainThreadTaskRunnerCount();
+ }
+
+ ~MainThreadPendingTaskRunner()
+ {
+ Scheduler* scheduler = Scheduler::shared();
+ if (!scheduler)
eseidel 2014/08/11 17:02:36 Feels like we should flush the tasks before shut-d
alexclarke 2014/08/12 11:37:03 We flush what we can (high priority tasks) but sin
+ return;
+ Scheduler::shared()->decrementMainThreadTaskRunnerCount();
+ }
+
+ // WebThread::Task implementation.
+ virtual void run() OVERRIDE
+ {
+ TRACE_EVENT2("blink", "MainThreadPendingTaskRunner::run",
eseidel 2014/08/11 17:02:36 Currious there is a trace here but not the other?
alexclarke 2014/08/12 11:37:02 Because Scheduler::TracedTask::run() does that for
+ "src_file", m_location.fileName(),
+ "src_func", m_location.functionName());
+ Scheduler* scheduler = Scheduler::shared();
+ if (scheduler)
+ Scheduler::shared()->runHighPriorityTasks();
+ m_task();
eseidel 2014/08/11 17:02:36 Why would we want to run this if !scheduler?
alexclarke 2014/08/12 11:37:02 Because this is the existing behaviour but we've a
+ }
+
+ Scheduler::Task m_task;
+ TraceLocation m_location;
+};
Scheduler* Scheduler::s_sharedScheduler = nullptr;
@@ -80,48 +124,103 @@ Scheduler* Scheduler::shared()
Scheduler::Scheduler()
: m_mainThread(blink::Platform::current()->currentThread())
, m_sharedTimerFunction(nullptr)
+ , m_mainThreadTaskRunnerCount(0)
+ , m_highPriotityTaskCount(0)
{
}
Scheduler::~Scheduler()
{
+ while (shouldYieldForHighPriorityWork()) {
+ runHighPriorityTasks();
+ }
}
-void Scheduler::scheduleTask(const TraceLocation& location, const Task& task)
-{
- m_mainThread->postTask(new MainThreadTaskAdapter(location, task));
-}
-
-void Scheduler::scheduleIdleTask(const IdleTask& idleTask)
+void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
{
// TODO: send a real allottedTime here.
- m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0));
+ m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location));
}
void Scheduler::postTask(const TraceLocation& location, const Task& task)
{
- scheduleTask(location, task);
+ m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location));
}
void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
{
- scheduleTask(location, task);
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ m_pendingInputTasks.append(TracedTask(task, location));
+ atomicIncrement(&m_highPriotityTaskCount);
+ maybePostMainThreadPendingHighPriorityTaskRunner();
}
void Scheduler::postCompositorTask(const TraceLocation& location, const Task& task)
{
- scheduleTask(location, task);
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ m_pendingCompositorTasks.append(TracedTask(task, location));
+ atomicIncrement(&m_highPriotityTaskCount);
+ maybePostMainThreadPendingHighPriorityTaskRunner();
}
-void Scheduler::postIdleTask(const IdleTask& idleTask)
+void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
{
- scheduleIdleTask(idleTask);
+ scheduleIdleTask(location, idleTask);
}
void Scheduler::tickSharedTimer()
{
TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
+
+ // Run any high priority tasks that are queued up, otherwise the blink timers will yield immediately.
+ runHighPriorityTasks();
m_sharedTimerFunction();
+
+ // The blink timers may have just yielded, so run any high priority tasks that where queued up
+ // while the blink timers were executing.
+ runHighPriorityTasks();
+}
+
+void Scheduler::runHighPriorityTasks()
+{
+ TRACE_EVENT0("blink", "Scheduler::runHighPriorityTasks");
+
+ m_pendingTasksMutex.lock();
+ Deque<TracedTask>& inputTasks = m_pendingInputTasks.swapBuffers();
eseidel 2014/08/11 17:02:36 This is kinda neat.
alexclarke 2014/08/12 11:37:02 Acknowledged.
+ Deque<TracedTask>& compositorTasks = m_pendingCompositorTasks.swapBuffers();
+ m_pendingTasksMutex.unlock();
+
+ for (;;) {
+ if (!inputTasks.isEmpty()) {
+ inputTasks.takeFirst().run();
+ atomicDecrement(&m_highPriotityTaskCount);
+ continue;
+ }
+
+ if (compositorTasks.isEmpty())
+ break;
+ compositorTasks.takeFirst().run();
+ atomicDecrement(&m_highPriotityTaskCount);
+ }
+}
+
+void Scheduler::incrementMainThreadTaskRunnerCount()
+{
+ atomicIncrement(&m_mainThreadTaskRunnerCount);
+}
+
+void Scheduler::decrementMainThreadTaskRunnerCount()
+{
+ atomicDecrement(&m_mainThreadTaskRunnerCount);
+}
+
+void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
+{
+ // Only post a task if there isn't a task already in flight.
+ if (acquireLoad(&m_mainThreadTaskRunnerCount))
+ return;
+
+ m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner());
}
void Scheduler::sharedTimerAdapter()
@@ -147,7 +246,15 @@ void Scheduler::stopSharedTimer()
bool Scheduler::shouldYieldForHighPriorityWork()
{
- return false;
+ return acquireLoad(&m_highPriotityTaskCount) != 0;
eseidel 2014/08/11 17:02:36 Is it concerning that this is being called often?
alexclarke 2014/08/12 11:37:02 Ultimately if we refactor all the blink timers we
+}
+
+void Scheduler::TracedTask::run()
+{
+ TRACE_EVENT2("blink", "TracedTask::run",
+ "src_file", m_location.fileName(),
+ "src_func", m_location.functionName());
+ m_task();
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698