Add await to callsites of BasicMessageChannel.send#182868
Add await to callsites of BasicMessageChannel.send#182868auto-submit[bot] merged 17 commits intoflutter:masterfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request adds await to callsites of BasicMessageChannel.send, which is now an async method. The changes are generally correct and necessary. However, I've found a couple of issues in the benchmark file dev/benchmarks/platform_channels_benchmarks/lib/main.dart. One change introduces a performance regression by serializing parallel operations, and another uses an async/await anti-pattern. I've provided suggestions to fix these issues.
| await basicStandard.send(payload).then((Object? result) { | ||
| _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload); | ||
| }); |
There was a problem hiding this comment.
Adding await inside this loop makes it sequential, which defeats the purpose of the _runBasicStandardParallel benchmark. Each iteration now waits for the send operation to complete before starting the next, removing the parallelism.
To restore the parallel behavior, the await should be removed.
basicStandard.send(payload).then((Object? result) {
_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
});There was a problem hiding this comment.
Use await Future.forEach() or Future.wait instead.
| await basicStandard.send(payload).then((Object? result) { | ||
| _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload); | ||
| }); |
There was a problem hiding this comment.
Using await with .then() is an anti-pattern in modern Dart as it can be expressed more clearly using async/await. This also avoids creating a Future<Future<void>> which is likely not intended.
await basicStandard.send(payload);
_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);There was a problem hiding this comment.
This future should have a .catch that reports error.
There was a problem hiding this comment.
Is the current impl satisfactory?
| basicStandard.send(payload).then((Object? result) { | ||
| _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload); | ||
| }); | ||
| await Future.wait([ |
There was a problem hiding this comment.
Future.wait is meant to run tasks in parallel and wait for the completion of all of them.
You should replace the entire for loop with something like (psuedocode):
await Future.wait(List.generate(parallel, (_) => () async {
await basicStandard.send(payload);
await _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
}));| await Future.wait( | ||
| Iterable.generate(parallel, (_) async { | ||
| await basicStandard.send(payload); | ||
| // ignore: unawaited_futures |
There was a problem hiding this comment.
Ignoring because recursive method is intended to run in parallel
There was a problem hiding this comment.
Are you sure we can't have await here? I think this still runs in parallel even if you use await, since Iterable.generate runs everything at the same time. In other words, each (_) async { ... } runs in parallel.
| _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload); | ||
| }); | ||
| await basicStandard.send(payload); | ||
| _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload); |
| @@ -68,11 +67,12 @@ Future<double> _runBasicStandardParallel( | |||
| final completer = Completer<int>(); | |||
| final counter = _Counter(); | |||
| watch.start(); | |||
| for (var i = 0; i < parallel; ++i) { | |||
| basicStandard.send(payload).then((Object? result) { | |||
| _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload); | |||
| }); | |||
| } | |||
| await Future.wait( | |||
| Iterable.generate(parallel, (_) async { | |||
| await basicStandard.send(payload); | |||
| await _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload); | |||
| }), | |||
| ); | |||
There was a problem hiding this comment.
I'm sorry but I just realized that we might have been doing something wrong. _runBasicStandardParallelRecurse is using its completer parameter as the async control, and shouldn't need additional Future return value.
(I suspect that this entire function is basically reinventing Future.wait from scratch.)
In short, I think the original implementation is probably completely correct and we shouldn't change it at all. It doesn't have anything that violate the lint either, right? All futures either has .then or is awaited.
Roll Flutter from 46fb7210422d to d3dd7744e81f (33 revisions) flutter/flutter@46fb721...d3dd774 2026-03-04 [email protected] Show warning when plugins do not support SwiftPM (flutter/flutter#182506) 2026-03-04 [email protected] Give guided message when project is not compatible with SwiftPM (flutter/flutter#182394) 2026-03-04 [email protected] Pass --web-define through to web runner when using --machine mode (flutter/flutter#183228) 2026-03-04 [email protected] Improve SwiftPM minimum platform mismatch diagnostics (flutter/flutter#182375) 2026-03-04 [email protected] Use dart::bin::SetupDartIo to setup dart:io (flutter/flutter#176714) 2026-03-04 [email protected] Roll Skia from 3197848b14ad to ada0b7628c79 (5 revisions) (flutter/flutter#183221) 2026-03-04 [email protected] Roll Skia from fe9e9f22c531 to 3197848b14ad (15 revisions) (flutter/flutter#183198) 2026-03-04 [email protected] refactor: remove material in reorderable_list_test, scroll_notification_test, scroll_physics_test, shortcuts_test, sliver_floating_header_test, snapshot_widget_test (flutter/flutter#182698) 2026-03-04 [email protected] refactor: remove material in pop_scope_test, route_notification_message_test, two_dimensional_utils, two_dimensional_viewport_test (flutter/flutter#182699) 2026-03-04 [email protected] Add dev/benchmarks/README.md (flutter/flutter#182976) 2026-03-03 [email protected] Roll RapidJSON to a branch based on the current upstream head (flutter/flutter#183048) 2026-03-03 [email protected] [Impeller] Update comments to reflect new info about 2-pass rendering (flutter/flutter#183050) 2026-03-03 [email protected] Add vmservices for accessibilityEvaluation (flutter/flutter#182791) 2026-03-03 [email protected] Roll Fuchsia Linux SDK from 0dCDM2oORHwDf_pyb... to JJw5EJ87vLGqFVl4h... (flutter/flutter#183177) 2026-03-03 [email protected] Support mixed color spaces in `Color.lerp` (flutter/flutter#182934) 2026-03-03 [email protected] Add warning when there is a widget with color between `Material` and `ListTile` (flutter/flutter#181402) 2026-03-03 [email protected] [ios]uitest for admob banner in scrollable list gesture issue (flutter/flutter#183128) 2026-03-03 [email protected] Roll Packages from faa4e22 to 9083bc9 (4 revisions) (flutter/flutter#183164) 2026-03-03 [email protected] Build App and native asset frameworks for Add to App FlutterPluginRegistrant (flutter/flutter#183136) 2026-03-03 [email protected] Roll Skia from f886711f180d to fe9e9f22c531 (4 revisions) (flutter/flutter#183155) 2026-03-03 [email protected] Roll Dart SDK from e86dbe9aa742 to c597ef90d2dc (2 revisions) (flutter/flutter#183147) 2026-03-03 [email protected] fix: bump matcher (flutter/flutter#183167) 2026-03-02 [email protected] Use isA to test for exceptions (flutter/flutter#183129) 2026-03-02 [email protected] [two_dimensional_scrollables] Fix tableview janks when first row/column pinned (flutter/flutter#180563) 2026-03-02 [email protected] Add await to callsites of BasicMessageChannel.send (flutter/flutter#182868) 2026-03-02 [email protected] Roll pub packages (flutter/flutter#183133) 2026-03-02 [email protected] Improve FFI code for windowing (flutter/flutter#183098) 2026-03-02 [email protected] [workflow] Update the changelog merge action to fetch the stable branch (flutter/flutter#183132) 2026-03-02 [email protected] Roll Skia from e180358b7a7a to f886711f180d (2 revisions) (flutter/flutter#183130) 2026-03-02 [email protected] Merge changelog from 3.41.3. (flutter/flutter#183131) 2026-03-02 [email protected] Make TextDecoration final and unify maskValue across platforms (flutter/flutter#183070) 2026-03-02 [email protected] Roll pub packages (flutter/flutter#182640) 2026-03-02 [email protected] Enable SwiftPM by default on master and beta (flutter/flutter#182923) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: ...
Impl:
```dart
/// Sends the specified [message] to the platform plugins on this channel.
///
/// Returns a [Future] which completes to the received response, which may
/// be null.
Future<T?> send(T message) async {
return codec.decodeMessage(await binaryMessenger.send(name, codec.encodeMessage(message)));
}
```
Part of flutter#181513
Impl:
Part of #181513