未验证 提交 95f2b727 编写于 作者: C chenjianguang 提交者: GitHub

Create root isolate asynchronously (#20142)

## Description
As the related issue refer, the application may be doing too much work on its main thread even in a simple hello_world demo.
That is because the creation of `Engine` on the ui thread takes a noticeable time, and it is blocking the platform thread in order to run `Shell::Setup` synchronously.
The cost of `Engine`'s constructor is mainly about the creating of root isolate. Actually, there used to be another time-consuming process, the default font manager setup, which was resolved by https://github.com/flutter/engine/pull/18225. 
Similar to https://github.com/flutter/engine/pull/18225, this pr move the creation of root isolate out from creating `Engine`. After this action, the main thread blocking is quite an acceptable slice.

## Related Issues
https://github.com/flutter/flutter/issues/40563 could be resolved by this pr.
上级 696c2aaf
...@@ -18,7 +18,10 @@ namespace flutter { ...@@ -18,7 +18,10 @@ namespace flutter {
RuntimeController::RuntimeController(RuntimeDelegate& client, RuntimeController::RuntimeController(RuntimeDelegate& client,
TaskRunners p_task_runners) TaskRunners p_task_runners)
: client_(client), vm_(nullptr), task_runners_(p_task_runners) {} : client_(client),
vm_(nullptr),
task_runners_(p_task_runners),
weak_factory_(this) {}
RuntimeController::RuntimeController( RuntimeController::RuntimeController(
RuntimeDelegate& p_client, RuntimeDelegate& p_client,
...@@ -50,48 +53,80 @@ RuntimeController::RuntimeController( ...@@ -50,48 +53,80 @@ RuntimeController::RuntimeController(
platform_data_(std::move(p_platform_data)), platform_data_(std::move(p_platform_data)),
isolate_create_callback_(p_isolate_create_callback), isolate_create_callback_(p_isolate_create_callback),
isolate_shutdown_callback_(p_isolate_shutdown_callback), isolate_shutdown_callback_(p_isolate_shutdown_callback),
persistent_isolate_data_(std::move(p_persistent_isolate_data)) { persistent_isolate_data_(std::move(p_persistent_isolate_data)),
// Create the root isolate as soon as the runtime controller is initialized. weak_factory_(this) {
// Create the root isolate as soon as the runtime controller is initialized,
// but not using a synchronous way to avoid blocking the platform thread a
// long time as it is waiting while creating `Shell` on that platform thread.
// It will be run at a later point when the engine provides a run // It will be run at a later point when the engine provides a run
// configuration and then runs the isolate. // configuration and then runs the isolate.
auto strong_root_isolate = create_and_config_root_isolate_ =
DartIsolate::CreateRootIsolate( std::async(std::launch::deferred, [self = weak_factory_.GetWeakPtr()]() {
vm_->GetVMData()->GetSettings(), // if (!self) {
isolate_snapshot_, // return;
task_runners_, // }
std::make_unique<PlatformConfiguration>(this), //
snapshot_delegate_, // auto strong_root_isolate =
io_manager_, // DartIsolate::CreateRootIsolate(
unref_queue_, // self->vm_->GetVMData()->GetSettings(), //
image_decoder_, // self->isolate_snapshot_, //
p_advisory_script_uri, // self->task_runners_, //
p_advisory_script_entrypoint, // std::make_unique<PlatformConfiguration>(self.get()), //
nullptr, // self->snapshot_delegate_, //
isolate_create_callback_, // self->io_manager_, //
isolate_shutdown_callback_ // self->unref_queue_, //
) self->image_decoder_, //
.lock(); self->advisory_script_uri_, //
self->advisory_script_entrypoint_, //
FML_CHECK(strong_root_isolate) << "Could not create root isolate."; nullptr, //
self->isolate_create_callback_, //
// The root isolate ivar is weak. self->isolate_shutdown_callback_ //
root_isolate_ = strong_root_isolate; )
.lock();
strong_root_isolate->SetReturnCodeCallback([this](uint32_t code) {
root_isolate_return_code_ = {true, code}; FML_CHECK(strong_root_isolate) << "Could not create root isolate.";
});
// The root isolate ivar is weak.
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { self->root_isolate_ = strong_root_isolate;
tonic::DartState::Scope scope(strong_root_isolate);
platform_configuration->DidCreateIsolate(); strong_root_isolate->SetReturnCodeCallback([self](uint32_t code) {
if (!FlushRuntimeStateToIsolate()) { if (!self) {
FML_DLOG(ERROR) << "Could not setup initial isolate state."; return;
} }
} else {
FML_DCHECK(false) << "RuntimeController created without window binding."; self->root_isolate_return_code_ = {true, code};
} });
FML_DCHECK(Dart_CurrentIsolate() == nullptr); if (auto* platform_configuration =
self->GetPlatformConfigurationIfAvailable()) {
tonic::DartState::Scope scope(strong_root_isolate);
platform_configuration->DidCreateIsolate();
if (!self->FlushRuntimeStateToIsolate()) {
FML_DLOG(ERROR) << "Could not setup initial isolate state.";
}
} else {
FML_DCHECK(false)
<< "RuntimeController created without window binding.";
}
FML_DCHECK(Dart_CurrentIsolate() == nullptr);
self->client_.OnRootIsolateCreated();
return;
});
// We're still trying to create the root isolate as soon as possible here on
// the UI thread although it's deferred a little bit by
// std::async(std::launch::deferred, ...). So the callers of `GetRootIsolate`
// should get a quick return after this UI thread task.
task_runners_.GetUITaskRunner()->PostTask(
[self = weak_factory_.GetWeakPtr()]() {
if (!self) {
return;
}
self->GetRootIsolate();
});
} }
RuntimeController::~RuntimeController() { RuntimeController::~RuntimeController() {
...@@ -107,8 +142,8 @@ RuntimeController::~RuntimeController() { ...@@ -107,8 +142,8 @@ RuntimeController::~RuntimeController() {
} }
} }
bool RuntimeController::IsRootIsolateRunning() const { bool RuntimeController::IsRootIsolateRunning() {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock(); std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
if (root_isolate) { if (root_isolate) {
return root_isolate->GetPhase() == DartIsolate::Phase::Running; return root_isolate->GetPhase() == DartIsolate::Phase::Running;
} }
...@@ -234,7 +269,7 @@ bool RuntimeController::ReportTimings(std::vector<int64_t> timings) { ...@@ -234,7 +269,7 @@ bool RuntimeController::ReportTimings(std::vector<int64_t> timings) {
} }
bool RuntimeController::NotifyIdle(int64_t deadline) { bool RuntimeController::NotifyIdle(int64_t deadline) {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock(); std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
if (!root_isolate) { if (!root_isolate) {
return false; return false;
} }
...@@ -291,7 +326,7 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id, ...@@ -291,7 +326,7 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id,
PlatformConfiguration* PlatformConfiguration*
RuntimeController::GetPlatformConfigurationIfAvailable() { RuntimeController::GetPlatformConfigurationIfAvailable() {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock(); std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
return root_isolate ? root_isolate->platform_configuration() : nullptr; return root_isolate ? root_isolate->platform_configuration() : nullptr;
} }
...@@ -353,17 +388,17 @@ RuntimeController::ComputePlatformResolvedLocale( ...@@ -353,17 +388,17 @@ RuntimeController::ComputePlatformResolvedLocale(
} }
Dart_Port RuntimeController::GetMainPort() { Dart_Port RuntimeController::GetMainPort() {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock(); std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
return root_isolate ? root_isolate->main_port() : ILLEGAL_PORT; return root_isolate ? root_isolate->main_port() : ILLEGAL_PORT;
} }
std::string RuntimeController::GetIsolateName() { std::string RuntimeController::GetIsolateName() {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock(); std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
return root_isolate ? root_isolate->debug_name() : ""; return root_isolate ? root_isolate->debug_name() : "";
} }
bool RuntimeController::HasLivePorts() { bool RuntimeController::HasLivePorts() {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock(); std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
if (!root_isolate) { if (!root_isolate) {
return false; return false;
} }
...@@ -372,11 +407,20 @@ bool RuntimeController::HasLivePorts() { ...@@ -372,11 +407,20 @@ bool RuntimeController::HasLivePorts() {
} }
tonic::DartErrorHandleType RuntimeController::GetLastError() { tonic::DartErrorHandleType RuntimeController::GetLastError() {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock(); std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
return root_isolate ? root_isolate->GetLastError() : tonic::kNoError; return root_isolate ? root_isolate->GetLastError() : tonic::kNoError;
} }
std::weak_ptr<DartIsolate> RuntimeController::GetRootIsolate() { std::weak_ptr<DartIsolate> RuntimeController::GetRootIsolate() {
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
if (root_isolate) {
return root_isolate_;
}
// Root isolate is not yet created, get it and do some configuration.
FML_DCHECK(create_and_config_root_isolate_.valid());
create_and_config_root_isolate_.get();
return root_isolate_; return root_isolate_;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_ #ifndef FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_
#define FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_ #define FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_
#include <future>
#include <memory> #include <memory>
#include <vector> #include <vector>
...@@ -340,7 +341,7 @@ class RuntimeController : public PlatformConfigurationClient { ...@@ -340,7 +341,7 @@ class RuntimeController : public PlatformConfigurationClient {
/// ///
/// @return True if root isolate running, False otherwise. /// @return True if root isolate running, False otherwise.
/// ///
virtual bool IsRootIsolateRunning() const; virtual bool IsRootIsolateRunning();
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/// @brief Dispatch the specified platform message to running root /// @brief Dispatch the specified platform message to running root
...@@ -422,7 +423,10 @@ class RuntimeController : public PlatformConfigurationClient { ...@@ -422,7 +423,10 @@ class RuntimeController : public PlatformConfigurationClient {
/// @brief Get a weak pointer to the root Dart isolate. This isolate may /// @brief Get a weak pointer to the root Dart isolate. This isolate may
/// only be locked on the UI task runner. Callers use this /// only be locked on the UI task runner. Callers use this
/// accessor to transition to the root isolate to the running /// accessor to transition to the root isolate to the running
/// phase. /// phase. Note that it might take times if the isolate is not yet
/// created, which should be done in a subsequence task after
/// constructing `RuntimeController`, or it should get a quick
/// return otherwise.
/// ///
/// @return The root isolate reference. /// @return The root isolate reference.
/// ///
...@@ -471,11 +475,16 @@ class RuntimeController : public PlatformConfigurationClient { ...@@ -471,11 +475,16 @@ class RuntimeController : public PlatformConfigurationClient {
std::string advisory_script_entrypoint_; std::string advisory_script_entrypoint_;
std::function<void(int64_t)> idle_notification_callback_; std::function<void(int64_t)> idle_notification_callback_;
PlatformData platform_data_; PlatformData platform_data_;
std::future<void> create_and_config_root_isolate_;
// Note that `root_isolate_` is created asynchronously from the constructor of
// `RuntimeController`, be careful to use it directly while it might have not
// been created yet. Call `GetRootIsolate()` instead which guarantees that.
std::weak_ptr<DartIsolate> root_isolate_; std::weak_ptr<DartIsolate> root_isolate_;
std::pair<bool, uint32_t> root_isolate_return_code_ = {false, 0}; std::pair<bool, uint32_t> root_isolate_return_code_ = {false, 0};
const fml::closure isolate_create_callback_; const fml::closure isolate_create_callback_;
const fml::closure isolate_shutdown_callback_; const fml::closure isolate_shutdown_callback_;
std::shared_ptr<const fml::Mapping> persistent_isolate_data_; std::shared_ptr<const fml::Mapping> persistent_isolate_data_;
fml::WeakPtrFactory<RuntimeController> weak_factory_;
PlatformConfiguration* GetPlatformConfigurationIfAvailable(); PlatformConfiguration* GetPlatformConfigurationIfAvailable();
......
...@@ -32,6 +32,8 @@ class RuntimeDelegate { ...@@ -32,6 +32,8 @@ class RuntimeDelegate {
virtual FontCollection& GetFontCollection() = 0; virtual FontCollection& GetFontCollection() = 0;
virtual void OnRootIsolateCreated() = 0;
virtual void UpdateIsolateDescription(const std::string isolate_name, virtual void UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) = 0; int64_t isolate_port) = 0;
......
...@@ -495,6 +495,10 @@ void Engine::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) { ...@@ -495,6 +495,10 @@ void Engine::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
} }
} }
void Engine::OnRootIsolateCreated() {
delegate_.OnRootIsolateCreated();
}
void Engine::UpdateIsolateDescription(const std::string isolate_name, void Engine::UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) { int64_t isolate_port) {
delegate_.UpdateIsolateDescription(isolate_name, isolate_port); delegate_.UpdateIsolateDescription(isolate_name, isolate_port);
......
...@@ -185,6 +185,15 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { ...@@ -185,6 +185,15 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
/// ///
virtual void OnPreEngineRestart() = 0; virtual void OnPreEngineRestart() = 0;
//--------------------------------------------------------------------------
/// @brief Notifies the shell that the root isolate is created.
/// Currently, this information is to add to the service
/// protocol list of available root isolates running in the VM
/// and their names so that the appropriate isolate can be
/// selected in the tools for debugging and instrumentation.
///
virtual void OnRootIsolateCreated() = 0;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/// @brief Notifies the shell of the name of the root isolate and its /// @brief Notifies the shell of the name of the root isolate and its
/// port when that isolate is launched, restarted (in the /// port when that isolate is launched, restarted (in the
...@@ -812,6 +821,9 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { ...@@ -812,6 +821,9 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
// |RuntimeDelegate| // |RuntimeDelegate|
void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) override; void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) override;
// |RuntimeDelegate|
void OnRootIsolateCreated() override;
// |RuntimeDelegate| // |RuntimeDelegate|
void UpdateIsolateDescription(const std::string isolate_name, void UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) override; int64_t isolate_port) override;
......
...@@ -24,6 +24,7 @@ class MockDelegate : public Engine::Delegate { ...@@ -24,6 +24,7 @@ class MockDelegate : public Engine::Delegate {
MOCK_METHOD1(OnEngineHandlePlatformMessage, MOCK_METHOD1(OnEngineHandlePlatformMessage,
void(fml::RefPtr<PlatformMessage>)); void(fml::RefPtr<PlatformMessage>));
MOCK_METHOD0(OnPreEngineRestart, void()); MOCK_METHOD0(OnPreEngineRestart, void());
MOCK_METHOD0(OnRootIsolateCreated, void());
MOCK_METHOD2(UpdateIsolateDescription, void(const std::string, int64_t)); MOCK_METHOD2(UpdateIsolateDescription, void(const std::string, int64_t));
MOCK_METHOD1(SetNeedsReportTimings, void(bool)); MOCK_METHOD1(SetNeedsReportTimings, void(bool));
MOCK_METHOD1(ComputePlatformResolvedLocale, MOCK_METHOD1(ComputePlatformResolvedLocale,
...@@ -46,6 +47,7 @@ class MockRuntimeDelegate : public RuntimeDelegate { ...@@ -46,6 +47,7 @@ class MockRuntimeDelegate : public RuntimeDelegate {
void(SemanticsNodeUpdates, CustomAccessibilityActionUpdates)); void(SemanticsNodeUpdates, CustomAccessibilityActionUpdates));
MOCK_METHOD1(HandlePlatformMessage, void(fml::RefPtr<PlatformMessage>)); MOCK_METHOD1(HandlePlatformMessage, void(fml::RefPtr<PlatformMessage>));
MOCK_METHOD0(GetFontCollection, FontCollection&()); MOCK_METHOD0(GetFontCollection, FontCollection&());
MOCK_METHOD0(OnRootIsolateCreated, void());
MOCK_METHOD2(UpdateIsolateDescription, void(const std::string, int64_t)); MOCK_METHOD2(UpdateIsolateDescription, void(const std::string, int64_t));
MOCK_METHOD1(SetNeedsReportTimings, void(bool)); MOCK_METHOD1(SetNeedsReportTimings, void(bool));
MOCK_METHOD1(ComputePlatformResolvedLocale, MOCK_METHOD1(ComputePlatformResolvedLocale,
...@@ -57,7 +59,7 @@ class MockRuntimeController : public RuntimeController { ...@@ -57,7 +59,7 @@ class MockRuntimeController : public RuntimeController {
public: public:
MockRuntimeController(RuntimeDelegate& client, TaskRunners p_task_runners) MockRuntimeController(RuntimeDelegate& client, TaskRunners p_task_runners)
: RuntimeController(client, p_task_runners) {} : RuntimeController(client, p_task_runners) {}
MOCK_CONST_METHOD0(IsRootIsolateRunning, bool()); MOCK_METHOD0(IsRootIsolateRunning, bool());
MOCK_METHOD1(DispatchPlatformMessage, bool(fml::RefPtr<PlatformMessage>)); MOCK_METHOD1(DispatchPlatformMessage, bool(fml::RefPtr<PlatformMessage>));
}; };
......
...@@ -562,8 +562,6 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view, ...@@ -562,8 +562,6 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
is_setup_ = true; is_setup_ = true;
vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription());
PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner( PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
task_runners_.GetIOTaskRunner()); task_runners_.GetIOTaskRunner());
...@@ -1133,6 +1131,19 @@ void Shell::OnPreEngineRestart() { ...@@ -1133,6 +1131,19 @@ void Shell::OnPreEngineRestart() {
latch.Wait(); latch.Wait();
} }
// |Engine::Delegate|
void Shell::OnRootIsolateCreated() {
auto description = GetServiceProtocolDescription();
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetPlatformTaskRunner(),
[self = weak_factory_.GetWeakPtr(),
description = std::move(description)]() {
if (self) {
self->vm_->GetServiceProtocol()->AddHandler(self.get(), description);
}
});
}
// |Engine::Delegate| // |Engine::Delegate|
void Shell::UpdateIsolateDescription(const std::string isolate_name, void Shell::UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) { int64_t isolate_port) {
...@@ -1277,9 +1288,15 @@ bool Shell::HandleServiceProtocolMessage( ...@@ -1277,9 +1288,15 @@ bool Shell::HandleServiceProtocolMessage(
// |ServiceProtocol::Handler| // |ServiceProtocol::Handler|
ServiceProtocol::Handler::Description Shell::GetServiceProtocolDescription() ServiceProtocol::Handler::Description Shell::GetServiceProtocolDescription()
const { const {
FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
if (!weak_engine_) {
return ServiceProtocol::Handler::Description();
}
return { return {
engine_->GetUIIsolateMainPort(), weak_engine_->GetUIIsolateMainPort(),
engine_->GetUIIsolateName(), weak_engine_->GetUIIsolateName(),
}; };
} }
......
...@@ -513,6 +513,9 @@ class Shell final : public PlatformView::Delegate, ...@@ -513,6 +513,9 @@ class Shell final : public PlatformView::Delegate,
// |Engine::Delegate| // |Engine::Delegate|
void OnPreEngineRestart() override; void OnPreEngineRestart() override;
// |Engine::Delegate|
void OnRootIsolateCreated() override;
// |Engine::Delegate| // |Engine::Delegate|
void UpdateIsolateDescription(const std::string isolate_name, void UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) override; int64_t isolate_port) override;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册