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

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

Issue 595023002: Implement idle task scheduling. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Post idle tasks to the main thread run loop. Created 6 years, 3 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
« no previous file with comments | « Source/platform/scheduler/Scheduler.h ('k') | Source/platform/scheduler/TracedTask.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/scheduler/Scheduler.cpp
diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp
index c88c4203a6a7e3c9ad6a36fb3f400e6ea1a7bcc0..97d84e6ce45a7ef32dd0e2af96311d47796ea094 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,53 @@ 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(const TracedIdleTask& idleTask)
+ : m_idleTask(idleTask)
+ {
+ 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();
+
+ if (scheduler->canRunIdleTask()) {
+ m_idleTask.run();
+ // Run the next idle task if possible.
+ scheduler->maybeExecuteIdleTask();
+ } else {
+ scheduler->repostIdleTask(m_idleTask);
+ }
+ }
+ }
+
+private:
+ TracedIdleTask m_idleTask;
+};
+
+
Scheduler* Scheduler::s_sharedScheduler = nullptr;
void Scheduler::initializeOnMainThread()
@@ -118,6 +129,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 +143,36 @@ Scheduler::~Scheduler()
}
}
-void Scheduler::willBeginFrame(const WebBeginFrameArgs& args)
+void Scheduler::willBeginFrame(double frameDeadlineSeconds)
{
- // TODO: Use frame deadline and interval to schedule idle tasks.
-}
+ m_currentFrameCommitted = false;
+ m_currentFrameDeadlineSeconds = frameDeadlineSeconds;
-void Scheduler::didCommitFrameToCompositor()
-{
- // TODO: Trigger the frame deadline immediately.
+ // TODO: Schedule a deferred task here to run idle work if didCommitFrameToCompositor never get's called
}
-void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
+void Scheduler::didCommitFrameToCompositor()
{
- // TODO: send a real allottedTime here.
- m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location));
+ m_currentFrameCommitted = true;
+ maybeExecuteIdleTask();
}
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 +200,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,10 +214,6 @@ void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
m_highPriorityTaskRunnerPosted = true;
}
-void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
-{
- scheduleIdleTask(location, idleTask);
-}
void Scheduler::tickSharedTimer()
{
@@ -228,7 +245,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 +258,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 +275,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;
@@ -273,6 +290,26 @@ bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
return highPriorityTasksExecuted > 0;
}
+bool Scheduler::maybeExecuteIdleTask()
+{
+ TRACE_EVENT0("blink", "Scheduler::maybeExecuteIdleTask");
+ if (canRunIdleTask()) {
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ if (!m_pendingIdleTasks.isEmpty()) {
+ m_mainThread->postTask(new MainThreadPendingIdleTaskRunner(m_pendingIdleTasks.takeFirst()));
+ return true;
+ }
+ }
picksi1 2014/09/30 09:13:51 Is this function correctly named? It isn't actuall
rmcilroy 2014/09/30 09:56:19 Yes it's tricky to name - I originally had maybeSc
picksi1 2014/09/30 12:34:00 maybePostMainThreadPendingHighPriorityTaskRunner()
+ return false;
+}
+
+void Scheduler::repostIdleTask(const TracedIdleTask& idleTask)
+{
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ // Post at the front since the task didn't get a chance to run.
+ m_pendingIdleTasks.prepend(idleTask);
+}
+
picksi1 2014/09/30 09:13:51 Should this be called repostAtFront (etc) or somet
rmcilroy 2014/09/30 09:56:19 Done.
void Scheduler::sharedTimerAdapter()
{
shared()->tickSharedTimer();
@@ -313,6 +350,16 @@ bool Scheduler::hasPendingHighPriorityWork() const
return acquireLoad(&m_highPriorityTaskCount) != 0;
}
+double Scheduler::currentFrameDeadlineSeconds() const
+{
+ return m_currentFrameDeadlineSeconds;
+}
+
+bool Scheduler::canRunIdleTask() const
+{
+ return m_currentFrameCommitted && (m_currentFrameDeadlineSeconds > Platform::current()->monotonicallyIncreasingTime());
+}
+
Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const
{
ASSERT(isMainThread());
« no previous file with comments | « Source/platform/scheduler/Scheduler.h ('k') | Source/platform/scheduler/TracedTask.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698