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

Unified Diff: Source/platform/scheduler/Scheduler.cpp

Issue 595023002: Implement idle task scheduling. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix comment Created 6 years, 2 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 c88c4203a6a7e3c9ad6a36fb3f400e6ea1a7bcc0..218fba7f99afc324cbec7555908e241905852cea 100644
--- a/Source/platform/scheduler/Scheduler.cpp
+++ b/Source/platform/scheduler/Scheduler.cpp
@@ -19,32 +19,6 @@ namespace {
// The time we should stay in CompositorPriority mode for, after a touch event.
double kLowSchedulerPolicyAfterTouchTimeSeconds = 0.1;
-// Can be created from any thread.
-// Note if the scheduler gets shutdown, this may be run after.
-class MainThreadIdleTaskAdapter : public WebThread::Task {
-public:
- MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs, const TraceLocation& location)
- : m_idleTask(idleTask)
- , m_allottedTimeMs(allottedTimeMs)
- , m_location(location)
- {
- }
-
- // WebThread::Task implementation.
- virtual void run() OVERRIDE
- {
- TRACE_EVENT2("blink", "MainThreadIdleTaskAdapter::run",
- "src_file", m_location.fileName(),
- "src_func", m_location.functionName());
- m_idleTask(m_allottedTimeMs);
- }
-
-private:
- Scheduler::IdleTask m_idleTask;
- double m_allottedTimeMs;
- TraceLocation m_location;
-};
-
} // namespace
// Typically only created from compositor or render threads.
@@ -86,16 +60,45 @@ public:
virtual void run() OVERRIDE
{
Scheduler* scheduler = Scheduler::shared();
- // FIXME: This check should't be necessary, tasks should not outlive blink.
+ // FIXME: This check shouldn't be necessary, tasks should not outlive blink.
ASSERT(scheduler);
if (scheduler)
- Scheduler::shared()->runPendingHighPriorityTasksIfInCompositorPriority();
+ scheduler->runPendingHighPriorityTasksIfInCompositorPriority();
+
m_task.run();
}
- TracedTask m_task;
+private:
+ TracedStandardTask m_task;
};
+
+// Can be created from any thread.
+// Note if the scheduler gets shutdown, this may be run after.
+class Scheduler::MainThreadPendingIdleTaskRunner : public WebThread::Task {
+public:
+ MainThreadPendingIdleTaskRunner()
+ {
+ ASSERT(Scheduler::shared());
+ }
+
+ // WebThread::Task implementation.
+ virtual void run() OVERRIDE
+ {
+ Scheduler* scheduler = Scheduler::shared();
+ // FIXME: This check shouldn't be necessary, tasks should not outlive blink.
+ ASSERT(scheduler);
+ if (scheduler) {
+ scheduler->runPendingHighPriorityTasksIfInCompositorPriority();
jochen (gone - plz use gerrit) 2014/10/06 07:33:19 if we're in compositor priority, why run an idle t
Sami 2014/10/06 09:48:30 Right, this call could be removed from here and we
rmcilroy 2014/10/06 11:29:42 The original reason I had this here was in case we
+ scheduler->maybeRunPendingIdleTask();
+ // If possible, run the next idle task by reposting on the main thread.
+ scheduler->maybePostMainThreadPendingIdleTask();
+ }
+ }
+
+};
+
+
Scheduler* Scheduler::s_sharedScheduler = nullptr;
void Scheduler::initializeOnMainThread()
@@ -118,6 +121,7 @@ Scheduler::Scheduler()
: m_sharedTimerFunction(nullptr)
, m_mainThread(blink::Platform::current()->currentThread())
, m_compositorPriorityPolicyEndTimeSeconds(0)
+ , m_currentFrameDeadlineSeconds(0)
, m_highPriorityTaskCount(0)
, m_highPriorityTaskRunnerPosted(false)
, m_schedulerPolicy(Normal)
@@ -131,32 +135,37 @@ Scheduler::~Scheduler()
}
}
-void Scheduler::willBeginFrame(const WebBeginFrameArgs& args)
+void Scheduler::willBeginFrame(double frameDeadlineSeconds)
{
- // TODO: Use frame deadline and interval to schedule idle tasks.
+ ASSERT(isMainThread());
+ m_currentFrameCommitted = false;
+ m_currentFrameDeadlineSeconds = frameDeadlineSeconds;
+ // TODO: Schedule a deferred task here to run idle work if didCommitFrameToCompositor never get's called
}
void Scheduler::didCommitFrameToCompositor()
{
- // TODO: Trigger the frame deadline immediately.
-}
-
-void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
-{
- // TODO: send a real allottedTime here.
- m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location));
+ ASSERT(isMainThread());
+ m_currentFrameCommitted = true;
+ maybePostMainThreadPendingIdleTask();
}
void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, const Task& task, const char* traceName)
{
Locker<Mutex> lock(m_pendingTasksMutex);
- m_pendingHighPriorityTasks.append(TracedTask(task, location, traceName));
+ m_pendingHighPriorityTasks.append(TracedStandardTask(task, location, traceName));
atomicIncrement(&m_highPriorityTaskCount);
maybePostMainThreadPendingHighPriorityTaskRunner();
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
}
+void Scheduler::postIdleTaskInternal(const TraceLocation& location, const IdleTask& idleTask, const char* traceName)
+{
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ m_pendingIdleTasks.append(TracedIdleTask(idleTask, location, traceName));
+}
+
void Scheduler::postTask(const TraceLocation& location, const Task& task)
{
m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::MainThreadTask"));
@@ -184,6 +193,11 @@ void Scheduler::postIpcTask(const TraceLocation& location, const Task& task)
m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::IpcTask"));
}
+void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
+{
+ postIdleTaskInternal(location, idleTask, "Scheduler::IdleTask");
+}
+
void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
{
ASSERT(m_pendingTasksMutex.locked());
@@ -193,9 +207,18 @@ void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
m_highPriorityTaskRunnerPosted = true;
}
-void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
+bool Scheduler::maybePostMainThreadPendingIdleTask()
{
- scheduleIdleTask(location, idleTask);
+ ASSERT(isMainThread());
+ TRACE_EVENT0("blink", "Scheduler::maybePostMainThreadPendingIdleTask");
+ if (canRunIdleTask()) {
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ if (!m_pendingIdleTasks.isEmpty()) {
+ m_mainThread->postTask(new MainThreadPendingIdleTaskRunner());
+ return true;
+ }
+ }
+ return false;
}
void Scheduler::tickSharedTimer()
@@ -221,6 +244,23 @@ bool Scheduler::runPendingHighPriorityTasksIfInCompositorPriority()
return swapQueuesAndRunPendingTasks();
}
+bool Scheduler::maybeRunPendingIdleTask()
+{
+ ASSERT(isMainThread());
+ if (!canRunIdleTask())
+ return false;
+
+ takeFirstPendingIdleTask().run();
+ return true;
+}
+
+TracedIdleTask Scheduler::takeFirstPendingIdleTask()
+{
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ ASSERT(!m_pendingIdleTasks.isEmpty());
+ return m_pendingIdleTasks.takeFirst();
+}
+
bool Scheduler::swapQueuesAndRunPendingTasks()
{
ASSERT(isMainThread());
@@ -228,7 +268,7 @@ bool Scheduler::swapQueuesAndRunPendingTasks()
// These locks guard against another thread posting input or compositor tasks while we swap the buffers.
// One the buffers have been swapped we can safely access the returned deque without having to lock.
m_pendingTasksMutex.lock();
- Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
+ Deque<TracedStandardTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
maybeEnterNormalSchedulerPolicy();
m_pendingTasksMutex.unlock();
return executeHighPriorityTasks(highPriorityTasks);
@@ -241,7 +281,7 @@ void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting()
// These locks guard against another thread posting input or compositor tasks while we swap the buffers.
// One the buffers have been swapped we can safely access the returned deque without having to lock.
m_pendingTasksMutex.lock();
- Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
+ Deque<TracedStandardTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
m_highPriorityTaskRunnerPosted = false;
maybeEnterNormalSchedulerPolicy();
m_pendingTasksMutex.unlock();
@@ -258,7 +298,7 @@ void Scheduler::maybeEnterNormalSchedulerPolicy()
enterSchedulerPolicyLocked(Normal);
}
-bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
+bool Scheduler::executeHighPriorityTasks(Deque<TracedStandardTask>& highPriorityTasks)
{
TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks");
int highPriorityTasksExecuted = 0;
@@ -313,6 +353,19 @@ bool Scheduler::hasPendingHighPriorityWork() const
return acquireLoad(&m_highPriorityTaskCount) != 0;
}
+double Scheduler::currentFrameDeadlineForIdleTasks() const
+{
+ ASSERT(isMainThread());
+ // TODO: Make idle time more fine-grain chunks when in Compositor priority.
+ return m_currentFrameDeadlineSeconds;
+}
+
+bool Scheduler::canRunIdleTask() const
+{
+ ASSERT(isMainThread());
+ return m_currentFrameCommitted && (m_currentFrameDeadlineSeconds > Platform::current()->monotonicallyIncreasingTime());
Sami 2014/10/06 09:48:30 To jochen's point, should we be checking !shouldYi
rmcilroy 2014/10/06 11:29:42 Done.
+}
+
Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const
{
ASSERT(isMainThread());

Powered by Google App Engine
This is Rietveld 408576698