1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4// FLUTTER_NOLINT
5
6#include "flutter/benchmarking/benchmarking.h"
7#include "flutter/fml/logging.h"
8#include "flutter/runtime/dart_vm.h"
9#include "flutter/shell/common/shell.h"
10#include "flutter/shell/common/thread_host.h"
11#include "flutter/testing/elf_loader.h"
12#include "flutter/testing/testing.h"
13
14namespace flutter {
15
16static void StartupAndShutdownShell(benchmark::State& state,
17 bool measure_startup,
18 bool measure_shutdown) {
19 auto assets_dir = fml::OpenDirectory(testing::GetFixturesPath(), false,
20 fml::FilePermission::kRead);
21 std::unique_ptr<Shell> shell;
22 std::unique_ptr<ThreadHost> thread_host;
23 testing::ELFAOTSymbols aot_symbols;
24
25 {
26 benchmarking::ScopedPauseTiming pause(state, !measure_startup);
27 Settings settings = {};
28 settings.task_observer_add = [](intptr_t, fml::closure) {};
29 settings.task_observer_remove = [](intptr_t) {};
30
31 if (DartVM::IsRunningPrecompiledCode()) {
32 aot_symbols = testing::LoadELFSymbolFromFixturesIfNeccessary();
33 FML_CHECK(
34 testing::PrepareSettingsForAOTWithSymbols(settings, aot_symbols))
35 << "Could not setup settings with AOT symbols.";
36 } else {
37 settings.application_kernels = [&]() {
38 std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
39 kernel_mappings.emplace_back(
40 fml::FileMapping::CreateReadOnly(assets_dir, "kernel_blob.bin"));
41 return kernel_mappings;
42 };
43 }
44
45 thread_host = std::make_unique<ThreadHost>(
46 "io.flutter.bench.", ThreadHost::Type::Platform |
47 ThreadHost::Type::GPU | ThreadHost::Type::IO |
48 ThreadHost::Type::UI);
49
50 TaskRunners task_runners("test",
51 thread_host->platform_thread->GetTaskRunner(),
52 thread_host->raster_thread->GetTaskRunner(),
53 thread_host->ui_thread->GetTaskRunner(),
54 thread_host->io_thread->GetTaskRunner());
55
56 shell = Shell::Create(
57 std::move(task_runners), settings,
58 [](Shell& shell) {
59 return std::make_unique<PlatformView>(shell, shell.GetTaskRunners());
60 },
61 [](Shell& shell) { return std::make_unique<Rasterizer>(shell); });
62 }
63
64 FML_CHECK(shell);
65
66 {
67 // The ui thread could be busy processing tasks after shell created, e.g.,
68 // default font manager setup. The measurement of shell shutdown should be
69 // considered after those ui tasks have been done.
70 //
71 // However, if we're measuring the complete time from startup to shutdown,
72 // this time should still be included.
73 benchmarking::ScopedPauseTiming pause(
74 state, !measure_shutdown || !measure_startup);
75 fml::AutoResetWaitableEvent latch;
76 fml::TaskRunner::RunNowOrPostTask(thread_host->ui_thread->GetTaskRunner(),
77 [&latch]() { latch.Signal(); });
78 latch.Wait();
79 }
80
81 {
82 benchmarking::ScopedPauseTiming pause(state, !measure_shutdown);
83 // Shutdown must occur synchronously on the platform thread.
84 fml::AutoResetWaitableEvent latch;
85 fml::TaskRunner::RunNowOrPostTask(
86 thread_host->platform_thread->GetTaskRunner(),
87 [&shell, &latch]() mutable {
88 shell.reset();
89 latch.Signal();
90 });
91 latch.Wait();
92 thread_host.reset();
93 }
94
95 FML_CHECK(!shell);
96}
97
98static void BM_ShellInitialization(benchmark::State& state) {
99 while (state.KeepRunning()) {
100 StartupAndShutdownShell(state, true, false);
101 }
102}
103
104BENCHMARK(BM_ShellInitialization);
105
106static void BM_ShellShutdown(benchmark::State& state) {
107 while (state.KeepRunning()) {
108 StartupAndShutdownShell(state, false, true);
109 }
110}
111
112BENCHMARK(BM_ShellShutdown);
113
114static void BM_ShellInitializationAndShutdown(benchmark::State& state) {
115 while (state.KeepRunning()) {
116 StartupAndShutdownShell(state, true, true);
117 }
118}
119
120BENCHMARK(BM_ShellInitializationAndShutdown);
121
122} // namespace flutter
123