| Index: Source/platform/scheduler/Scheduler.cpp
|
| diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp
|
| index 4a447721f58921b8fe0500568ed583f76288b5c8..abba6b776a12d8359fb521ab171795994885dbea 100644
|
| --- a/Source/platform/scheduler/Scheduler.cpp
|
| +++ b/Source/platform/scheduler/Scheduler.cpp
|
| @@ -16,6 +16,8 @@
|
|
|
| namespace blink {
|
|
|
| +double Scheduler::s_lowLatencyModeAfterTouchTimeSeconds = 0.1;
|
| +
|
| namespace {
|
|
|
| // Can be created from any thread.
|
| @@ -63,6 +65,7 @@ public:
|
| ASSERT(scheduler);
|
| if (!scheduler)
|
| return;
|
| + // NOTE if we're not in low latency mode, this is the only place they will actually get executed.
|
| scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting();
|
| }
|
| };
|
| @@ -86,7 +89,7 @@ public:
|
| // FIXME: This check should't be necessary, tasks should not outlive blink.
|
| ASSERT(scheduler);
|
| if (scheduler)
|
| - Scheduler::shared()->swapQueuesAndRunPendingTasks();
|
| + Scheduler::shared()->runPendingHighPrioirtyTasksIfInLowLatencyMode();
|
| m_task.run();
|
| }
|
|
|
| @@ -116,6 +119,8 @@ Scheduler::Scheduler()
|
| , m_mainThread(blink::Platform::current()->currentThread())
|
| , m_highPriorityTaskCount(0)
|
| , m_highPriorityTaskRunnerPosted(false)
|
| + , m_latencyMode(Normal)
|
| + , m_lowLatencyModeEndTimeSeconds(0)
|
| {
|
| }
|
|
|
| @@ -150,9 +155,11 @@ void Scheduler::postTask(const TraceLocation& location, const Task& task)
|
| void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
|
| {
|
| Locker<Mutex> lock(m_pendingTasksMutex);
|
| + setLatencyMode(LowLatency);
|
| 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 +168,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 +190,21 @@ 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 = runPendingHighPrioirtyTasksIfInLowLatencyMode();
|
| 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();
|
| + runPendingHighPrioirtyTasksIfInLowLatencyMode();
|
| +}
|
| +
|
| +bool Scheduler::runPendingHighPrioirtyTasksIfInLowLatencyMode()
|
| +{
|
| + if (latencyMode() != LowLatency)
|
| + return false;
|
| +
|
| + return swapQueuesAndRunPendingTasks();
|
| }
|
|
|
| bool Scheduler::swapQueuesAndRunPendingTasks()
|
| @@ -227,6 +243,11 @@ 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);
|
| +
|
| + // Go back to normal latency mode if enough time has elapsed.
|
| + if (latencyMode() == LowLatency && Platform::current()->monotonicallyIncreasingTime() > m_lowLatencyModeEndTimeSeconds)
|
| + setLatencyMode(Normal);
|
| return highPriorityTasksExecuted > 0;
|
| }
|
|
|
| @@ -253,6 +274,10 @@ void Scheduler::stopSharedTimer()
|
|
|
| bool Scheduler::shouldYieldForHighPriorityWork() const
|
| {
|
| + // It's only worthwhile yielding in low latency mode.
|
| + if (latencyMode() != LowLatency)
|
| + return false;
|
| +
|
| return hasPendingHighPriorityWork();
|
| }
|
|
|
| @@ -266,6 +291,24 @@ bool Scheduler::hasPendingHighPriorityWork() const
|
| return acquireLoad(&m_highPriorityTaskCount) != 0;
|
| }
|
|
|
| +Scheduler::LatencyMode Scheduler::latencyMode() 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<LatencyMode>(acquireLoad(&m_latencyMode));
|
| +}
|
| +
|
| +void Scheduler::setLatencyMode(LatencyMode latencyMode)
|
| +{
|
| + if (latencyMode == LowLatency)
|
| + m_lowLatencyModeEndTimeSeconds = Platform::current()->monotonicallyIncreasingTime() + s_lowLatencyModeAfterTouchTimeSeconds;
|
| +
|
| + releaseStore(&m_latencyMode, latencyMode);
|
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "LatencyMode", latencyMode);
|
| +}
|
| +
|
| void Scheduler::TracedTask::run()
|
| {
|
| TRACE_EVENT2("blink", "TracedTask::run",
|
|
|