Pause dart microtasks while UI thread is processing frame workloads
diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index e763696..00c12f0 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc
@@ -325,7 +325,7 @@ std::make_unique<ShellTestVsyncWaiter>(task_runners, vsync_clock)); } else { return static_cast<std::unique_ptr<VsyncWaiter>>( - std::make_unique<VsyncWaiterFallback>(task_runners)); + std::make_unique<VsyncWaiterFallback>(task_runners, true)); } };
diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 5a21085..d31c138 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc
@@ -1335,6 +1335,7 @@ }; AddNativeCallback("NativeReportTimingsCallback", CREATE_NATIVE_ENTRY(nativeTimingCallback)); + ASSERT_TRUE(configuration.IsValid()); RunEngine(shell.get(), std::move(configuration)); for (int i = 0; i < 10; i += 1) {
diff --git a/shell/common/vsync_waiter.cc b/shell/common/vsync_waiter.cc index 886f672..40ced72 100644 --- a/shell/common/vsync_waiter.cc +++ b/shell/common/vsync_waiter.cc
@@ -91,7 +91,8 @@ } void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time, - fml::TimePoint frame_target_time) { + fml::TimePoint frame_target_time, + bool pause_secondary_tasks) { Callback callback; std::vector<fml::closure> secondary_callbacks; @@ -114,6 +115,9 @@ if (callback) { auto flow_identifier = fml::tracing::TraceNonce(); + if (pause_secondary_tasks) { + PauseDartMicroTasks(); + } // The base trace ensures that flows have a root to begin from if one does // not exist. The trace viewer will ignore traces that have no base event @@ -124,11 +128,15 @@ TRACE_FLOW_BEGIN("flutter", kVsyncFlowName, flow_identifier); task_runners_.GetUITaskRunner()->PostTaskForTime( - [callback, flow_identifier, frame_start_time, frame_target_time]() { + [this, callback, flow_identifier, frame_start_time, frame_target_time, + pause_secondary_tasks]() { FML_TRACE_EVENT("flutter", kVsyncTraceName, "StartTime", frame_start_time, "TargetTime", frame_target_time); callback(frame_start_time, frame_target_time); TRACE_FLOW_END("flutter", kVsyncFlowName, flow_identifier); + if (pause_secondary_tasks) { + ResumeDartMicroTasks(); + } }, frame_start_time); } @@ -139,4 +147,16 @@ } } +void VsyncWaiter::PauseDartMicroTasks() { + auto ui_task_queue_id = task_runners_.GetUITaskRunner()->GetTaskQueueId(); + auto task_queues = fml::MessageLoopTaskQueues::GetInstance(); + task_queues->PauseSecondarySource(ui_task_queue_id); +} + +void VsyncWaiter::ResumeDartMicroTasks() { + auto ui_task_queue_id = task_runners_.GetUITaskRunner()->GetTaskQueueId(); + auto task_queues = fml::MessageLoopTaskQueues::GetInstance(); + task_queues->ResumeSecondarySource(ui_task_queue_id); +} + } // namespace flutter
diff --git a/shell/common/vsync_waiter.h b/shell/common/vsync_waiter.h index 0843990..d593c70 100644 --- a/shell/common/vsync_waiter.h +++ b/shell/common/vsync_waiter.h
@@ -49,13 +49,17 @@ virtual void AwaitVSync() = 0; void FireCallback(fml::TimePoint frame_start_time, - fml::TimePoint frame_target_time); + fml::TimePoint frame_target_time, + bool pause_secondary_tasks = true); private: std::mutex callback_mutex_; Callback callback_; std::unordered_map<uintptr_t, fml::closure> secondary_callbacks_; + void PauseDartMicroTasks(); + void ResumeDartMicroTasks(); + FML_DISALLOW_COPY_AND_ASSIGN(VsyncWaiter); };
diff --git a/shell/common/vsync_waiter_fallback.cc b/shell/common/vsync_waiter_fallback.cc index 514dc02..8bf51c5 100644 --- a/shell/common/vsync_waiter_fallback.cc +++ b/shell/common/vsync_waiter_fallback.cc
@@ -21,8 +21,11 @@ } // namespace -VsyncWaiterFallback::VsyncWaiterFallback(TaskRunners task_runners) - : VsyncWaiter(std::move(task_runners)), phase_(fml::TimePoint::Now()) {} +VsyncWaiterFallback::VsyncWaiterFallback(TaskRunners task_runners, + bool for_testing) + : VsyncWaiter(std::move(task_runners)), + phase_(fml::TimePoint::Now()), + for_testing_(for_testing) {} VsyncWaiterFallback::~VsyncWaiterFallback() = default; @@ -36,7 +39,7 @@ auto next = SnapToNextTick(fml::TimePoint::Now(), phase_, kSingleFrameInterval); - FireCallback(next, next + kSingleFrameInterval); + FireCallback(next, next + kSingleFrameInterval, !for_testing_); } } // namespace flutter
diff --git a/shell/common/vsync_waiter_fallback.h b/shell/common/vsync_waiter_fallback.h index 5226dda..b2ae63f 100644 --- a/shell/common/vsync_waiter_fallback.h +++ b/shell/common/vsync_waiter_fallback.h
@@ -15,12 +15,14 @@ /// A |VsyncWaiter| that will fire at 60 fps irrespective of the vsync. class VsyncWaiterFallback final : public VsyncWaiter { public: - VsyncWaiterFallback(TaskRunners task_runners); + explicit VsyncWaiterFallback(TaskRunners task_runners, + bool for_testing = false); ~VsyncWaiterFallback() override; private: fml::TimePoint phase_; + const bool for_testing_; // |VsyncWaiter| void AwaitVSync() override;
diff --git a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm index d71ecd7d7..37d9b23 100644 --- a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm +++ b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm
@@ -23,7 +23,8 @@ callback:std::bind(&VsyncWaiterIOS::FireCallback, this, std::placeholders::_1, - std::placeholders::_2)]) {} + std::placeholders::_2, + true)]) {} VsyncWaiterIOS::~VsyncWaiterIOS() { // This way, we will get no more callbacks from the display link that holds a weak (non-nilling)
diff --git a/shell/platform/fuchsia/flutter/vsync_waiter.cc b/shell/platform/fuchsia/flutter/vsync_waiter.cc index 5a8fe59..fd8f601 100644 --- a/shell/platform/fuchsia/flutter/vsync_waiter.cc +++ b/shell/platform/fuchsia/flutter/vsync_waiter.cc
@@ -197,7 +197,7 @@ } fml::TimePoint previous_vsync = next_vsync - vsync_info.presentation_interval; - FireCallback(previous_vsync, next_vsync); + FireCallback(previous_vsync, next_vsync, false); } } // namespace flutter_runner