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 | |
14 | namespace flutter { |
15 | |
16 | static 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 | |
98 | static void BM_ShellInitialization(benchmark::State& state) { |
99 | while (state.KeepRunning()) { |
100 | StartupAndShutdownShell(state, true, false); |
101 | } |
102 | } |
103 | |
104 | BENCHMARK(BM_ShellInitialization); |
105 | |
106 | static void BM_ShellShutdown(benchmark::State& state) { |
107 | while (state.KeepRunning()) { |
108 | StartupAndShutdownShell(state, false, true); |
109 | } |
110 | } |
111 | |
112 | BENCHMARK(BM_ShellShutdown); |
113 | |
114 | static void BM_ShellInitializationAndShutdown(benchmark::State& state) { |
115 | while (state.KeepRunning()) { |
116 | StartupAndShutdownShell(state, true, true); |
117 | } |
118 | } |
119 | |
120 | BENCHMARK(BM_ShellInitializationAndShutdown); |
121 | |
122 | } // namespace flutter |
123 | |