I am running my application in development (debug) mode on local machine so I'm not sure how much this affects network requests. The target device where the app is running is Android emulator. I have an endpoint which fetches some data, this data can be quite large, it's a large-ish JSON that gets parsed into data structure (class) in my application code.
I am experiencing a problem where sometimes these requests time out (my timeout is set at 30s) even though the actual response is less than 5s. I am attaching a screenshot from dev tools where you can see that the duration of the request is 25 seconds which is just too much. I think time to first byte (TTFB) is the actual time before it starts receiving the data, so the server code is not slow. I don't understand how the "end" time is calculated though.
My internet connection (download) is about 50-70Mbit/s (ADSL).
Screenshot:
What do you think could be the cause for such a long duration of request to be completed? Could it be the size of payload? Or does the framework (Flutter) take a long time to process the response?
I'm using dio² http client to make my requests so not sure if that plays any role. I tried optimising the path where I'm converting JSON response payload into data objects (classes) stored in memory¹ but that doesn't seem to help. I don't think I'm using any weird code pattern³ as all of the other parts of my app are performant.
Unfortunately I can't easily reproduce the situation of what the screenshot is displaying but when I tried doing it, the payload size was over 1MB and in that scenario I believe it could be over 2MB which is pretty large for JSON.
flutter doctor -v output:
[✓] Flutter (Channel stable, 2.8.1, on macOS 11.6.1 20G224 darwin-x64, locale en-CZ)
• Flutter version 2.8.1 at /Users/user/fvm/versions/2.8.1
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 77d935af4d (6 weeks ago), 2021-12-16 08:37:33 -0800
• Engine revision 890a5fca2e
• Dart version 2.15.1
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at /Users/user/Library/Android/sdk
• Platform android-31, build-tools 31.0.0
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.11.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2020.3)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
[✓] IntelliJ IDEA Community Edition (version 2020.2.1)
• IntelliJ at /Applications/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.58.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension can be installed from:
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (2 available)
• SM A505FN (mobile) • XXXXXXX • android-arm64 • Android 11 (API 30)
• Chrome (web) • chrome • web-javascript • Google Chrome 97.0.4692.99
• No issues found!
¹ I receive list of objects in the JSON response. These objects have nested object lists. One of the lists are GPS coordinates that form a path so there can be lot of them. However I need just one list of coordinates from the list of objects so I just dropped the other ones before converting them to my data structures so it basically cuts down 90% of the previous unoptimized size.
² Version 4.0.0
³ It's a regular Flutter app where all widgets come from material.dart module. The network calls are triggered outside of UI by usage of BLoC pattern (via flutter_bloc lib). Each API call has its own event belonging to some BLoC.
The actual API call is performed by a instance of wrapper class that contains an instance of dio client and passes the result to relevant BLoC. The instances of wrapper classes and dio instances are created via dependency injection. Wrapper classes are singletons, dio instances are created once for each of these wrapper classes. The creation of these classes happens before the runApp.
