diff --git a/.cirrus.yml b/.cirrus.yml index 82b5d8f97557c..d90a760e2258b 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -62,11 +62,13 @@ task: ./txt_benchmarks --benchmark_format=json > txt_benchmarks.json ./fml_benchmarks --benchmark_format=json > fml_benchmarks.json ./shell_benchmarks --benchmark_format=json > shell_benchmarks.json + ./ui_benchmarks --benchmark_format=json > ui_benchmarks.json cd $ENGINE_PATH/src/flutter/testing/benchmark pub get dart bin/parse_and_send.dart ../../../out/host_release/txt_benchmarks.json dart bin/parse_and_send.dart ../../../out/host_release/fml_benchmarks.json dart bin/parse_and_send.dart ../../../out/host_release/shell_benchmarks.json + dart bin/parse_and_send.dart ../../../out/host_release/ui_benchmarks.json - name: build_and_test_linux_release compile_host_script: | cd $ENGINE_PATH/src diff --git a/BUILD.gn b/BUILD.gn index 91d7724287a0f..19dce340cd183 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -83,6 +83,7 @@ group("flutter") { if (!is_win) { public_deps += [ "//flutter/fml:fml_benchmarks", + "//flutter/lib/ui:ui_benchmarks", "//flutter/shell/common:shell_benchmarks", "//flutter/third_party/txt:txt_benchmarks", ] diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 07d1c4b73c346..91f1b1ee4e25d 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -388,6 +388,7 @@ FILE: ../../../flutter/lib/ui/text/paragraph_builder.cc FILE: ../../../flutter/lib/ui/text/paragraph_builder.h FILE: ../../../flutter/lib/ui/text/text_box.h FILE: ../../../flutter/lib/ui/ui.dart +FILE: ../../../flutter/lib/ui/ui_benchmarks.cc FILE: ../../../flutter/lib/ui/ui_dart_state.cc FILE: ../../../flutter/lib/ui/ui_dart_state.h FILE: ../../../flutter/lib/ui/window.dart diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index f1100c3f66470..a122a35eaa9c5 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -180,4 +180,22 @@ if (current_toolchain == host_toolchain) { "//third_party/dart/runtime/bin:elf_loader", ] } + + executable("ui_benchmarks") { + testonly = true + + configs += [ "//flutter:export_dynamic_symbols" ] + + sources = [ + "ui_benchmarks.cc", + ] + + deps = [ + ":ui", + ":ui_unittests_fixtures", + "//flutter/benchmarking", + "//flutter/shell/common:common", + "//flutter/testing:fixture_test", + ] + } } diff --git a/lib/ui/fixtures/ui_test.dart b/lib/ui/fixtures/ui_test.dart index 852edd6dc9286..ecd42cc041bf5 100644 --- a/lib/ui/fixtures/ui_test.dart +++ b/lib/ui/fixtures/ui_test.dart @@ -40,3 +40,7 @@ void _validateVertices(Vertices vertices) native 'ValidateVertices'; void frameCallback(FrameInfo info) { print('called back'); } + +@pragma('vm:entry-point') +void messageCallback(dynamic data) { +} diff --git a/lib/ui/ui_benchmarks.cc b/lib/ui/ui_benchmarks.cc new file mode 100644 index 0000000000000..ebf8d9927ae6c --- /dev/null +++ b/lib/ui/ui_benchmarks.cc @@ -0,0 +1,72 @@ +// 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/benchmarking/benchmarking.h" +#include "flutter/common/settings.h" +#include "flutter/lib/ui/window/platform_message_response_dart.h" +#include "flutter/runtime/dart_vm_lifecycle.h" +#include "flutter/shell/common/thread_host.h" +#include "flutter/testing/dart_isolate_runner.h" +#include "flutter/testing/fixture_test.h" + +#include + +namespace flutter { + +class Fixture : public testing::FixtureTest { + void TestBody() override{}; +}; + +static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) { + ThreadHost thread_host("test", + 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()); + Fixture fixture; + auto settings = fixture.CreateSettingsForFixture(); + auto vm_ref = DartVMRef::Create(settings); + auto isolate = + testing::RunDartCodeInIsolate(vm_ref, settings, task_runners, "main", {}, + testing::GetFixturesPath(), {}); + + while (state.KeepRunning()) { + state.PauseTiming(); + bool successful = isolate->RunInIsolateScope([&]() -> bool { + // Simulate a message of 3 MB + std::vector data(3 << 20, 0); + std::unique_ptr mapping = + std::make_unique(data); + + Dart_Handle library = Dart_RootLibrary(); + Dart_Handle closure = + Dart_GetField(library, Dart_NewStringFromCString("messageCallback")); + + auto message = fml::MakeRefCounted( + tonic::DartPersistentValue(isolate->get(), closure), + thread_host.ui_thread->GetTaskRunner()); + + message->Complete(std::move(mapping)); + + return true; + }); + FML_CHECK(successful); + state.ResumeTiming(); + + // We skip timing everything above because the copy triggered by + // message->Complete is a task posted on the UI thread. The following wait + // for a UI task would let us know when that copy is done. + std::promise completed; + task_runners.GetUITaskRunner()->PostTask( + [&completed] { completed.set_value(true); }); + completed.get_future().wait(); + } +} + +BENCHMARK(BM_PlatformMessageResponseDartComplete) + ->Unit(benchmark::kMicrosecond); + +} // namespace flutter diff --git a/testing/BUILD.gn b/testing/BUILD.gn index 69f7d322264d4..1ff8ee97f2f6a 100644 --- a/testing/BUILD.gn +++ b/testing/BUILD.gn @@ -82,6 +82,21 @@ source_set("skia") { ] } +source_set("fixture_test") { + testonly = true + + sources = [ + "fixture_test.cc", + "fixture_test.h", + ] + + public_deps = [ + ":dart", + "//flutter/common", + "//flutter/runtime:runtime", + ] +} + if (enable_unittests) { # SwiftShader only supports x86/x64_64 if (target_cpu == "x86" || target_cpu == "x64") { diff --git a/testing/fixture_test.cc b/testing/fixture_test.cc new file mode 100644 index 0000000000000..ac81612afd5fb --- /dev/null +++ b/testing/fixture_test.cc @@ -0,0 +1,53 @@ +// 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/testing/fixture_test.h" + +namespace flutter { +namespace testing { + +FixtureTest::FixtureTest() + : native_resolver_(std::make_shared()), + assets_dir_(fml::OpenDirectory(GetFixturesPath(), + false, + fml::FilePermission::kRead)), + aot_symbols_(LoadELFSymbolFromFixturesIfNeccessary()) {} + +Settings FixtureTest::CreateSettingsForFixture() { + Settings settings; + settings.leak_vm = false; + settings.task_observer_add = [](intptr_t, fml::closure) {}; + settings.task_observer_remove = [](intptr_t) {}; + settings.isolate_create_callback = [this]() { + native_resolver_->SetNativeResolverForIsolate(); + }; + settings.enable_observatory = false; + SetSnapshotsAndAssets(settings); + return settings; +} + +void FixtureTest::SetSnapshotsAndAssets(Settings& settings) { + if (!assets_dir_.is_valid()) { + return; + } + + settings.assets_dir = assets_dir_.get(); + + // In JIT execution, all snapshots are present within the binary itself and + // don't need to be explicitly supplied by the embedder. In AOT, these + // snapshots will be present in the application AOT dylib. + if (DartVM::IsRunningPrecompiledCode()) { + FML_CHECK(PrepareSettingsForAOTWithSymbols(settings, aot_symbols_)); + } else { + settings.application_kernels = [this]() { + std::vector> kernel_mappings; + kernel_mappings.emplace_back( + fml::FileMapping::CreateReadOnly(assets_dir_, "kernel_blob.bin")); + return kernel_mappings; + }; + } +} + +} // namespace testing +} // namespace flutter diff --git a/testing/fixture_test.h b/testing/fixture_test.h new file mode 100644 index 0000000000000..340e29a30d5e1 --- /dev/null +++ b/testing/fixture_test.h @@ -0,0 +1,39 @@ +// 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. + +#ifndef FLUTTER_TESTING_FIXTURE_TEST_H_ +#define FLUTTER_TESTING_FIXTURE_TEST_H_ + +#include + +#include "flutter/common/settings.h" +#include "flutter/runtime/dart_vm.h" +#include "flutter/testing/elf_loader.h" +#include "flutter/testing/test_dart_native_resolver.h" +#include "flutter/testing/testing.h" +#include "flutter/testing/thread_test.h" + +namespace flutter { +namespace testing { + +class FixtureTest : public ThreadTest { + public: + FixtureTest(); + + Settings CreateSettingsForFixture(); + + private: + std::shared_ptr native_resolver_; + fml::UniqueFD assets_dir_; + ELFAOTSymbols aot_symbols_; + + void SetSnapshotsAndAssets(Settings& settings); + + FML_DISALLOW_COPY_AND_ASSIGN(FixtureTest); +}; + +} // namespace testing +} // namespace flutter + +#endif // FLUTTER_TESTING_FIXTURE_TEST_H_ diff --git a/testing/run_tests.py b/testing/run_tests.py index 35d5173ae3c08..c0f6e9938b64f 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -160,6 +160,8 @@ def RunEngineBenchmarks(build_dir, filter): RunEngineExecutable(build_dir, 'fml_benchmarks', filter) + RunEngineExecutable(build_dir, 'ui_benchmarks', filter) + if IsLinux(): RunEngineExecutable(build_dir, 'txt_benchmarks', filter)