Skip to content

Commit 5b6444f

Browse files
authored
[web] benchmark and optimize defaultTargetPlatform (flutter#75037)
1 parent 4ba2619 commit 5b6444f

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2014 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+
import 'package:flutter/foundation.dart';
6+
7+
import 'recorder.dart';
8+
9+
/// Benchmarks the performance of the [defaultTargetPlatform] getter.
10+
///
11+
/// The getter relies on the expensive `window.matchMedia` and if not properly
12+
/// cached can cause performance issues.
13+
class BenchDefaultTargetPlatform extends RawRecorder {
14+
BenchDefaultTargetPlatform() : super(name: benchmarkName);
15+
16+
static const String benchmarkName = 'default_target_platform';
17+
18+
/// A dummy counter just to make sure the compiler doesn't inline the
19+
/// benchmark and make it a no-op.
20+
int counter = 0;
21+
22+
@override
23+
void body(Profile profile) {
24+
profile.record('runtime', () {
25+
for (int i = 0; i < 10000; i++) {
26+
counter += defaultTargetPlatform.index;
27+
}
28+
}, reported: true);
29+
}
30+
}

dev/benchmarks/macrobenchmarks/lib/web_benchmarks.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'src/web/bench_build_material_checkbox.dart';
1515
import 'src/web/bench_card_infinite_scroll.dart';
1616
import 'src/web/bench_child_layers.dart';
1717
import 'src/web/bench_clipped_out_pictures.dart';
18+
import 'src/web/bench_default_target_platform.dart';
1819
import 'src/web/bench_draw_rect.dart';
1920
import 'src/web/bench_dynamic_clip_on_static_picture.dart';
2021
import 'src/web/bench_mouse_region_grid_hover.dart';
@@ -37,6 +38,7 @@ const bool isCanvasKit = bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultVal
3738
/// When adding a new benchmark, add it to this map. Make sure that the name
3839
/// of your benchmark is unique.
3940
final Map<String, RecorderFactory> benchmarks = <String, RecorderFactory>{
41+
BenchDefaultTargetPlatform.benchmarkName: () => BenchDefaultTargetPlatform(),
4042
BenchBuildImage.benchmarkName: () => BenchBuildImage(),
4143
BenchCardInfiniteScroll.benchmarkName: () => BenchCardInfiniteScroll.forward(),
4244
BenchCardInfiniteScroll.benchmarkNameBackward: () => BenchCardInfiniteScroll.backward(),

packages/flutter/lib/src/foundation/_platform_web.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ platform.TargetPlatform get defaultTargetPlatform {
1010
// To get a better guess at the targetPlatform we need to be able to reference
1111
// the window, but that won't be available until we fix the platforms
1212
// configuration for Flutter.
13-
platform.TargetPlatform result = _browserPlatform();
14-
if (platform.debugDefaultTargetPlatformOverride != null)
15-
result = platform.debugDefaultTargetPlatformOverride!;
16-
return result;
13+
return platform.debugDefaultTargetPlatformOverride ?? _browserPlatform;
1714
}
1815

19-
platform.TargetPlatform _browserPlatform() {
16+
// Lazy-initialized and forever cached current browser platform.
17+
//
18+
// Computing the platform is expensive as it uses `window.matchMedia`, which
19+
// needs to parse and evaluate a CSS selector. On some devices this takes up to
20+
// 0.20ms. As `defaultTargetPlatform` is routinely called dozens of times per
21+
// frame this value should be cached.
22+
final platform.TargetPlatform _browserPlatform = () {
2023
final String navigatorPlatform = html.window.navigator.platform?.toLowerCase() ?? '';
2124
if (navigatorPlatform.startsWith('mac')) {
2225
return platform.TargetPlatform.macOS;
@@ -41,4 +44,4 @@ platform.TargetPlatform _browserPlatform() {
4144
return platform.TargetPlatform.linux;
4245
}
4346
return platform.TargetPlatform.android;
44-
}
47+
}();

0 commit comments

Comments
 (0)