Flutter Engine
The Flutter Engine
dl_region_benchmarks.cc
Go to the documentation of this file.
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
5#include "flutter/benchmarking/benchmarking.h"
6
7#include "flutter/display_list/geometry/dl_region.h"
8#include "flutter/fml/logging.h"
10
11#include <random>
12
13namespace {
14
15template <typename RNG>
16std::vector<SkIRect> GenerateRects(RNG& rng,
17 const SkIRect& bounds,
18 int numRects,
19 int maxSize) {
20 auto max_size_x = std::min(maxSize, bounds.width());
21 auto max_size_y = std::min(maxSize, bounds.height());
22
23 std::uniform_int_distribution pos_x(bounds.fLeft, bounds.fRight - max_size_x);
24 std::uniform_int_distribution pos_y(bounds.fTop, bounds.fBottom - max_size_y);
25 std::uniform_int_distribution size_x(1, max_size_x);
26 std::uniform_int_distribution size_y(1, max_size_y);
27
28 std::vector<SkIRect> rects;
29 for (int i = 0; i < numRects; ++i) {
31 SkIRect::MakeXYWH(pos_x(rng), pos_y(rng), size_x(rng), size_y(rng));
32 rects.push_back(rect);
33 }
34 return rects;
35}
36
37template <typename RNG>
38SkIRect RandomSubRect(RNG& rng, const SkIRect& rect, double size_factor) {
39 FML_DCHECK(size_factor <= 1);
40
41 int32_t width = rect.width() * size_factor;
42 int32_t height = rect.height() * size_factor;
43
44 std::uniform_int_distribution pos_x(0, rect.width() - width);
45 std::uniform_int_distribution pos_y(0, rect.height() - height);
46
47 return SkIRect::MakeXYWH(rect.fLeft + pos_x(rng), rect.fTop + pos_y(rng),
48 width, height);
49}
50
51class SkRegionAdapter {
52 public:
53 explicit SkRegionAdapter(const std::vector<SkIRect>& rects) {
54 region_.setRects(rects.data(), rects.size());
55 }
56
57 SkIRect getBounds() { return region_.getBounds(); }
58
59 static SkRegionAdapter unionRegions(const SkRegionAdapter& a1,
60 const SkRegionAdapter& a2) {
61 SkRegionAdapter result(a1);
62 result.region_.op(a2.region_, SkRegion::kUnion_Op);
63 return result;
64 }
65
66 static SkRegionAdapter intersectRegions(const SkRegionAdapter& a1,
67 const SkRegionAdapter& a2) {
68 SkRegionAdapter result(a1);
69 result.region_.op(a2.region_, SkRegion::kIntersect_Op);
70 return result;
71 }
72
73 bool intersects(const SkRegionAdapter& region) {
74 return region_.intersects(region.region_);
75 }
76
77 bool intersects(const SkIRect& rect) { return region_.intersects(rect); }
78
79 std::vector<SkIRect> getRects() {
80 std::vector<SkIRect> rects;
81 SkRegion::Iterator it(region_);
82 while (!it.done()) {
83 rects.push_back(it.rect());
84 it.next();
85 }
86 return rects;
87 }
88
89 private:
90 SkRegion region_;
91};
92
93class DlRegionAdapter {
94 public:
95 explicit DlRegionAdapter(const std::vector<SkIRect>& rects)
96 : region_(rects) {}
97
98 static DlRegionAdapter unionRegions(const DlRegionAdapter& a1,
99 const DlRegionAdapter& a2) {
100 return DlRegionAdapter(
101 flutter::DlRegion::MakeUnion(a1.region_, a2.region_));
102 }
103
104 static DlRegionAdapter intersectRegions(const DlRegionAdapter& a1,
105 const DlRegionAdapter& a2) {
106 return DlRegionAdapter(
107 flutter::DlRegion::MakeIntersection(a1.region_, a2.region_));
108 }
109
110 SkIRect getBounds() { return region_.bounds(); }
111
112 bool intersects(const DlRegionAdapter& region) {
113 return region_.intersects(region.region_);
114 }
115
116 bool intersects(const SkIRect& rect) { return region_.intersects(rect); }
117
118 std::vector<SkIRect> getRects() { return region_.getRects(false); }
119
120 private:
121 explicit DlRegionAdapter(flutter::DlRegion&& region)
122 : region_(std::move(region)) {}
123
124 flutter::DlRegion region_;
125};
126
127template <typename Region>
128void RunFromRectsBenchmark(benchmark::State& state, int maxSize) {
129 std::random_device d;
130 std::seed_seq seed{2, 1, 3};
131 std::mt19937 rng(seed);
132
133 std::uniform_int_distribution pos(0, 4000);
134 std::uniform_int_distribution size(1, maxSize);
135
136 std::vector<SkIRect> rects;
137 for (int i = 0; i < 2000; ++i) {
138 SkIRect rect = SkIRect::MakeXYWH(pos(rng), pos(rng), size(rng), size(rng));
139 rects.push_back(rect);
140 }
141
142 while (state.KeepRunning()) {
143 Region region(rects);
144 }
145}
146
147template <typename Region>
148void RunGetRectsBenchmark(benchmark::State& state, int maxSize) {
149 std::random_device d;
150 std::seed_seq seed{2, 1, 3};
151 std::mt19937 rng(seed);
152
153 std::uniform_int_distribution pos(0, 4000);
154 std::uniform_int_distribution size(1, maxSize);
155
156 std::vector<SkIRect> rects;
157 for (int i = 0; i < 2000; ++i) {
158 SkIRect rect = SkIRect::MakeXYWH(pos(rng), pos(rng), size(rng), size(rng));
159 rects.push_back(rect);
160 }
161
162 Region region(rects);
163
164 while (state.KeepRunning()) {
165 auto vec2 = region.getRects();
166 }
167}
168
169enum RegionOp { kUnion, kIntersection };
170
171template <typename Region>
172void RunRegionOpBenchmark(benchmark::State& state,
173 RegionOp op,
174 bool withSingleRect,
175 int maxSize,
176 double sizeFactor) {
177 std::random_device d;
178 std::seed_seq seed{2, 1, 3};
179 std::mt19937 rng(seed);
180
181 SkIRect bounds1 = SkIRect::MakeWH(4000, 4000);
182 SkIRect bounds2 = RandomSubRect(rng, bounds1, sizeFactor);
183
184 auto rects = GenerateRects(rng, bounds1, 500, maxSize);
185 Region region1(rects);
186
187 rects = GenerateRects(rng, bounds2, withSingleRect ? 1 : 500 * sizeFactor,
188 maxSize);
189 Region region2(rects);
190
191 switch (op) {
192 case kUnion:
193 while (state.KeepRunning()) {
194 Region::unionRegions(region1, region2);
195 }
196 break;
197 case kIntersection:
198 while (state.KeepRunning()) {
199 Region::intersectRegions(region1, region2);
200 }
201 break;
202 }
203}
204
205template <typename Region>
206void RunIntersectsRegionBenchmark(benchmark::State& state,
207 int maxSize,
208 double sizeFactor) {
209 std::random_device d;
210 std::seed_seq seed{2, 1, 3};
211 std::mt19937 rng(seed);
212
213 SkIRect bounds1 = SkIRect::MakeWH(4000, 4000);
214 SkIRect bounds2 = RandomSubRect(rng, bounds1, sizeFactor);
215
216 auto rects = GenerateRects(rng, bounds1, 500, maxSize);
217 Region region1(rects);
218
219 rects = GenerateRects(rng, bounds2, 500 * sizeFactor, maxSize);
220 Region region2(rects);
221
222 while (state.KeepRunning()) {
223 region1.intersects(region2);
224 }
225}
226
227template <typename Region>
228void RunIntersectsSingleRectBenchmark(benchmark::State& state, int maxSize) {
229 std::random_device d;
230 std::seed_seq seed{2, 1, 3};
231 std::mt19937 rng(seed);
232
233 std::uniform_int_distribution pos(0, 4000);
234 std::uniform_int_distribution size(1, maxSize);
235
236 std::vector<SkIRect> rects;
237 for (int i = 0; i < 500; ++i) {
238 SkIRect rect = SkIRect::MakeXYWH(pos(rng), pos(rng), size(rng), size(rng));
239 rects.push_back(rect);
240 }
241 Region region1(rects);
242
243 rects.clear();
244 for (int i = 0; i < 100; ++i) {
245 SkIRect rect = SkIRect::MakeXYWH(pos(rng), pos(rng), size(rng), size(rng));
246 rects.push_back(rect);
247 }
248
249 while (state.KeepRunning()) {
250 for (auto& rect : rects) {
251 region1.intersects(rect);
252 }
253 }
254}
255
256} // namespace
257
258namespace flutter {
259
260static void BM_DlRegion_FromRects(benchmark::State& state, int maxSize) {
261 RunFromRectsBenchmark<DlRegionAdapter>(state, maxSize);
262}
263
264static void BM_SkRegion_FromRects(benchmark::State& state, int maxSize) {
265 RunFromRectsBenchmark<SkRegionAdapter>(state, maxSize);
266}
267
268static void BM_DlRegion_GetRects(benchmark::State& state, int maxSize) {
269 RunGetRectsBenchmark<DlRegionAdapter>(state, maxSize);
270}
271
272static void BM_SkRegion_GetRects(benchmark::State& state, int maxSize) {
273 RunGetRectsBenchmark<SkRegionAdapter>(state, maxSize);
274}
275
277 RegionOp op,
278 bool withSingleRect,
279 int maxSize,
280 double sizeFactor) {
281 RunRegionOpBenchmark<DlRegionAdapter>(state, op, withSingleRect, maxSize,
282 sizeFactor);
283}
284
286 RegionOp op,
287 bool withSingleRect,
288 int maxSize,
289 double sizeFactor) {
290 RunRegionOpBenchmark<SkRegionAdapter>(state, op, withSingleRect, maxSize,
291 sizeFactor);
292}
293
295 int maxSize,
296 double sizeFactor) {
297 RunIntersectsRegionBenchmark<DlRegionAdapter>(state, maxSize, sizeFactor);
298}
299
301 int maxSize,
302 double sizeFactor) {
303 RunIntersectsRegionBenchmark<SkRegionAdapter>(state, maxSize, sizeFactor);
304}
305
307 int maxSize) {
308 RunIntersectsSingleRectBenchmark<DlRegionAdapter>(state, maxSize);
309}
310
312 int maxSize) {
313 RunIntersectsSingleRectBenchmark<SkRegionAdapter>(state, maxSize);
314}
315
316const double kSizeFactorSmall = 0.3;
317
319 ->Unit(benchmark::kNanosecond);
321 ->Unit(benchmark::kNanosecond);
323 ->Unit(benchmark::kNanosecond);
325 ->Unit(benchmark::kNanosecond);
327 ->Unit(benchmark::kNanosecond);
329 ->Unit(benchmark::kNanosecond);
331 ->Unit(benchmark::kNanosecond);
333 ->Unit(benchmark::kNanosecond);
334
336 ->Unit(benchmark::kNanosecond);
338 ->Unit(benchmark::kNanosecond);
340 ->Unit(benchmark::kNanosecond);
342 ->Unit(benchmark::kNanosecond);
344 ->Unit(benchmark::kNanosecond);
346 ->Unit(benchmark::kNanosecond);
348 ->Unit(benchmark::kNanosecond);
350 ->Unit(benchmark::kNanosecond);
351
353 TinyAsymmetric,
354 30,
356 ->Unit(benchmark::kNanosecond);
358 TinyAsymmetric,
359 30,
361 ->Unit(benchmark::kNanosecond);
363 SmallAsymmetric,
364 100,
366 ->Unit(benchmark::kNanosecond);
368 SmallAsymmetric,
369 100,
371 ->Unit(benchmark::kNanosecond);
373 MediumAsymmetric,
374 400,
376 ->Unit(benchmark::kNanosecond);
378 MediumAsymmetric,
379 400,
381 ->Unit(benchmark::kNanosecond);
383 LargeAsymmetric,
384 1500,
386 ->Unit(benchmark::kNanosecond);
388 LargeAsymmetric,
389 1500,
391 ->Unit(benchmark::kNanosecond);
392
394 Union_Tiny,
395 RegionOp::kUnion,
396 false,
397 30,
398 1.0)
399 ->Unit(benchmark::kMicrosecond);
401 Union_Tiny,
402 RegionOp::kUnion,
403 false,
404 30,
405 1.0)
406 ->Unit(benchmark::kMicrosecond);
408 Union_Small,
409 RegionOp::kUnion,
410 false,
411 100,
412 1.0)
413 ->Unit(benchmark::kMicrosecond);
415 Union_Small,
416 RegionOp::kUnion,
417 false,
418 100,
419 1.0)
420 ->Unit(benchmark::kMicrosecond);
422 Union_Medium,
423 RegionOp::kUnion,
424 false,
425 400,
426 1.0)
427 ->Unit(benchmark::kMicrosecond);
429 Union_Medium,
430 RegionOp::kUnion,
431 false,
432 400,
433 1.0)
434 ->Unit(benchmark::kMicrosecond);
436 Union_Large,
437 RegionOp::kUnion,
438 false,
439 1500,
440 1.0)
441 ->Unit(benchmark::kMicrosecond);
443 Union_Large,
444 RegionOp::kUnion,
445 false,
446 1500,
447 1.0)
448 ->Unit(benchmark::kMicrosecond);
449
451 Union_TinyAsymmetric,
452 RegionOp::kUnion,
453 false,
454 30,
456 ->Unit(benchmark::kMicrosecond);
458 Union_TinyAsymmetric,
459 RegionOp::kUnion,
460 false,
461 30,
463 ->Unit(benchmark::kMicrosecond);
465 Union_SmallAsymmetric,
466 RegionOp::kUnion,
467 false,
468 100,
470 ->Unit(benchmark::kMicrosecond);
472 Union_SmallAsymmetric,
473 RegionOp::kUnion,
474 false,
475 100,
477 ->Unit(benchmark::kMicrosecond);
479 Union_MediumAsymmetric,
480 RegionOp::kUnion,
481 false,
482 400,
484 ->Unit(benchmark::kMicrosecond);
486 Union_MediumAsymmetric,
487 RegionOp::kUnion,
488 false,
489 400,
491 ->Unit(benchmark::kMicrosecond);
493 Union_LargeAsymmetric,
494 RegionOp::kUnion,
495 false,
496 1500,
498 ->Unit(benchmark::kMicrosecond);
500 Union_LargeAsymmetric,
501 RegionOp::kUnion,
502 false,
503 1500,
505 ->Unit(benchmark::kMicrosecond);
506
508 Intersection_Tiny,
509 RegionOp::kIntersection,
510 false,
511 30,
512 1.0)
513 ->Unit(benchmark::kMicrosecond);
515 Intersection_Tiny,
516 RegionOp::kIntersection,
517 false,
518 30,
519 1.0)
520 ->Unit(benchmark::kMicrosecond);
522 Intersection_Small,
523 RegionOp::kIntersection,
524 false,
525 100,
526 1.0)
527 ->Unit(benchmark::kMicrosecond);
529 Intersection_Small,
530 RegionOp::kIntersection,
531 false,
532 100,
533 1.0)
534 ->Unit(benchmark::kMicrosecond);
536 Intersection_Medium,
537 RegionOp::kIntersection,
538 false,
539 400,
540 1.0)
541 ->Unit(benchmark::kMicrosecond);
543 Intersection_Medium,
544 RegionOp::kIntersection,
545 false,
546 400,
547 1.0)
548 ->Unit(benchmark::kMicrosecond);
550 Intersection_Large,
551 RegionOp::kIntersection,
552 false,
553 1500,
554 1.0)
555 ->Unit(benchmark::kMicrosecond);
557 Intersection_Large,
558 RegionOp::kIntersection,
559 false,
560 1500,
561 1.0)
562 ->Unit(benchmark::kMicrosecond);
563
565 Intersection_TinyAsymmetric,
566 RegionOp::kIntersection,
567 false,
568 30,
570 ->Unit(benchmark::kMicrosecond);
572 Intersection_TinyAsymmetric,
573 RegionOp::kIntersection,
574 false,
575 30,
577 ->Unit(benchmark::kMicrosecond);
579 Intersection_SmallAsymmetric,
580 RegionOp::kIntersection,
581 false,
582 100,
584 ->Unit(benchmark::kMicrosecond);
586 Intersection_SmallAsymmetric,
587 RegionOp::kIntersection,
588 false,
589 100,
591 ->Unit(benchmark::kMicrosecond);
593 Intersection_MediumAsymmetric,
594 RegionOp::kIntersection,
595 false,
596 400,
598 ->Unit(benchmark::kMicrosecond);
600 Intersection_MediumAsymmetric,
601 RegionOp::kIntersection,
602 false,
603 400,
605 ->Unit(benchmark::kMicrosecond);
607 Intersection_LargeAsymmetric,
608 RegionOp::kIntersection,
609 false,
610 1500,
612 ->Unit(benchmark::kMicrosecond);
614 Intersection_LargeAsymmetric,
615 RegionOp::kIntersection,
616 false,
617 1500,
619 ->Unit(benchmark::kMicrosecond);
620
622 Intersection_SingleRect_Tiny,
623 RegionOp::kIntersection,
624 true,
625 30,
626 1.0)
627 ->Unit(benchmark::kMicrosecond);
629 Intersection_SingleRect_Tiny,
630 RegionOp::kIntersection,
631 true,
632 30,
633 1.0)
634 ->Unit(benchmark::kMicrosecond);
636 Intersection_SingleRect_Small,
637 RegionOp::kIntersection,
638 true,
639 100,
640 1.0)
641 ->Unit(benchmark::kMicrosecond);
643 Intersection_SingleRect_Small,
644 RegionOp::kIntersection,
645 true,
646 100,
647 1.0)
648 ->Unit(benchmark::kMicrosecond);
650 Intersection_SingleRect_Medium,
651 RegionOp::kIntersection,
652 true,
653 400,
654 1.0)
655 ->Unit(benchmark::kMicrosecond);
657 Intersection_SingleRect_Medium,
658 RegionOp::kIntersection,
659 true,
660 400,
661 1.0)
662 ->Unit(benchmark::kMicrosecond);
664 Intersection_SingleRect_Large,
665 RegionOp::kIntersection,
666 true,
667 1500,
668 1.0)
669 ->Unit(benchmark::kMicrosecond);
671 Intersection_SingleRect_Large,
672 RegionOp::kIntersection,
673 true,
674 1500,
675 1.0)
676 ->Unit(benchmark::kMicrosecond);
677
679 ->Unit(benchmark::kMicrosecond);
681 ->Unit(benchmark::kMicrosecond);
683 ->Unit(benchmark::kMicrosecond);
685 ->Unit(benchmark::kMicrosecond);
687 ->Unit(benchmark::kMicrosecond);
689 ->Unit(benchmark::kMicrosecond);
691 ->Unit(benchmark::kMicrosecond);
693 ->Unit(benchmark::kMicrosecond);
694
696 ->Unit(benchmark::kMicrosecond);
698 ->Unit(benchmark::kMicrosecond);
700 ->Unit(benchmark::kMicrosecond);
702 ->Unit(benchmark::kMicrosecond);
704 ->Unit(benchmark::kMicrosecond);
706 ->Unit(benchmark::kMicrosecond);
708 ->Unit(benchmark::kMicrosecond);
710 ->Unit(benchmark::kMicrosecond);
711
712} // namespace flutter
SkPoint pos
@ kUnion_Op
target unioned with operand
Definition: SkRegion.h:369
@ kIntersect_Op
target intersected with operand
Definition: SkRegion.h:368
static DlRegion MakeIntersection(const DlRegion &a, const DlRegion &b)
Definition: dl_region.cc:497
static DlRegion MakeUnion(const DlRegion &a, const DlRegion &b)
Definition: dl_region.cc:405
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
AtkStateType state
GAsyncResult * result
#define FML_DCHECK(condition)
Definition: logging.h:103
static float min(float r, float g, float b)
Definition: hsl.cpp:48
Optional< SkRect > bounds
Definition: SkRecords.h:189
ClipOpAndAA opAA SkRegion region
Definition: SkRecords.h:238
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
static void BM_DlRegion_Operation(benchmark::State &state, RegionOp op, bool withSingleRect, int maxSize, double sizeFactor)
static void BM_SkRegion_IntersectsSingleRect(benchmark::State &state, int maxSize)
static void BM_DlRegion_GetRects(benchmark::State &state, int maxSize)
static void BM_SkRegion_FromRects(benchmark::State &state, int maxSize)
static void BM_SkRegion_GetRects(benchmark::State &state, int maxSize)
static void BM_DlRegion_IntersectsRegion(benchmark::State &state, int maxSize, double sizeFactor)
const double kSizeFactorSmall
static void BM_DlRegion_FromRects(benchmark::State &state, int maxSize)
static void BM_SkRegion_Operation(benchmark::State &state, RegionOp op, bool withSingleRect, int maxSize, double sizeFactor)
static void BM_SkRegion_IntersectsRegion(benchmark::State &state, int maxSize, double sizeFactor)
static void BM_DlRegion_IntersectsSingleRect(benchmark::State &state, int maxSize)
BENCHMARK_CAPTURE(BM_DisplayListBuilderDefault, kDefault, DisplayListBuilderBenchmarkType::kDefault) -> Unit(benchmark::kMicrosecond)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: ref_ptr.h:256
int32_t height
int32_t width
Definition: SkRect.h:32
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104