Skip to content

Instantly share code, notes, and snippets.

@lukepighetti
Last active February 27, 2023 17:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukepighetti/617fba9bf192ba3b49bfb8cf9a0106ae to your computer and use it in GitHub Desktop.
Save lukepighetti/617fba9bf192ba3b49bfb8cf9a0106ae to your computer and use it in GitHub Desktop.

I was trying to do some performance profiling of our production app and I noticed a certain function was taking a lot more time than I expected (350ms vs 1ms), so I started to dig deeper. In doing so, it looked like if I changed that function from a Future<String> to a String with no other code changes (it could have been written as a FutureOr), the execution time of that code branch reduced to expected levels.

I posted about this on Twitter and created a reproduction.

https://twitter.com/luke_pighetti/status/1630255285372633089?s=20

This code runs in a fresh Flutter app on iOS Simulator.

It almost looks like a flurry of concurrent Futures are queueing up and delaying other futures.

import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
asyncInit();
super.initState();
}
Future<void> asyncInit() async {
await Future.wait([
for (var i = 0; i < 10; i++) ...[
asyncParent(),
],
]);
print('---------------------');
await Future.wait([
for (var i = 0; i < 10; i++) ...[
syncParent(),
],
]);
print('---------------------');
await asyncParent();
}
Future<String> asyncParent() async {
final s = Stopwatch()..start();
final result = await asyncChild();
s.stop();
print('asyncParent: ${s.elapsedMilliseconds}');
return result;
}
Future<String> asyncChild() async {
final s = Stopwatch()..start();
const result = 'foo';
s.stop();
print('asyncChild: ${s.elapsedMilliseconds}');
return result;
}
Future<String> syncParent() async {
final s = Stopwatch()..start();
final result = syncChild();
s.stop();
print('syncParent: ${s.elapsedMilliseconds}');
return result;
}
String syncChild() {
final s = Stopwatch()..start();
const result = 'foo';
s.stop();
print('syncChild: ${s.elapsedMilliseconds}');
return result;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Foo'),
),
);
}
}
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncChild: 0
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: asyncParent: 30
flutter: ---------------------
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: syncChild: 0
flutter: syncParent: 0
flutter: ---------------------
flutter: asyncChild: 0
flutter: asyncParent: 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment