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

Peformance improvement : reduce engine init time 50%off at least #17192

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 190 additions & 0 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,144 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
return shell;
}

bool Shell::CreateShellAsyncOnPlatformThread(
ShellCreateCallback async_init_callback,
DartVMRef vm,
TaskRunners task_runners,
WindowData window_data,
Settings settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
if (!task_runners.IsValid()) {
FML_LOG(ERROR) << "Task runners to run the shell were invalid.";
return false;
}

auto shell =
std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));

// Create the rasterizer on the GPU thread.
auto rasterizer_promise =
std::make_shared<std::promise<std::unique_ptr<Rasterizer>>>();

fml::TaskRunner::RunNowOrPostTask(
task_runners.GetRasterTaskRunner(),
[rasterizer_promise,
on_create_rasterizer = std::move(on_create_rasterizer), //
shell = shell.get() //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
rasterizer_promise->set_value(std::move(rasterizer));
});

// Create the platform view on the platform thread (this thread).
auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return false;
}

// Ask the platform view for the vsync waiter. This will be used by the engine
// to create the animator.
auto vsync_waiter = platform_view->CreateVSyncWaiter();
if (!vsync_waiter) {
return false;
}

// Create the IO manager on the IO thread. The IO manager must be initialized
// first because it has state that the other subsystems depend on. It must
// first be booted and the necessary references obtained to initialize the
// other subsystems.
auto io_manager_promise =
std::make_shared<std::promise<std::unique_ptr<ShellIOManager>>>();
auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner();

fml::TaskRunner::RunNowOrPostTask(
io_task_runner,
[io_task_runner,
io_manager_promise, //
weak_platform_view = platform_view->GetWeakPtr(), //
is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch() //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupIOSubsystem");
auto io_manager = std::make_unique<ShellIOManager>(
weak_platform_view.getUnsafe()->CreateResourceContext(),
is_backgrounded_sync_switch, io_task_runner);
io_manager_promise->set_value(std::move(io_manager));
});

// Send dispatcher_maker to the engine constructor because shell won't have
// platform_view set until Shell::Setup is called later.
auto dispatcher_maker = platform_view->GetDispatcherMaker();

// Create the engine on the UI thread.
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
fml::MakeCopyable(
[shell = std::move(shell), //
platform_view = std::move(platform_view),
async_init_callback = std::move(async_init_callback), //
dispatcher_in = std::move(dispatcher_maker), //
window_data = std::move(window_data), //
isolate_snapshot = std::move(isolate_snapshot), //
vsync_waiter = std::move(vsync_waiter), //
io_manager_promise, //
// io_manager_future, //
// rasterizer_future,
rasterizer_promise //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
const auto& task_runners = shell->GetTaskRunners();

// The animator is owned by the UI thread but it gets its vsync
// pulses from the platform.
auto animator = std::make_unique<Animator>(*shell, task_runners,
std::move(vsync_waiter));

// wait params(io、gpu task end)
auto rasterizer = rasterizer_promise->get_future().get();
auto snapshot_delegate = rasterizer->GetSnapshotDelegate();
auto io_manager = io_manager_promise->get_future().get();
auto unref_queue = io_manager->GetSkiaUnrefQueue();

auto engine_ref =
std::make_unique<Engine>(*(shell.get()), //
dispatcher_in, //
*shell->GetDartVM(), //
std::move(isolate_snapshot), //
task_runners, //
window_data, //
shell->GetSettings(), //
std::move(animator), //
io_manager->GetWeakPtr(), //
std::move(unref_queue), //
std::move(snapshot_delegate) //
);

fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetPlatformTaskRunner(),
fml::MakeCopyable(
[async_init_callback = std::move(async_init_callback),
shell = std::move(shell),
platform_view = std::move(platform_view),
rasterizer = std::move(rasterizer),
io_manager = std::move(io_manager),
engine = std::move(engine_ref)]() mutable {
if (!shell->Setup(std::move(platform_view), //
std::move(engine), //
std::move(rasterizer), //
std::move(io_manager)) //
) {
async_init_callback(false, nullptr);
} else {
async_init_callback(true, std::move(shell));
}
}));
}));
return true;
}

static void RecordStartupTimestamp() {
if (engine_main_enter_ts == 0) {
engine_main_enter_ts = Dart_TimelineGetMicros();
Expand Down Expand Up @@ -240,6 +378,58 @@ static void PerformInitializationTasks(const Settings& settings) {
});
}

void Shell::CreateAsync(
ShellCreateCallback create_callback,
TaskRunners task_runners,
WindowData window_data,
Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
if (!create_callback) {
FML_CHECK(create_callback) << "CreateAsync: create_callback must be vaild!";
return;
}
PerformInitializationTasks(settings);
PersistentCache::SetCacheSkSL(settings.cache_sksl);

TRACE_EVENT0("flutter", "Shell::CreateAsync");

auto vm = DartVMRef::Create(settings);
FML_CHECK(vm) << "Must be able to initialize the VM.";

auto vm_data = vm->GetVMData();

if (!task_runners.IsValid() || !on_create_platform_view ||
!on_create_rasterizer) {
create_callback(false, nullptr);
return;
}
auto isolate_snapshot = vm_data->GetIsolateSnapshot();
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetPlatformTaskRunner(),
fml::MakeCopyable(
[vm = std::move(vm), //
create_callback = std::move(create_callback), //
task_runners = std::move(task_runners), //
window_data = std::move(window_data), //
settings = std::move(settings), //
isolate_snapshot = std::move(isolate_snapshot), //
on_create_platform_view = std::move(on_create_platform_view), //
on_create_rasterizer = std::move(on_create_rasterizer) //
]() mutable {
CreateShellAsyncOnPlatformThread(
std::move(create_callback), //
std::move(vm), //
std::move(task_runners), //
std::move(window_data), //
std::move(settings), //
std::move(isolate_snapshot), //
std::move(on_create_platform_view), //
std::move(on_create_rasterizer) //
);
}));
}

std::unique_ptr<Shell> Shell::Create(
TaskRunners task_runners,
Settings settings,
Expand Down
19 changes: 19 additions & 0 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class Shell final : public PlatformView::Delegate,
public:
template <class T>
using CreateCallback = std::function<std::unique_ptr<T>(Shell&)>;
using ShellCreateCallback =
std::function<void(bool success, std::unique_ptr<Shell> shell)>;

//----------------------------------------------------------------------------
/// @brief Creates a shell instance using the provided settings. The
Expand Down Expand Up @@ -166,6 +168,13 @@ class Shell final : public PlatformView::Delegate,
CreateCallback<PlatformView> on_create_platform_view,
CreateCallback<Rasterizer> on_create_rasterizer);

static void CreateAsync(ShellCreateCallback callBack,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a docstring. Please include the threads that will be invoking each callback.

TaskRunners task_runners,
WindowData window_data,
Settings settings,
CreateCallback<PlatformView> on_create_platform_view,
CreateCallback<Rasterizer> on_create_rasterizer);

//----------------------------------------------------------------------------
/// @brief Creates a shell instance using the provided settings. The
/// callbacks to create the various shell subcomponents will be
Expand Down Expand Up @@ -431,6 +440,16 @@ class Shell final : public PlatformView::Delegate,
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer);

static bool CreateShellAsyncOnPlatformThread(
ShellCreateCallback async_init_callback,
DartVMRef vm,
TaskRunners task_runners,
WindowData window_data,
Settings settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer);

bool Setup(std::unique_ptr<PlatformView> platform_view,
std::unique_ptr<Engine> engine,
std::unique_ptr<Rasterizer> rasterizer,
Expand Down
87 changes: 87 additions & 0 deletions shell/common/shell_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,79 @@ static void StartupAndShutdownShell(benchmark::State& state,
FML_CHECK(!shell);
}

static void StartupAsync(benchmark::State& state, bool mesure_async_total) {
auto assets_dir = fml::OpenDirectory(testing::GetFixturesPath(), false,
fml::FilePermission::kRead);
std::unique_ptr<Shell> shell_res;
std::unique_ptr<ThreadHost> thread_host;
testing::ELFAOTSymbols aot_symbols;
{
Settings settings = {};
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};

if (DartVM::IsRunningPrecompiledCode()) {
aot_symbols = testing::LoadELFSymbolFromFixturesIfNeccessary();
FML_CHECK(
testing::PrepareSettingsForAOTWithSymbols(settings, aot_symbols))
<< "Could not setup settings with AOT symbols.";
} else {
settings.application_kernels = [&]() {
std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
kernel_mappings.emplace_back(
fml::FileMapping::CreateReadOnly(assets_dir, "kernel_blob.bin"));
return kernel_mappings;
};
}

thread_host = std::make_unique<ThreadHost>(
"io.flutter.bench.", ThreadHost::Type::Platform |
ThreadHost::Type::GPU | ThreadHost::Type::IO |
ThreadHost::Type::UI);

TaskRunners task_runners("test",
thread_host->platform_thread->GetTaskRunner(),
thread_host->raster_thread->GetTaskRunner(),
thread_host->ui_thread->GetTaskRunner(),
thread_host->io_thread->GetTaskRunner());

fml::AutoResetWaitableEvent latch;
Shell::CreateAsync(
[&latch, &shell_res](bool success, std::unique_ptr<Shell> shell) {
if (success) {
shell_res = std::move(shell);
}
latch.Signal();
},
std::move(task_runners), WindowData{/* default window data */},
settings,
[](Shell& shell) {
return std::make_unique<PlatformView>(shell, shell.GetTaskRunners());
},
[](Shell& shell) {
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
});
benchmarking::ScopedPauseTiming pause(state, !mesure_async_total);
latch.Wait();
FML_CHECK(shell_res);
}
{
// dont' care shutdown time here
benchmarking::ScopedPauseTiming pause(state, true);
// Shutdown must occur synchronously on the platform thread.
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
thread_host->platform_thread->GetTaskRunner(),
[&shell_res, &latch]() mutable {
shell_res.reset();
latch.Signal();
});
latch.Wait();
thread_host.reset();
}
FML_CHECK(!shell_res);
}

static void BM_ShellInitialization(benchmark::State& state) {
while (state.KeepRunning()) {
StartupAndShutdownShell(state, true, false);
Expand All @@ -105,4 +178,18 @@ static void BM_ShellInitializationAndShutdown(benchmark::State& state) {

BENCHMARK(BM_ShellInitializationAndShutdown);

static void BM_ShellInitializationAsyncLockTime(benchmark::State& state) {
while (state.KeepRunning()) {
StartupAsync(state, false);
}
}
BENCHMARK(BM_ShellInitializationAsyncLockTime);

static void BM_ShellInitializationAsyncTotalTime(benchmark::State& state) {
while (state.KeepRunning()) {
StartupAsync(state, true);
}
}
BENCHMARK(BM_ShellInitializationAsyncTotalTime);

} // namespace flutter
Loading