Chromium Code Reviews| Index: Source/platform/scheduler/Scheduler.cpp |
| diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp |
| index 4a447721f58921b8fe0500568ed583f76288b5c8..2276544f923631a5c2916f02898b31c01d0e854e 100644 |
| --- a/Source/platform/scheduler/Scheduler.cpp |
| +++ b/Source/platform/scheduler/Scheduler.cpp |
| @@ -18,6 +18,9 @@ namespace blink { |
| 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 { |
| @@ -63,6 +66,8 @@ public: |
| ASSERT(scheduler); |
| if (!scheduler) |
| return; |
| + // NOTE we must unconditionally execute high priority tasks here, since if we're not in CompositorPriority |
| + // mode, then this is the only place where high priority tasks will be executed. |
| scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting(); |
| } |
| }; |
| @@ -86,7 +91,7 @@ public: |
| // FIXME: This check should't be necessary, tasks should not outlive blink. |
| ASSERT(scheduler); |
| if (scheduler) |
| - Scheduler::shared()->swapQueuesAndRunPendingTasks(); |
| + Scheduler::shared()->runPendingHighPriorityTasksIfInCompositorPriority(); |
| m_task.run(); |
| } |
| @@ -116,6 +121,8 @@ Scheduler::Scheduler() |
| , m_mainThread(blink::Platform::current()->currentThread()) |
| , m_highPriorityTaskCount(0) |
| , m_highPriorityTaskRunnerPosted(false) |
| + , m_schedulerPolicy(Normal) |
| + , m_compositorPriorityPolicyEndTimeSeconds(0) |
| { |
| } |
| @@ -153,6 +160,7 @@ void Scheduler::postInputTask(const TraceLocation& location, const Task& task) |
| m_pendingHighPriorityTasks.append(TracedTask(task, location)); |
| atomicIncrement(&m_highPriorityTaskCount); |
| maybePostMainThreadPendingHighPriorityTaskRunner(); |
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount); |
| } |
| void Scheduler::postCompositorTask(const TraceLocation& location, const Task& task) |
| @@ -161,6 +169,7 @@ void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta |
| m_pendingHighPriorityTasks.append(TracedTask(task, location)); |
| atomicIncrement(&m_highPriorityTaskCount); |
| maybePostMainThreadPendingHighPriorityTaskRunner(); |
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount); |
| } |
| void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() |
| @@ -182,13 +191,22 @@ void Scheduler::tickSharedTimer() |
| TRACE_EVENT0("blink", "Scheduler::tickSharedTimer"); |
| // Run any high priority tasks that are queued up, otherwise the blink timers will yield immediately. |
| - bool workDone = swapQueuesAndRunPendingTasks(); |
| + bool workDone = runPendingHighPriorityTasksIfInCompositorPriority(); |
| 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. |
| if (!workDone) |
| - swapQueuesAndRunPendingTasks(); |
| + runPendingHighPriorityTasksIfInCompositorPriority(); |
| +} |
| + |
| +bool Scheduler::runPendingHighPriorityTasksIfInCompositorPriority() |
| +{ |
| + ASSERT(isMainThread()); |
| + if (schedulerPolicy() != CompositorPriority) |
| + return false; |
| + |
| + return swapQueuesAndRunPendingTasks(); |
| } |
| bool Scheduler::swapQueuesAndRunPendingTasks() |
| @@ -199,6 +217,7 @@ bool Scheduler::swapQueuesAndRunPendingTasks() |
| // 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(); |
| + maybeEnterNormalschedulerPolicy(); |
| m_pendingTasksMutex.unlock(); |
| return executeHighPriorityTasks(highPriorityTasks); |
| } |
| @@ -212,10 +231,20 @@ void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting() |
| m_pendingTasksMutex.lock(); |
| Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers(); |
| m_highPriorityTaskRunnerPosted = false; |
| + maybeEnterNormalschedulerPolicy(); |
| m_pendingTasksMutex.unlock(); |
| executeHighPriorityTasks(highPriorityTasks); |
| } |
| +void Scheduler::maybeEnterNormalschedulerPolicy() |
| +{ |
| + ASSERT(m_pendingTasksMutex.locked()); |
|
Sami
2014/09/11 11:32:18
Also add ASSERT(isMainThread());
alexclarke
2014/09/11 11:52:05
Done.
|
| + |
| + // Go back to the normal scheduler policy if enough time has elapsed. |
| + if (schedulerPolicy() == CompositorPriority && Platform::current()->monotonicallyIncreasingTime() > m_compositorPriorityPolicyEndTimeSeconds) |
| + enterSchedulerPolicy(Normal); |
| +} |
| + |
| bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks) |
| { |
| TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks"); |
| @@ -227,6 +256,7 @@ bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks) |
| int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPriorityTasksExecuted); |
| ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0); |
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount); |
| return highPriorityTasksExecuted > 0; |
| } |
| @@ -253,6 +283,10 @@ void Scheduler::stopSharedTimer() |
| bool Scheduler::shouldYieldForHighPriorityWork() const |
| { |
| + // It's only worthwhile yielding in CompositorPriority mode. |
| + if (schedulerPolicy() != CompositorPriority) |
| + return false; |
| + |
| return hasPendingHighPriorityWork(); |
| } |
| @@ -266,6 +300,24 @@ bool Scheduler::hasPendingHighPriorityWork() const |
| return acquireLoad(&m_highPriorityTaskCount) != 0; |
| } |
| +Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const |
| +{ |
| + ASSERT(isMainThread()); |
| + // It's important not to miss the transition from normal to low latency mode, otherwise we're likely to |
| + // delay the processing of input tasks. Since that transition is triggered by a different thread, we |
| + // need either a lock or a memory barrier, and the memory barrier is probably cheaper. |
| + return static_cast<SchedulerPolicy>(acquireLoad(&m_schedulerPolicy)); |
| +} |
| + |
| +void Scheduler::enterSchedulerPolicy(SchedulerPolicy SchedulerPolicy) |
|
Sami
2014/09/11 11:32:18
scheduler shouldn't be capitalized here.
alexclarke
2014/09/11 11:52:05
Done.
|
| +{ |
| + if (SchedulerPolicy == CompositorPriority) |
| + m_compositorPriorityPolicyEndTimeSeconds = Platform::current()->monotonicallyIncreasingTime() + kLowSchedulerPolicyAfterTouchTimeSeconds; |
|
Sami
2014/09/11 11:32:18
We need to grab m_pendingTasksMutex here, right?
alexclarke
2014/09/11 11:52:04
Done.
|
| + |
| + releaseStore(&m_schedulerPolicy, SchedulerPolicy); |
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "SchedulerPolicy", SchedulerPolicy); |
| +} |
| + |
| void Scheduler::TracedTask::run() |
| { |
| TRACE_EVENT2("blink", "TracedTask::run", |