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

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

Issue 595023002: Implement idle task scheduling. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: 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
Index: Source/platform/scheduler/Scheduler.cpp
diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp
index c88c4203a6a7e3c9ad6a36fb3f400e6ea1a7bcc0..3ab073242f21fa3df6ea8073c2074a9ac0cb0adb 100644
--- a/Source/platform/scheduler/Scheduler.cpp
+++ b/Source/platform/scheduler/Scheduler.cpp
@@ -10,7 +10,9 @@
#include "platform/ThreadTimers.h"
#include "platform/TraceEvent.h"
#include "public/platform/Platform.h"
+// #include "public/web/WebBeginFrameArgs.h"
rmcilroy 2014/09/24 08:49:18 Sami: I get a checkdeps error when I include this
Sami 2014/09/24 14:00:40 Right, we can't use the web/ headers from platform
rmcilroy 2014/09/29 17:42:57 Done.
#include "wtf/MainThread.h"
+#include "wtf/PassOwnPtr.h"
namespace blink {
@@ -19,32 +21,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 +62,19 @@ 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();
+
m_task.run();
}
- TracedTask m_task;
+private:
+ TracedStandardTask m_task;
};
+
Scheduler* Scheduler::s_sharedScheduler = nullptr;
void Scheduler::initializeOnMainThread()
@@ -118,6 +97,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)
@@ -133,30 +113,36 @@ Scheduler::~Scheduler()
void Scheduler::willBeginFrame(const WebBeginFrameArgs& args)
{
- // TODO: Use frame deadline and interval to schedule idle tasks.
+ m_currentFrameDeadlineSeconds = args.lastFrameTimeMonotonic + args.interval;
rmcilroy 2014/09/24 08:49:18 This is the deadline used by the compositor implem
Sami 2014/09/24 14:00:40 I think there are two different deadlines here: 1)
rmcilroy 2014/09/29 17:42:57 Acknowledged.
}
void Scheduler::didCommitFrameToCompositor()
{
- // TODO: Trigger the frame deadline immediately.
-}
+ if (getSecondsUntilFrameDeadline() > 0) {
Sami 2014/09/24 14:00:40 I don't think we want to run any tasks directly in
rmcilroy 2014/09/29 17:42:57 Sounds like a plan - done.
+ swapQueuesAndRunPendingIdleTasks();
+ }
+ // Reset frame deadline.
+ m_currentFrameDeadlineSeconds = 0;
-void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
-{
- // TODO: send a real allottedTime here.
- m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location));
+ // TODO: Trigger the frame deadline immediately.
}
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(adoptPtr(new 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(adoptPtr(new TracedIdleTask(idleTask, location, traceName)));
+}
+
void Scheduler::postTask(const TraceLocation& location, const Task& task)
{
m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::MainThreadTask"));
@@ -184,6 +170,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 +184,6 @@ void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
m_highPriorityTaskRunnerPosted = true;
}
-void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
-{
- scheduleIdleTask(location, idleTask);
-}
void Scheduler::tickSharedTimer()
{
@@ -228,7 +215,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<OwnPtr<TracedTask> >& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
maybeEnterNormalSchedulerPolicy();
m_pendingTasksMutex.unlock();
return executeHighPriorityTasks(highPriorityTasks);
@@ -241,7 +228,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<OwnPtr<TracedTask> >& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
m_highPriorityTaskRunnerPosted = false;
maybeEnterNormalSchedulerPolicy();
m_pendingTasksMutex.unlock();
@@ -258,12 +245,12 @@ void Scheduler::maybeEnterNormalSchedulerPolicy()
enterSchedulerPolicyLocked(Normal);
}
-bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
+bool Scheduler::executeHighPriorityTasks(Deque<OwnPtr<TracedTask> >& highPriorityTasks)
{
TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks");
int highPriorityTasksExecuted = 0;
while (!highPriorityTasks.isEmpty()) {
- highPriorityTasks.takeFirst().run();
+ highPriorityTasks.takeFirst()->run();
highPriorityTasksExecuted++;
}
@@ -273,6 +260,47 @@ bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
return highPriorityTasksExecuted > 0;
}
+bool Scheduler::swapQueuesAndRunPendingIdleTasks()
+{
+ ASSERT(isMainThread());
+
+ // 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<OwnPtr<TracedTask> >& idleTasks = m_pendingIdleTasks.swapBuffers();
+ m_pendingTasksMutex.unlock();
+ return executeIdleTasks(idleTasks);
+}
picksi1 2014/09/25 08:53:31 I wonder if the added complexity of swapping buffe
rmcilroy 2014/09/29 17:42:57 I've re-worked this completely such that we only e
+
+bool Scheduler::executeIdleTasks(Deque<OwnPtr<TracedTask> >& idleTasks)
+{
+ TRACE_EVENT0("blink", "Scheduler::executeIdleTasks");
+ int idleTasksExecuted = 0;
+ while (!idleTasks.isEmpty() && getSecondsUntilFrameDeadline() > 0) {
+ idleTasks.takeFirst()->run();
+ idleTasksExecuted++;
+
+ // Give high priority a chance to preempt idle tasks.
+ runPendingHighPriorityTasksIfInCompositorPriority();
+ }
+
+ if (!idleTasks.isEmpty()) {
+ repostAllIdleTasks(idleTasks);
+ }
+ ASSERT(idleTasks.isEmpty());
+
+ return idleTasksExecuted > 0;
+}
+
+void Scheduler::repostAllIdleTasks(Deque<OwnPtr<TracedTask> >& idleTasks)
+{
+ Locker<Mutex> lock(m_pendingTasksMutex);
+ while (!idleTasks.isEmpty()) {
+ // TODO: Post at the front to avoid starvation?
+ m_pendingIdleTasks.append(idleTasks.takeFirst());
+ }
+}
+
void Scheduler::sharedTimerAdapter()
{
shared()->tickSharedTimer();
@@ -313,6 +341,12 @@ bool Scheduler::hasPendingHighPriorityWork() const
return acquireLoad(&m_highPriorityTaskCount) != 0;
}
+double Scheduler::getSecondsUntilFrameDeadline() const
+{
+ double delta = m_currentFrameDeadlineSeconds - Platform::current()->monotonicallyIncreasingTime();
+ return (delta > 0) ? delta : 0;
+}
+
picksi1 2014/09/25 08:53:31 Do we actually need the result in seconds? Is it w
rmcilroy 2014/09/29 17:42:57 Reworked this so that we have canRunIdleTask() and
Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const
{
ASSERT(isMainThread());

Powered by Google App Engine
This is Rietveld 408576698