From 54cdc26afbc62c7ec3cf6ca6569bfc67f6c5cf18 Mon Sep 17 00:00:00 2001 From: Yegor Date: Thu, 16 Apr 2020 14:46:41 -0700 Subject: [PATCH] add benchmark for picture recording (#54908) --- .../lib/src/web/bench_picture_recording.dart | 75 +++++++++++++++++++ .../macrobenchmarks/lib/web_benchmarks.dart | 2 + 2 files changed, 77 insertions(+) create mode 100644 dev/benchmarks/macrobenchmarks/lib/src/web/bench_picture_recording.dart diff --git a/dev/benchmarks/macrobenchmarks/lib/src/web/bench_picture_recording.dart b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_picture_recording.dart new file mode 100644 index 0000000000..1e45f9a1f0 --- /dev/null +++ b/dev/benchmarks/macrobenchmarks/lib/src/web/bench_picture_recording.dart @@ -0,0 +1,75 @@ +// Copyright 2014 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. + +import 'dart:ui'; + +import 'package:macrobenchmarks/src/web/recorder.dart'; + +/// Measure the performance of paint bounds estimation by recording a picture +/// without actually rendering it. +/// +/// Bounds estimation is done in two phases: +/// +/// * As we call drawing methods on `Canvas` we grow bounds with every paint op. +/// * When we're done recording a picture we call `PictureRecorder.endRecording` +/// at which point we compute the overall picture bounds and cache the result. +/// +/// This benchmarks puts emphasis on paint operations that trigger expensive +/// math such as `transformLTRB`. To do that we push non-identity transforms +/// and rotations before calling drawing methods. +class BenchPictureRecording extends RawRecorder { + BenchPictureRecording() : super(name: benchmarkName); + + static const String benchmarkName = 'bench_picture_recording'; + + /// Cached paint used for drawing. + /// + /// We want to avoid polluting the results with paint initialization logic. + Paint paint; + + /// A prelaid out and cached paragraph. + /// + /// This is cached to remove text layout time from the benchmark time. + Paragraph paragraph; + + @override + Future setUpAll() async { + paint = Paint(); + paragraph = (ParagraphBuilder(ParagraphStyle()) + ..addText('abcd edfh ijkl mnop qrst uvwx yz')) + .build() + ..layout(const ParagraphConstraints(width: 50)); + } + + @override + void body(Profile profile) { + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder); + profile.record('recordPaintCommands', () { + for (int i = 1; i <= 100; i++) { + canvas.translate((10 + i).toDouble(), (10 + i).toDouble()); + + canvas.save(); + for (int j = 0; j < 10; j++) { + canvas.drawRect(const Rect.fromLTWH(10, 10, 10, 10), paint); + canvas.drawCircle(const Offset(50, 50), 50, paint); + canvas.rotate(1.0); + } + canvas.restore(); + + canvas.save(); + for (int j = 0; j < 10; j++) { + canvas.translate(1, 1); + canvas.clipRect(Rect.fromLTWH(20, 20, 40 / i, 40)); + canvas.drawRRect(RRect.fromRectAndRadius(const Rect.fromLTWH(10, 10, 10, 10), const Radius.circular(2)), paint); + canvas.drawParagraph(paragraph, Offset.zero); + } + canvas.restore(); + } + }); + profile.record('estimatePaintBounds', () { + recorder.endRecording(); + }); + } +} diff --git a/dev/benchmarks/macrobenchmarks/lib/web_benchmarks.dart b/dev/benchmarks/macrobenchmarks/lib/web_benchmarks.dart index e306199442..06e4a99e77 100644 --- a/dev/benchmarks/macrobenchmarks/lib/web_benchmarks.dart +++ b/dev/benchmarks/macrobenchmarks/lib/web_benchmarks.dart @@ -14,6 +14,7 @@ import 'src/web/bench_build_material_checkbox.dart'; import 'src/web/bench_card_infinite_scroll.dart'; import 'src/web/bench_draw_rect.dart'; import 'src/web/bench_dynamic_clip_on_static_picture.dart'; +import 'src/web/bench_picture_recording.dart'; import 'src/web/bench_simple_lazy_text_scroll.dart'; import 'src/web/bench_text_out_of_picture_bounds.dart'; import 'src/web/recorder.dart'; @@ -33,6 +34,7 @@ final Map benchmarks = { BenchSimpleLazyTextScroll.benchmarkName: () => BenchSimpleLazyTextScroll(), BenchBuildMaterialCheckbox.benchmarkName: () => BenchBuildMaterialCheckbox(), BenchDynamicClipOnStaticPicture.benchmarkName: () => BenchDynamicClipOnStaticPicture(), + BenchPictureRecording.benchmarkName: () => BenchPictureRecording(), if (isCanvasKit) BenchBuildColorsGrid.canvasKitBenchmarkName: () => BenchBuildColorsGrid.canvasKit(),