| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "flutter/shell/common/shell.h" |
| |
| #include "flutter/benchmarking/benchmarking.h" |
| #include "flutter/fml/logging.h" |
| #include "flutter/runtime/dart_vm.h" |
| #include "flutter/shell/common/thread_host.h" |
| #include "flutter/testing/elf_loader.h" |
| #include "flutter/testing/testing.h" |
| |
| namespace flutter { |
| |
| static void StartupAndShutdownShell(benchmark::State& state, |
| bool measure_startup, |
| bool measure_shutdown) { |
| auto assets_dir = fml::OpenDirectory(testing::GetFixturesPath(), false, |
| fml::FilePermission::kRead); |
| std::unique_ptr<Shell> shell; |
| std::unique_ptr<ThreadHost> thread_host; |
| testing::ELFAOTSymbols aot_symbols; |
| |
| { |
| benchmarking::ScopedPauseTiming pause(state, !measure_startup); |
| 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 set up 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::RASTER | |
| 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()); |
| |
| shell = Shell::Create( |
| flutter::PlatformData(), std::move(task_runners), settings, |
| [](Shell& shell) { |
| return std::make_unique<PlatformView>(shell, shell.GetTaskRunners()); |
| }, |
| [](Shell& shell) { return std::make_unique<Rasterizer>(shell); }); |
| } |
| |
| FML_CHECK(shell); |
| |
| { |
| // The ui thread could be busy processing tasks after shell created, e.g., |
| // default font manager setup. The measurement of shell shutdown should be |
| // considered after those ui tasks have been done. |
| // |
| // However, if we're measuring the complete time from startup to shutdown, |
| // this time should still be included. |
| benchmarking::ScopedPauseTiming pause( |
| state, !measure_shutdown || !measure_startup); |
| fml::AutoResetWaitableEvent latch; |
| fml::TaskRunner::RunNowOrPostTask(thread_host->ui_thread->GetTaskRunner(), |
| [&latch]() { latch.Signal(); }); |
| latch.Wait(); |
| } |
| |
| { |
| benchmarking::ScopedPauseTiming pause(state, !measure_shutdown); |
| // Shutdown must occur synchronously on the platform thread. |
| fml::AutoResetWaitableEvent latch; |
| fml::TaskRunner::RunNowOrPostTask( |
| thread_host->platform_thread->GetTaskRunner(), |
| [&shell, &latch]() mutable { |
| shell.reset(); |
| latch.Signal(); |
| }); |
| latch.Wait(); |
| thread_host.reset(); |
| } |
| |
| FML_CHECK(!shell); |
| } |
| |
| static void BM_ShellInitialization(benchmark::State& state) { |
| while (state.KeepRunning()) { |
| StartupAndShutdownShell(state, true, false); |
| } |
| } |
| |
| BENCHMARK(BM_ShellInitialization); |
| |
| static void BM_ShellShutdown(benchmark::State& state) { |
| while (state.KeepRunning()) { |
| StartupAndShutdownShell(state, false, true); |
| } |
| } |
| |
| BENCHMARK(BM_ShellShutdown); |
| |
| static void BM_ShellInitializationAndShutdown(benchmark::State& state) { |
| while (state.KeepRunning()) { |
| StartupAndShutdownShell(state, true, true); |
| } |
| } |
| |
| BENCHMARK(BM_ShellInitializationAndShutdown); |
| |
| } // namespace flutter |