From db630fbd931ee41cd61add73a9e9773e97d2c409 Mon Sep 17 00:00:00 2001 From: chenjianguang Date: Fri, 29 May 2020 08:53:04 +0800 Subject: [PATCH] Setup default font manager after engine created, to improve startup performance (flutter/engine#18225) --- engine/src/flutter/lib/ui/text/font_collection.cc | 6 ++++-- engine/src/flutter/lib/ui/text/font_collection.h | 2 ++ engine/src/flutter/shell/common/engine.cc | 5 +++++ engine/src/flutter/shell/common/engine.h | 5 +++++ engine/src/flutter/shell/common/shell.cc | 8 ++++++++ .../flutter/shell/platform/android/flutter_main.cc | 11 +++++++++++ .../io/flutter/embedding/engine/FlutterJNI.java | 7 +++++++ .../embedding/engine/loader/FlutterLoader.java | 11 +++++++++++ 8 files changed, 53 insertions(+), 2 deletions(-) diff --git a/engine/src/flutter/lib/ui/text/font_collection.cc b/engine/src/flutter/lib/ui/text/font_collection.cc index 8d1070852c3..c59dac72087 100644 --- a/engine/src/flutter/lib/ui/text/font_collection.cc +++ b/engine/src/flutter/lib/ui/text/font_collection.cc @@ -47,8 +47,6 @@ void _LoadFontFromList(Dart_NativeArguments args) { FontCollection::FontCollection() : collection_(std::make_shared()) { - collection_->SetupDefaultFontManager(); - dynamic_font_manager_ = sk_make_sp(); collection_->SetDynamicFontManager(dynamic_font_manager_); } @@ -68,6 +66,10 @@ std::shared_ptr FontCollection::GetFontCollection() const { return collection_; } +void FontCollection::SetupDefaultFontManager() { + collection_->SetupDefaultFontManager(); +} + void FontCollection::RegisterFonts( std::shared_ptr asset_manager) { std::unique_ptr manifest_mapping = diff --git a/engine/src/flutter/lib/ui/text/font_collection.h b/engine/src/flutter/lib/ui/text/font_collection.h index 4e19e2a9997..48e0e1e49db 100644 --- a/engine/src/flutter/lib/ui/text/font_collection.h +++ b/engine/src/flutter/lib/ui/text/font_collection.h @@ -29,6 +29,8 @@ class FontCollection { std::shared_ptr GetFontCollection() const; + void SetupDefaultFontManager(); + void RegisterFonts(std::shared_ptr asset_manager); void RegisterTestFonts(); diff --git a/engine/src/flutter/shell/common/engine.cc b/engine/src/flutter/shell/common/engine.cc index 47034113763..9f03c9200fd 100644 --- a/engine/src/flutter/shell/common/engine.cc +++ b/engine/src/flutter/shell/common/engine.cc @@ -90,6 +90,11 @@ fml::WeakPtr Engine::GetWeakPtr() const { return weak_factory_.GetWeakPtr(); } +void Engine::SetupDefaultFontManager() { + TRACE_EVENT0("flutter", "Engine::SetupDefaultFontManager"); + font_collection_.SetupDefaultFontManager(); +} + bool Engine::UpdateAssetManager( std::shared_ptr new_asset_manager) { if (asset_manager_ == new_asset_manager) { diff --git a/engine/src/flutter/shell/common/engine.h b/engine/src/flutter/shell/common/engine.h index 0f5f0717220..5f970b37177 100644 --- a/engine/src/flutter/shell/common/engine.h +++ b/engine/src/flutter/shell/common/engine.h @@ -363,6 +363,11 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { /// [[nodiscard]] bool Restart(RunConfiguration configuration); + //---------------------------------------------------------------------------- + /// @brief Setup default font manager according to specific platform. + /// + void SetupDefaultFontManager(); + //---------------------------------------------------------------------------- /// @brief Updates the asset manager referenced by the root isolate of a /// Flutter application. This happens implicitly in the call to diff --git a/engine/src/flutter/shell/common/shell.cc b/engine/src/flutter/shell/common/shell.cc index fd5a581647d..99236e05cb5 100644 --- a/engine/src/flutter/shell/common/shell.cc +++ b/engine/src/flutter/shell/common/shell.cc @@ -542,6 +542,14 @@ bool Shell::Setup(std::unique_ptr platform_view, weak_rasterizer_ = rasterizer_->GetWeakPtr(); weak_platform_view_ = platform_view_->GetWeakPtr(); + // Setup the time-consuming default font manager right after engine created. + fml::TaskRunner::RunNowOrPostTask(task_runners_.GetUITaskRunner(), + [engine = weak_engine_] { + if (engine) { + engine->SetupDefaultFontManager(); + } + }); + is_setup_ = true; vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription()); diff --git a/engine/src/flutter/shell/platform/android/flutter_main.cc b/engine/src/flutter/shell/platform/android/flutter_main.cc index cb2d51649aa..1493bf4f0d1 100644 --- a/engine/src/flutter/shell/platform/android/flutter_main.cc +++ b/engine/src/flutter/shell/platform/android/flutter_main.cc @@ -21,6 +21,7 @@ #include "flutter/shell/common/shell.h" #include "flutter/shell/common/switches.h" #include "third_party/dart/runtime/include/dart_tools_api.h" +#include "third_party/skia/include/core/SkFontMgr.h" namespace flutter { @@ -155,6 +156,11 @@ void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) { }); } +static void PrefetchDefaultFontManager(JNIEnv* env, jclass jcaller) { + // Initialize a singleton owned by Skia. + SkFontMgr::RefDefault(); +} + bool FlutterMain::Register(JNIEnv* env) { static const JNINativeMethod methods[] = { { @@ -163,6 +169,11 @@ bool FlutterMain::Register(JNIEnv* env) { "lang/String;Ljava/lang/String;Ljava/lang/String;J)V", .fnPtr = reinterpret_cast(&Init), }, + { + .name = "nativePrefetchDefaultFontManager", + .signature = "()V", + .fnPtr = reinterpret_cast(&PrefetchDefaultFontManager), + }, }; jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI"); diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 6f55fce248f..b0d5ad9ba19 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -106,6 +106,13 @@ public class FlutterJNI { @NonNull String engineCachesPath, long initTimeMillis); + /** + * Prefetch the default font manager provided by SkFontMgr::RefDefault() which is a process-wide + * singleton owned by Skia. Note that, the first call to SkFontMgr::RefDefault() will take + * noticeable time, but later calls will return a reference to the preexisting font manager. + */ + public static native void nativePrefetchDefaultFontManager(); + // TODO(mattcarroll): add javadocs @UiThread public native boolean nativeGetIsSoftwareRenderingEnabled(); diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java index bd506957289..c57d8c86b83 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java @@ -144,6 +144,17 @@ public class FlutterLoader { System.loadLibrary("flutter"); + // Prefetch the default font manager as soon as possible on a background thread. + // It helps to reduce time cost of engine setup that blocks the platform thread. + Executors.newSingleThreadExecutor() + .execute( + new Runnable() { + @Override + public void run() { + FlutterJNI.nativePrefetchDefaultFontManager(); + } + }); + if (resourceExtractor != null) { resourceExtractor.waitForCompletion(); }