Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 89cf074

Browse files
authored
Setup default font manager after engine created, to improve startup performance (#18225)
1 parent 389a59d commit 89cf074

File tree

8 files changed

+53
-2
lines changed

8 files changed

+53
-2
lines changed

lib/ui/text/font_collection.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ void _LoadFontFromList(Dart_NativeArguments args) {
4747

4848
FontCollection::FontCollection()
4949
: collection_(std::make_shared<txt::FontCollection>()) {
50-
collection_->SetupDefaultFontManager();
51-
5250
dynamic_font_manager_ = sk_make_sp<txt::DynamicFontManager>();
5351
collection_->SetDynamicFontManager(dynamic_font_manager_);
5452
}
@@ -68,6 +66,10 @@ std::shared_ptr<txt::FontCollection> FontCollection::GetFontCollection() const {
6866
return collection_;
6967
}
7068

69+
void FontCollection::SetupDefaultFontManager() {
70+
collection_->SetupDefaultFontManager();
71+
}
72+
7173
void FontCollection::RegisterFonts(
7274
std::shared_ptr<AssetManager> asset_manager) {
7375
std::unique_ptr<fml::Mapping> manifest_mapping =

lib/ui/text/font_collection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class FontCollection {
2929

3030
std::shared_ptr<txt::FontCollection> GetFontCollection() const;
3131

32+
void SetupDefaultFontManager();
33+
3234
void RegisterFonts(std::shared_ptr<AssetManager> asset_manager);
3335

3436
void RegisterTestFonts();

shell/common/engine.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ fml::WeakPtr<Engine> Engine::GetWeakPtr() const {
9090
return weak_factory_.GetWeakPtr();
9191
}
9292

93+
void Engine::SetupDefaultFontManager() {
94+
TRACE_EVENT0("flutter", "Engine::SetupDefaultFontManager");
95+
font_collection_.SetupDefaultFontManager();
96+
}
97+
9398
bool Engine::UpdateAssetManager(
9499
std::shared_ptr<AssetManager> new_asset_manager) {
95100
if (asset_manager_ == new_asset_manager) {

shell/common/engine.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,11 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
363363
///
364364
[[nodiscard]] bool Restart(RunConfiguration configuration);
365365

366+
//----------------------------------------------------------------------------
367+
/// @brief Setup default font manager according to specific platform.
368+
///
369+
void SetupDefaultFontManager();
370+
366371
//----------------------------------------------------------------------------
367372
/// @brief Updates the asset manager referenced by the root isolate of a
368373
/// Flutter application. This happens implicitly in the call to

shell/common/shell.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,14 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
542542
weak_rasterizer_ = rasterizer_->GetWeakPtr();
543543
weak_platform_view_ = platform_view_->GetWeakPtr();
544544

545+
// Setup the time-consuming default font manager right after engine created.
546+
fml::TaskRunner::RunNowOrPostTask(task_runners_.GetUITaskRunner(),
547+
[engine = weak_engine_] {
548+
if (engine) {
549+
engine->SetupDefaultFontManager();
550+
}
551+
});
552+
545553
is_setup_ = true;
546554

547555
vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription());

shell/platform/android/flutter_main.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "flutter/shell/common/shell.h"
2222
#include "flutter/shell/common/switches.h"
2323
#include "third_party/dart/runtime/include/dart_tools_api.h"
24+
#include "third_party/skia/include/core/SkFontMgr.h"
2425

2526
namespace flutter {
2627

@@ -155,6 +156,11 @@ void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) {
155156
});
156157
}
157158

159+
static void PrefetchDefaultFontManager(JNIEnv* env, jclass jcaller) {
160+
// Initialize a singleton owned by Skia.
161+
SkFontMgr::RefDefault();
162+
}
163+
158164
bool FlutterMain::Register(JNIEnv* env) {
159165
static const JNINativeMethod methods[] = {
160166
{
@@ -163,6 +169,11 @@ bool FlutterMain::Register(JNIEnv* env) {
163169
"lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
164170
.fnPtr = reinterpret_cast<void*>(&Init),
165171
},
172+
{
173+
.name = "nativePrefetchDefaultFontManager",
174+
.signature = "()V",
175+
.fnPtr = reinterpret_cast<void*>(&PrefetchDefaultFontManager),
176+
},
166177
};
167178

168179
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");

shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ public static native void nativeInit(
106106
@NonNull String engineCachesPath,
107107
long initTimeMillis);
108108

109+
/**
110+
* Prefetch the default font manager provided by SkFontMgr::RefDefault() which is a process-wide
111+
* singleton owned by Skia. Note that, the first call to SkFontMgr::RefDefault() will take
112+
* noticeable time, but later calls will return a reference to the preexisting font manager.
113+
*/
114+
public static native void nativePrefetchDefaultFontManager();
115+
109116
// TODO(mattcarroll): add javadocs
110117
@UiThread
111118
public native boolean nativeGetIsSoftwareRenderingEnabled();

shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,17 @@ public InitResult call() {
144144

145145
System.loadLibrary("flutter");
146146

147+
// Prefetch the default font manager as soon as possible on a background thread.
148+
// It helps to reduce time cost of engine setup that blocks the platform thread.
149+
Executors.newSingleThreadExecutor()
150+
.execute(
151+
new Runnable() {
152+
@Override
153+
public void run() {
154+
FlutterJNI.nativePrefetchDefaultFontManager();
155+
}
156+
});
157+
147158
if (resourceExtractor != null) {
148159
resourceExtractor.waitForCompletion();
149160
}

0 commit comments

Comments
 (0)