firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.63k stars 3.95k forks source link

Firestore transaction latency, huge difference between web and mobile #8623

Closed DanielBFox closed 1 year ago

DanielBFox commented 2 years ago

Discussed in https://github.com/firebase/flutterfire/discussions/8549

Originally posted by **DanielBFox** April 29, 2022 I couple of months ago I decided to use flutter/firebase/firestore on a brand new app. I started to develop it for the web platform and everything was ok about the firestore performances. Now I'm developing the android version (basically it's the same code for all the DB services) and the firestore performances are not good at all. Concretely, I observe a huge difference when running the same transaction (same wifi connection) on any web browser and on android devices. On the web, it takes less than 150ms to run it : > js_primitives.dart:47 @@@Before transaction **2022-04-25 11:25:11.539** js_primitives.dart:47 @@@Start transaction 2022-04-25 11:25:11.573 js_primitives.dart:47 @@@After seed get 2022-04-25 11:25:11.637 js_primitives.dart:47 @@@after tag get 2022-04-25 11:25:11.638 js_primitives.dart:47 @@@after set counter 2022-04-25 11:25:11.639 js_primitives.dart:47 @@@after set plant 2022-04-25 11:25:11.643 js_primitives.dart:47 @@@after set tag 2022-04-25 11:25:11.644 js_primitives.dart:47 @@@after set post 2022-04-25 11:25:11.645 js_primitives.dart:47 @@@After transaction **2022-04-25 11:25:11.718** On a galaxy j6 with android 10, it takes 2.5 seconds to run it : > I/flutter (10627): @@@Before transaction **2022-04-25 08:58:44.577700** I/flutter (10627): @@@Start transaction 2022-04-25 08:58:44.619733 I/flutter (10627): @@@After seed get 2022-04-25 08:58:47.067945 I/flutter (10627): @@@after tag get 2022-04-25 08:58:47.068416 I/flutter (10627): @@@after set counter 2022-04-25 08:58:47.068670 I/flutter (10627): @@@after set plant 2022-04-25 08:58:47.068998 I/flutter (10627): @@@after set tag 2022-04-25 08:58:47.069214 I/flutter (10627): @@@after set post **2022-04-25 08:58:47.069472** On a galaxy A40 with android 11, it takes more that 12 seconds : I/flutter (30636): @@@Before transaction **2022-04-2415:38:43.237485** I/flutter (30636): @@@Start transaction 2022-04-24 15:38:43.549120 I/flutter (30636): @@@After seed get 2022-04-24 15:38:49.340047 I/flutter (30636): @@@after tag get 2022-04-24 15:38:49.341779 I/flutter (30636): @@@after set counter 2022-04-24 15:38:49.342491 I/flutter (30636): @@@after set plant 2022-04-24 15:38:49.377040 I/flutter (30636): @@@after set tag 2022-04-24 15:38:49.377556 I/flutter (30636): @@@after set post 2022-04-24 15:38:49.391190 I/flutter (30636): @@@After transaction **2022-04-2415:38:55.602388** Here is the code of the transaction : ``` Future sowInNursery({ required String farmName, required String specieName, required String varietyName, required String providerName, required String seedId, required Timestamp dateTime, String? tagName, int? quantity, String? farmPhotoUrl, required String farmerUid, String? farmerPhotoUrl, String? farmerDisplayName, Timestamp? seedReproductionDateTime, required String languageCode, }) async { late DocumentReference tagDocumentReference; if (tagName != null) { tagDocumentReference = getTagDocumentReference(farmName, tagName); } DocumentReference seedDocumentReference = getSeedDocumentReference( farmName, specieName, varietyName, providerName, seedId); DocumentReference plantDocumentReference = getPlantDocumentReferenceWithAutoGeneratedId( farmName, specieName, varietyName, providerName, seedId); DocumentReference counterDocumentReference = getCounterDocumentReference( farmName, specieName, varietyName, dateTime); DocumentReference postDocumentReference = getPostDocumentReferenceWithAutoGeneratedId(farmName); doc.Plant plant = doc.Plant( farm: farmName, specie: specieName, variety: varietyName, provider: providerName, seed: seedId, name: plantDocumentReference.id, seedReproductionDateTime: seedReproductionDateTime, stages: doc.Stages( nurserySowedStage: doc.NurserySowedStage( dateTime: dateTime, tag: tagName, farmerUid: farmerUid, stockItem: doc.StockItem.forNurserySowing(quantity)))) ..lifecycleStages = [pb.LifecycleStage.NURSERY_SOWED] ..plantActions = [pb.PlantAction.SOW_IN_NURSERY]; doc.Post post = doc.Post( farm: farmName, name: postDocumentReference.id, dateTime: dateTime, updateDateTime: dateTime, farmerUid: farmerUid, farmerPhotoUrl: farmPhotoUrl, farmerDisplayName: farmerDisplayName, farmPhotoUrl: farmPhotoUrl, stagePostType: doc.StagePostType( counterLifecycleStage: pb.CounterLifecycleStage.NURSERY_SOWINGS, specie: specieName, variety: varietyName, stockItem: doc.StockItem.forTransplant(quantity))); doc.Plant document = await firebaseService.firestore.runTransaction((transaction) async { print("@@@Start transaction ${DateTime.now()}"); // Read the seed doc DocumentSnapshot seedSnapshot = await transaction.get(seedDocumentReference); if (!seedSnapshot.exists) { throw Exception("La graine ${seedDocumentReference.id} n'existe pas"); } doc.Seed seed = doc.Seed.fromJson(seedSnapshot.data()! as Map); print("@@@After seed get ${DateTime.now()}"); // Read the tag doc late doc.Tag tag; if (tagName != null) { DocumentSnapshot tagSnapshot = await transaction.get(tagDocumentReference); if (!tagSnapshot.exists) { throw Exception( "L'étiquette ${tagDocumentReference.id} n'existe pas"); } tag = doc.Tag.fromJson(tagSnapshot.data()! as Map); } print("@@@after tag get ${DateTime.now()}"); // Update the counter doc if (quantity != null) { DocumentSnapshot counterSnapshot = await transaction.get(counterDocumentReference); doc.Counter? counter; if (counterSnapshot.exists) { counter = doc.Counter.fromJson( counterSnapshot.data()! as Map); } counter = updateCounterDocument( counter, farmName, specieName, varietyName, counterDocumentReference.id, 1, doc.StockItem.forNurserySowing(quantity)!, pb.CounterLifecycleStage.NURSERY_SOWINGS); transaction.set(counterDocumentReference, counter.toJson()); } print("@@@after set counter ${DateTime.now()}"); // Create the plant doc transaction.set(plantDocumentReference, plant.toJson()); print("@@@after set plant ${DateTime.now()}"); // Update the tag doc if (tagName != null) { tag.taggedPlants.add(doc.TaggedPlant( plant: doc.Plant( farm: farmName, specie: specieName, variety: varietyName, provider: providerName, seed: seedId, name: plantDocumentReference.id, ), counter: 1)); transaction.set(tagDocumentReference, tag.toJson()); } print("@@@after set tag ${DateTime.now()}"); // Create the post doc transaction.set(postDocumentReference, post.toJson()); print("@@@after set post ${DateTime.now()}"); return plant; }); return document; } ```
DanielBFox commented 2 years ago

Each get returns only 1 single document. And each collection used in the transaction contains at most 10 documents

darshankawar commented 2 years ago

@DanielBFox In order to address this issue properly, please provide flutter doctor -v, plugin version you are using along with a minimal reproducible code sample that shows the behavior between web and mobile as you reported.

DanielBFox commented 2 years ago

flutter doctor -v

[✓] Flutter (Channel stable, 2.10.0, on Ubuntu 20.04.3 LTS 5.11.0-38-generic, locale fr_BE.UTF-8)
    • Flutter version 2.10.0 at /home/daniel/development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 5f105a6ca7 (il y a 3 mois), 2022-02-01 14:15:42 -0800
    • Engine revision 776efd2034
    • Dart version 2.16.0
    • DevTools version 2.9.2

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at /home/daniel/Android/Sdk
    • Platform android-31, build-tools 31.0.0
    • ANDROID_HOME = /home/daniel/Android/Sdk
    • Java binary at: /usr/local/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✓] Android Studio (version 2020.3)
    • Android Studio at /usr/local/android-studio
    • Flutter plugin version 61.2.2
    • Dart plugin version 203.8452
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)

[✓] VS Code (version 1.63.2)
    • VS Code at /usr/share/code
    • Flutter extension version 3.36.0

[✓] Connected device (2 available)
    • SM A405FN (mobile) • R58N14GZWPW • android-arm64  • Android 11 (API 30)
    • Chrome (web)       • chrome      • web-javascript • Google Chrome 97.0.4692.71

[✓] HTTP Host Availability
    • All required HTTP hosts are available

flutter pub deps -- --style=compact

Dart SDK 2.16.0
Flutter SDK 2.10.0
mygardenpro 1.0.0+1

dependencies:
- badges 2.0.2 [flutter]
- cached_network_image 3.2.0 [flutter flutter_cache_manager octo_image cached_network_image_platform_interface cached_network_image_web]
- carousel_slider 4.0.0 [flutter]
- core 0.0.6+0 [flutter flutter_riverpod shared_preferences json_annotation protobuf grpc decimal firebase_storage cloud_firestore timeago intl package_info_plus]
- cupertino_icons 1.0.4
- dropdown_button2 1.2.2 [flutter]
- firebase_app_check 0.0.6+7 [firebase_app_check_platform_interface firebase_app_check_web firebase_core firebase_core_platform_interface flutter]
- firebase_auth 3.3.9 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta]
- firebase_core 1.13.1 [firebase_core_platform_interface firebase_core_web flutter meta]
- firebase_messaging 11.2.8 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta]
- firebase_storage 10.2.9 [firebase_core firebase_core_platform_interface firebase_storage_platform_interface firebase_storage_web flutter]
- flutter 0.0.0 [characters collection material_color_utilities meta typed_data vector_math sky_engine]
- flutter_form_builder 7.1.1 [flutter intl collection]
- flutter_launcher_icons 0.9.2 [args image path yaml]
- flutter_local_notifications 9.3.3 [clock flutter flutter_local_notifications_linux flutter_local_notifications_platform_interface timezone]
- flutter_localizations 0.0.0 [flutter intl characters clock collection material_color_utilities meta path typed_data vector_math]
- flutter_native_splash 1.3.3 [args image meta path xml yaml universal_io]
- flutter_riverpod 1.0.3 [collection flutter meta riverpod state_notifier]
- flutterfire_ui 0.3.5+1 [cloud_firestore collection crypto desktop_webview_auth email_validator firebase_auth firebase_core firebase_database firebase_dynamic_links flutter flutter_facebook_auth flutter_localizations flutter_svg google_sign_in sign_in_with_apple twitter_login]
- form_builder_validators 7.6.1 [flutter flutter_localizations intl collection]
- freezed 1.1.1 [analyzer build build_config collection meta source_gen freezed_annotation]
- freezed_annotation 1.1.0 [collection json_annotation meta]
- geoflutterfire 3.0.3 [flutter cloud_firestore rxdart flutter_lints]
- google_maps_flutter 2.1.3 [flutter flutter_plugin_android_lifecycle google_maps_flutter_platform_interface]
- grpc 3.0.2 [archive async crypto fixnum googleapis_auth meta http http2 protobuf]
- image_picker 0.8.4+10 [flutter flutter_plugin_android_lifecycle image_picker_for_web image_picker_platform_interface]
- intl 0.17.0 [clock path]
- json_annotation 4.4.0 [meta]
- linked_scroll_controller 0.2.0 [flutter]
- material_design_icons_flutter 5.0.6595 [flutter]
- protobuf 2.0.1 [fixnum collection]
- rflutter_alert 2.0.4 [flutter]
- scrollable_positioned_list 0.2.3 [flutter collection]
- stack 0.2.1
- stream_chat_flutter 3.6.1 [cached_network_image characters chewie collection diacritic dio ezanimation file_picker flutter flutter_markdown flutter_portal flutter_slidable flutter_svg http_parser image_gallery_saver image_picker jiffy lottie meta path_provider photo_manager photo_view rxdart share_plus shimmer stream_chat_flutter_core substring_highlight synchronized url_launcher video_compress video_player video_thumbnail]
- stream_chat_flutter_core 3.6.1 [collection connectivity_plus flutter meta rxdart stream_chat]
- stream_chat_localizations 2.1.0 [flutter flutter_localizations stream_chat_flutter]
- timelines 0.1.0 [flutter]
- timer_builder 2.0.0 [flutter]
- toggle_switch 2.0.1 [flutter]
- tuple 2.0.0 [quiver]
- week_of_year 2.0.0

dev dependencies:
- build_runner 2.1.7 [args async analyzer build build_config build_daemon build_resolvers build_runner_core code_builder collection crypto dart_style frontend_server_client glob graphs http_multi_server io js logging meta mime package_config path pool pub_semver pubspec_parse shelf shelf_web_socket stack_trace stream_transform timing watcher web_socket_channel yaml]
- flutter_lints 1.0.4 [lints]
- flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher material_color_utilities meta source_span stream_channel string_scanner term_glyph typed_data]
- json_serializable 6.1.5 [analyzer async build build_config collection json_annotation meta path pub_semver pubspec_parse source_gen source_helper]

transitive dependencies:
- _fe_analyzer_shared 36.0.0 [meta]
- analyzer 3.3.1 [_fe_analyzer_shared collection convert crypto glob meta package_config path pub_semver source_span watcher yaml]
- archive 3.2.1 [crypto path]
- args 2.3.0
- asn1lib 1.1.0
- async 2.8.2 [collection meta]
- boolean_selector 2.1.0 [source_span string_scanner]
- build 2.2.1 [analyzer async convert crypto glob logging meta path]
- build_config 1.0.0 [checked_yaml json_annotation path pubspec_parse yaml]
- build_daemon 3.0.1 [built_collection built_value http_multi_server logging path pool shelf shelf_web_socket stream_transform watcher web_socket_channel]
- build_resolvers 2.0.6 [analyzer async build crypto graphs logging path package_config pool pub_semver stream_transform yaml]
- build_runner_core 7.2.3 [async build build_config build_resolvers collection convert crypto glob graphs json_annotation logging meta path package_config pool timing watcher yaml]
- built_collection 5.1.1
- built_value 8.1.4 [built_collection collection fixnum meta]
- cached_network_image_platform_interface 1.0.0 [flutter flutter_cache_manager]
- cached_network_image_web 1.0.1 [flutter flutter_cache_manager cached_network_image_platform_interface]
- characters 1.2.0
- charcode 1.3.1
- checked_yaml 2.0.1 [json_annotation source_span yaml]
- chewie 1.3.2 [cupertino_icons flutter provider video_player wakelock very_good_analysis]
- clock 1.1.0
- cloud_firestore 3.1.13 [cloud_firestore_platform_interface cloud_firestore_web collection firebase_core firebase_core_platform_interface flutter meta]
- cloud_firestore_platform_interface 5.5.4 [collection firebase_core flutter meta plugin_platform_interface]
- cloud_firestore_web 2.6.13 [cloud_firestore_platform_interface collection firebase_core firebase_core_web flutter flutter_web_plugins js]
- code_builder 4.1.0 [built_collection built_value collection matcher meta]
- collection 1.15.0
- connectivity_plus 2.3.0 [flutter connectivity_plus_platform_interface connectivity_plus_linux connectivity_plus_macos connectivity_plus_web connectivity_plus_windows]
- connectivity_plus_linux 1.3.0 [flutter connectivity_plus_platform_interface meta nm]
- connectivity_plus_macos 1.2.2 [connectivity_plus_platform_interface flutter]
- connectivity_plus_platform_interface 1.2.0 [flutter meta plugin_platform_interface]
- connectivity_plus_web 1.2.0 [connectivity_plus_platform_interface flutter_web_plugins flutter]
- connectivity_plus_windows 1.2.0 [connectivity_plus_platform_interface flutter]
- convert 3.0.1 [typed_data]
- cross_file 0.3.2 [flutter js meta]
- crypto 3.0.1 [collection typed_data]
- crypto_keys 0.3.0 [pointycastle meta collection quiver]
- csslib 0.17.1 [source_span]
- dart_style 2.2.1 [analyzer args path pub_semver source_span]
- dbus 0.7.1 [args ffi meta xml]
- decimal 1.5.0 [rational]
- desktop_webview_auth 0.0.5 [crypto flutter http]
- diacritic 0.1.3
- dio 4.0.6 [http_parser path]
- email_validator 2.0.1
- equatable 2.0.3 [collection meta]
- ezanimation 0.6.0 [flutter]
- fake_async 1.2.0 [clock collection]
- ffi 1.1.2
- file 6.1.2 [meta path]
- file_picker 4.5.1 [flutter flutter_web_plugins flutter_plugin_android_lifecycle plugin_platform_interface ffi path win32]
- firebase_app_check_platform_interface 0.0.4+1 [firebase_core flutter meta plugin_platform_interface]
- firebase_app_check_web 0.0.5+7 [firebase_app_check_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js]
- firebase_auth_platform_interface 6.2.1 [firebase_core flutter meta plugin_platform_interface]
- firebase_auth_web 3.3.9 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser intl js meta]
- firebase_core_platform_interface 4.2.5 [collection flutter meta plugin_platform_interface]
- firebase_core_web 1.6.2 [firebase_core_platform_interface flutter flutter_web_plugins js meta]
- firebase_database 9.0.8 [firebase_core firebase_core_platform_interface firebase_database_platform_interface firebase_database_web flutter]
- firebase_database_platform_interface 0.2.1+1 [collection firebase_core flutter meta plugin_platform_interface]
- firebase_database_web 0.2.0+7 [firebase_core firebase_core_web firebase_database_platform_interface flutter flutter_web_plugins js]
- firebase_dynamic_links 4.0.8 [firebase_core firebase_core_platform_interface firebase_dynamic_links_platform_interface flutter meta plugin_platform_interface]
- firebase_dynamic_links_platform_interface 0.2.1+1 [firebase_core flutter meta plugin_platform_interface]
- firebase_messaging_platform_interface 3.2.1 [firebase_core flutter meta plugin_platform_interface]
- firebase_messaging_web 2.2.9 [firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins js meta]
- firebase_storage_platform_interface 4.1.1 [collection firebase_core flutter meta plugin_platform_interface]
- firebase_storage_web 3.2.10 [async firebase_core firebase_core_web firebase_storage_platform_interface flutter flutter_web_plugins http js meta]
- fixnum 1.0.0
- flutter_blurhash 0.6.4 [flutter]
- flutter_cache_manager 3.3.0 [clock collection file flutter http path path_provider pedantic rxdart sqflite uuid]
- flutter_facebook_auth 4.1.1 [flutter flutter_facebook_auth_platform_interface flutter_facebook_auth_web]
- flutter_facebook_auth_platform_interface 3.0.1 [flutter plugin_platform_interface]
- flutter_facebook_auth_web 3.0.0+1 [flutter flutter_web_plugins js flutter_facebook_auth_platform_interface]
- flutter_local_notifications_linux 0.4.2 [flutter flutter_local_notifications_platform_interface dbus path xdg_directories]
- flutter_local_notifications_platform_interface 5.0.0 [flutter plugin_platform_interface]
- flutter_markdown 0.6.10 [flutter markdown meta path]
- flutter_plugin_android_lifecycle 2.0.5 [flutter]
- flutter_portal 0.4.0 [flutter]
- flutter_slidable 0.6.0 [flutter]
- flutter_svg 1.0.3 [flutter meta path_drawing vector_math xml]
- flutter_web_plugins 0.0.0 [flutter js characters collection material_color_utilities meta typed_data vector_math]
- frontend_server_client 2.1.2 [async path]
- glob 2.0.2 [async collection file path string_scanner]
- google_maps_flutter_platform_interface 2.1.5 [collection flutter plugin_platform_interface stream_transform]
- google_sign_in 5.2.4 [flutter google_sign_in_platform_interface google_sign_in_web]
- google_sign_in_platform_interface 2.1.2 [flutter quiver]
- google_sign_in_web 0.10.0+5 [flutter flutter_web_plugins google_sign_in_platform_interface js]
- googleapis_auth 1.3.0 [crypto http http_parser]
- graphs 2.1.0 [collection]
- html 0.15.0 [csslib source_span]
- http 0.13.4 [async http_parser meta path]
- http2 2.0.0
- http_multi_server 3.2.0 [async]
- http_parser 4.0.0 [charcode collection source_span string_scanner typed_data]
- image 3.1.3 [archive meta xml]
- image_gallery_saver 1.7.1 [flutter]
- image_picker_for_web 2.1.6 [flutter flutter_web_plugins image_picker_platform_interface]
- image_picker_platform_interface 2.4.4 [cross_file flutter http plugin_platform_interface]
- io 1.0.3 [meta path string_scanner]
- jiffy 5.0.0 [intl]
- jose 0.3.2 [crypto_keys meta typed_data x509 http http_parser asn1lib collection]
- js 0.6.3
- lints 1.0.1
- logging 1.0.2
- lottie 1.3.0 [archive flutter path vector_math]
- markdown 5.0.0 [args charcode meta]
- matcher 0.12.11 [stack_trace]
- material_color_utilities 0.1.3
- meta 1.7.0
- mime 1.0.1
- nested 1.0.0 [flutter]
- nm 0.5.0 [dbus]
- octo_image 1.0.1 [flutter flutter_blurhash]
- package_config 2.0.2 [path]
- package_info_plus 1.4.0 [flutter package_info_plus_platform_interface package_info_plus_linux package_info_plus_macos package_info_plus_windows package_info_plus_web]
- package_info_plus_linux 1.0.3 [package_info_plus_platform_interface flutter path]
- package_info_plus_macos 1.3.0 [flutter]
- package_info_plus_platform_interface 1.0.2 [flutter meta plugin_platform_interface]
- package_info_plus_web 1.0.4 [flutter flutter_web_plugins http meta package_info_plus_platform_interface]
- package_info_plus_windows 1.0.4 [package_info_plus_platform_interface ffi flutter win32]
- path 1.8.0
- path_drawing 1.0.0 [vector_math meta path_parsing flutter]
- path_parsing 1.0.0 [vector_math meta]
- path_provider 2.0.9 [flutter path_provider_android path_provider_ios path_provider_linux path_provider_macos path_provider_platform_interface path_provider_windows]
- path_provider_android 2.0.12 [flutter path_provider_platform_interface]
- path_provider_ios 2.0.8 [flutter path_provider_platform_interface]
- path_provider_linux 2.1.5 [ffi flutter path path_provider_platform_interface xdg_directories]
- path_provider_macos 2.0.5 [flutter path_provider_platform_interface]
- path_provider_platform_interface 2.0.3 [flutter platform plugin_platform_interface]
- path_provider_windows 2.0.5 [ffi flutter path path_provider_platform_interface win32]
- pedantic 1.11.1
- petitparser 4.4.0 [meta]
- photo_manager 2.0.8 [flutter]
- photo_view 0.13.0 [flutter]
- platform 3.1.0
- plugin_platform_interface 2.1.2 [meta]
- pointycastle 3.6.0 [collection convert js]
- pool 1.5.0 [async stack_trace]
- process 4.2.4 [file path platform]
- provider 6.0.2 [collection flutter nested]
- pub_semver 2.1.0 [collection meta]
- pubspec_parse 1.2.0 [checked_yaml collection json_annotation pub_semver yaml]
- quiver 3.0.1+1 [matcher]
- rate_limiter 0.1.1
- rational 1.2.1
- riverpod 1.0.3 [collection meta state_notifier]
- rxdart 0.27.3
- share_plus 4.0.4 [meta mime flutter share_plus_platform_interface share_plus_linux share_plus_macos share_plus_windows share_plus_web]
- share_plus_linux 3.0.0 [share_plus_platform_interface file flutter meta url_launcher]
- share_plus_macos 3.0.0 [share_plus_platform_interface flutter]
- share_plus_platform_interface 3.0.2 [flutter meta mime plugin_platform_interface]
- share_plus_web 3.0.0 [share_plus_platform_interface url_launcher flutter flutter_web_plugins meta]
- share_plus_windows 3.0.0 [share_plus_platform_interface flutter meta url_launcher]
- shared_preferences 2.0.13 [flutter shared_preferences_android shared_preferences_ios shared_preferences_linux shared_preferences_macos shared_preferences_platform_interface shared_preferences_web shared_preferences_windows]
- shared_preferences_android 2.0.11 [flutter shared_preferences_platform_interface]
- shared_preferences_ios 2.1.0 [flutter shared_preferences_platform_interface]
- shared_preferences_linux 2.1.0 [file flutter path path_provider_linux path_provider_platform_interface shared_preferences_platform_interface]
- shared_preferences_macos 2.0.3 [flutter shared_preferences_platform_interface]
- shared_preferences_platform_interface 2.0.0 [flutter]
- shared_preferences_web 2.0.3 [flutter flutter_web_plugins shared_preferences_platform_interface]
- shared_preferences_windows 2.1.0 [file flutter path path_provider_platform_interface path_provider_windows shared_preferences_platform_interface]
- shelf 1.2.0 [async collection http_parser path stack_trace stream_channel]
- shelf_web_socket 1.0.1 [shelf stream_channel web_socket_channel]
- shimmer 2.0.0 [flutter]
- sign_in_with_apple 3.3.0 [flutter meta sign_in_with_apple_platform_interface sign_in_with_apple_web]
- sign_in_with_apple_platform_interface 1.0.0 [flutter plugin_platform_interface meta]
- sign_in_with_apple_web 1.0.1 [flutter flutter_web_plugins sign_in_with_apple_platform_interface js]
- sky_engine 0.0.99
- source_gen 1.2.1 [analyzer async build dart_style glob meta path source_span yaml]
- source_helper 1.3.1 [analyzer collection source_gen]
- source_span 1.8.1 [collection path term_glyph]
- sqflite 2.0.2 [flutter sqflite_common path]
- sqflite_common 2.2.0 [synchronized path meta]
- stack_trace 1.10.0 [path]
- state_notifier 0.7.2+1 [meta]
- stream_channel 2.1.0 [async]
- stream_chat 3.6.1 [async collection dio equatable freezed_annotation http_parser jose json_annotation logging meta mime rate_limiter rxdart uuid web_socket_channel]
- stream_transform 2.0.0
- string_scanner 1.1.0 [charcode source_span]
- substring_highlight 1.0.33 [flutter]
- synchronized 3.0.0
- term_glyph 1.2.0
- test_api 0.4.8 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph matcher]
- timeago 3.2.2
- timezone 0.8.0 [path]
- timing 1.0.0 [json_annotation]
- twitter_login 4.0.1 [flutter crypto http]
- typed_data 1.3.0 [collection]
- universal_io 2.0.4 [collection crypto meta typed_data]
- url_launcher 6.1.0 [flutter url_launcher_android url_launcher_ios url_launcher_linux url_launcher_macos url_launcher_platform_interface url_launcher_web url_launcher_windows]
- url_launcher_android 6.0.16 [flutter url_launcher_platform_interface]
- url_launcher_ios 6.0.15 [flutter url_launcher_platform_interface]
- url_launcher_linux 3.0.0 [flutter url_launcher_platform_interface]
- url_launcher_macos 3.0.0 [flutter url_launcher_platform_interface]
- url_launcher_platform_interface 2.0.5 [flutter plugin_platform_interface]
- url_launcher_web 2.0.9 [flutter flutter_web_plugins url_launcher_platform_interface]
- url_launcher_windows 3.0.0 [flutter url_launcher_platform_interface]
- uuid 3.0.6 [crypto]
- vector_math 2.1.1
- very_good_analysis 2.4.0
- video_compress 3.1.0 [flutter]
- video_player 2.4.0 [flutter html video_player_android video_player_avfoundation video_player_platform_interface video_player_web]
- video_player_android 2.3.2 [flutter video_player_platform_interface]
- video_player_avfoundation 2.3.2 [flutter video_player_platform_interface]
- video_player_platform_interface 5.1.2 [flutter plugin_platform_interface]
- video_player_web 2.0.8 [flutter flutter_web_plugins video_player_platform_interface]
- video_thumbnail 0.5.0 [flutter]
- wakelock 0.6.1+2 [flutter meta wakelock_macos wakelock_platform_interface wakelock_web wakelock_windows]
- wakelock_macos 0.4.0 [flutter flutter_web_plugins wakelock_platform_interface]
- wakelock_platform_interface 0.3.0 [flutter meta]
- wakelock_web 0.4.0 [flutter flutter_web_plugins js wakelock_platform_interface]
- wakelock_windows 0.2.0 [flutter wakelock_platform_interface win32]
- watcher 1.0.1 [async path]
- web_socket_channel 2.1.0 [async crypto stream_channel]
- win32 2.4.1 [ffi]
- x509 0.2.2 [asn1lib quiver crypto_keys]
- xdg_directories 0.2.0+1 [meta path process]
- xml 5.3.1 [collection meta petitparser]
- yaml 3.1.0 [collection source_span string_scanner]
DanielBFox commented 2 years ago

Code sample

Extracting a code sample from this big project which is reproducible on your side is complicated. I share hereunder the way I initialize firebase and call the transaction Maybe with this you'll have an idea about the root cause or any clue on a config parameter to change (if not I'll take the time to create a small project from scratch).

Firebase init (called once from the main class)

class FirebaseService {
  FirebaseService._internal();

  FirebaseAuth get fireAuth => FirebaseAuth.instance;
  FirebaseFirestore get firestore => FirebaseFirestore.instance;
  FirebaseMessaging get fireMessaging => FirebaseMessaging.instance;
  firebase_storage.FirebaseStorage get fireStorage =>
      firebase_storage.FirebaseStorage.instance;
  FirebaseAppCheck fireAppCheck = FirebaseAppCheck.instance;
  Geoflutterfire get geoFlutterFire => Geoflutterfire();
  // FirebasePerformance get performance => FirebasePerformance.instance;

  /// Create a [AndroidNotificationChannel] for heads up notifications
  late AndroidNotificationChannel channel;
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  static Future<FirebaseService> init() async {
    await Firebase.initializeApp(
      options: DefaultFirebaseOptions.currentPlatform,
    ).catchError((Object e) {
      print("$e");
    });
    return FirebaseService._internal();
  }

  Future<void> configureFirebaseFirestore() async {
    await FirebaseFirestore.instance.clearPersistence();
    firestore.settings = const Settings(persistenceEnabled: false);
  }
}

Firebase options

 import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
    show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
///   options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
  static FirebaseOptions get currentPlatform {
    if (kIsWeb) {
      throw UnsupportedError(
        'DefaultFirebaseOptions have not been configured for web - '
        'you can reconfigure this by running the FlutterFire CLI again.',
      );
    }
    // ignore: missing_enum_constant_in_switch
    switch (defaultTargetPlatform) {
      case TargetPlatform.android:
        return android;
      case TargetPlatform.iOS:
        throw UnsupportedError(
          'DefaultFirebaseOptions have not been configured for ios - '
          'you can reconfigure this by running the FlutterFire CLI again.',
        );
      case TargetPlatform.macOS:
        throw UnsupportedError(
          'DefaultFirebaseOptions have not been configured for macos - '
          'you can reconfigure this by running the FlutterFire CLI again.',
        );
    }

    throw UnsupportedError(
      'DefaultFirebaseOptions are not supported for this platform.',
    );
  }

  static const FirebaseOptions android = FirebaseOptions(
...
  );
}

Transaction call

await ref.read(gardenerServiceProvider).sowInNursery(
        languageCode: ref.read(appStateNotifierProvider).languageCode,
        farmName: ref.read(appStateNotifierProvider).selectedFarm!.name,
        specieName: seed.specie,
        varietyName: seed.variety,
        providerName: seed.provider,
        seedId: seed.name,
        dateTime: dateTime,
        tagName: tagName,
        quantity: quantity,
        farmPhotoUrl: ref.read(appStateNotifierProvider).selectedFarm!.photoUrl,
        farmerUid: ref.read(userStateNotifierProvider).user!.uid,
        farmerDisplayName:
            ref.read(userStateNotifierProvider).user!.displayName,
        farmerPhotoUrl: ref.read(userStateNotifierProvider).user!.photoURL,
        seedReproductionDateTime:
            seed.reproducted ? seed.reproductionDateTime : null);
darshankawar commented 2 years ago

Thanks for the update. Looking at the code sample provided, there seem to be lot of thing going on in it, like usage of third party plugins like geoflutterfire. In order to narrow down the behavior to flutterfire, would be good to have a minimal code sample without third party plugin code.

DanielBFox commented 2 years ago

I'll do my best to provide a minimal code sample asap (by the end of this week). I noticed that the same behaviour occurs as well with very small transactions (with one single read / write). It's lighting fast on web, slow on a galaxy J6 and very slow on a galaxy a40 Geoflutterfire is not used in the transactions. Thanks

google-oss-bot commented 2 years ago

Hey @DanielBFox. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

DanielBFox commented 2 years ago

Hello,

I did some additional test on a minimal application created from scratch and I did not notice any performance issue.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const TestPage(title: 'Flutter Demo Home Page'),
    );
  }
}

class TestPage extends StatefulWidget {
  const TestPage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  var db = FirebaseFirestore.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () async {
                  print("@@@Write WITH transaction/1 ${DateTime.now()}");
                  final user2 = <String, dynamic>{
                    "first": "Ada2",
                    "last": "Lovelace2",
                    "born": 1816
                  };
                  DocumentReference documentReference =
                      db.doc("/testcollection/user2");
                  await db.runTransaction((transaction) async {
                    DocumentSnapshot snapshot =
                        await transaction.get(documentReference);
                    if (!snapshot.exists) {
                      transaction.set(documentReference, user2);
                    }
                  });
                  print("@@@Write WITH transaction/2 ${DateTime.now()}");
                },
                child: const Text("Write WITH transaction")),
            ElevatedButton(
                onPressed: () async {
                  print("@@@Write WO transaction/1 ${DateTime.now()}");
                  final user1 = <String, dynamic>{
                    "first": "Ada",
                    "last": "Lovelace",
                    "born": 1815
                  };
                  await db.collection("testcollection").doc("user1").set(user1);
                  print("@@@Write WO transaction/2 ${DateTime.now()}");
                },
                child: const Text("Write WO transaction")),
            ElevatedButton(
                onPressed: () async {
                  print("@@@Read/1 ${DateTime.now()}");
                  DocumentSnapshot snapshot =
                      await db.doc("/testcollection/user1").get();
                  print("@@@Read/2 ${DateTime.now()}");
                  print(snapshot.data());
                },
                child: const Text("Read"))
          ],
        ),
      ),
    );
  }
}

The results are :

I/flutter (10136): @@@Write WO transaction/1 2022-05-21 07:13:12.337451
W/DynamiteModule(10136): Local module descriptor class for com.google.android.gms.providerinstaller.dynamite not found.
I/DynamiteModule(10136): Considering local module com.google.android.gms.providerinstaller.dynamite:0 and remote module com.google.android.gms.providerinstaller.dynamite:0
W/ProviderInstaller(10136): Failed to load providerinstaller module: No acceptable module com.google.android.gms.providerinstaller.dynamite found. Local version is 0 and remote version is 0.
I/TetheringManager(10136): registerTetheringEventCallback:com.example.mygardentest
D/ConnectivityManager(10136): ConnectivityManager() mContext=android.app.Application@c0af getOpPackageName()=com.example.mygardentest getBasePackageName()=com.example.mygardentest getPackageName()=com.example.mygardentest
2
I/le.mygardentes(10136): The ClassLoaderContext is a special shared library.
V/NativeCrypto(10136): Registering com/google/android/gms/org/conscrypt/NativeCrypto's 295 native methods...
W/le.mygardentes(10136): Accessing hidden method Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String; (greylist, reflection, allowed)
I/ProviderInstaller(10136): Installed default security provider GmsCore_OpenSSL
W/le.mygardentes(10136): Accessing hidden field Ljava/net/Socket;->impl:Ljava/net/SocketImpl; (greylist, reflection, allowed)
W/le.mygardentes(10136): Accessing hidden method Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; (greylist,core-platform-api, linking, allowed)
W/le.mygardentes(10136): Accessing hidden method Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V (greylist,core-platform-api, linking, allowed)
W/le.mygardentes(10136): Accessing hidden method Ljava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V (greylist, reflection, allowed)
W/le.mygardentes(10136): Accessing hidden method Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy; (greylist,core-platform-api, linking, allowed)
W/le.mygardentes(10136): Accessing hidden method Ldalvik/system/BlockGuard$Policy;->onNetwork()V (greylist, linking, allowed)
I/flutter (10136): @@@Write WO transaction/2 2022-05-21 07:13:13.495430

I/flutter (10136): @@@Read/1 2022-05-21 07:13:50.231062
I/flutter (10136): @@@Read/2 2022-05-21 07:13:50.442588

I/flutter (10136): @@@Read/1 2022-05-21 07:13:51.940644
I/flutter (10136): @@@Read/2 2022-05-21 07:13:52.060539

I/flutter (10136): @@@Read/1 2022-05-21 07:13:53.168248
I/flutter (10136): @@@Read/2 2022-05-21 07:13:53.322886

I/flutter (10136): @@@Write WITH transaction/1 2022-05-21 07:14:39.477276
I/flutter (10136): @@@Write WITH transaction/2 2022-05-21 07:14:39.832151

We can see that the initialization of GMS slows down a bit the first write but after that read & writes and going fast.

I added the very same test code on the "big app" and maybe I've got a clue on what's happening. On the first write I had 2 different results :

Test 1 
======
I/flutter (31652): @@@Write WO transaction/1 2022-05-20 18:37:27.123925
W/DynamiteModule(31652): Local module descriptor class for com.google.android.gms.providerinstaller.dynamite not found.
I/DynamiteModule(31652): Considering local module com.google.android.gms.providerinstaller.dynamite:0 and remote module com.google.android.gms.providerinstaller.dynamite:0
W/ProviderInstaller(31652): Failed to load providerinstaller module: No acceptable module com.google.android.gms.providerinstaller.dynamite found. Local version is 0 and remote version is 0.
I/fox.mygardenpr(31652): The ClassLoaderContext is a special shared library.
V/NativeCrypto(31652): Registering com/google/android/gms/org/conscrypt/NativeCrypto's 295 native methods...
W/fox.mygardenpr(31652): Accessing hidden method Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String; (greylist, reflection, allowed)
I/ProviderInstaller(31652): Installed default security provider GmsCore_OpenSSL
W/fox.mygardenpr(31652): Accessing hidden field Ljava/net/Socket;->impl:Ljava/net/SocketImpl; (greylist, reflection, allowed)
W/fox.mygardenpr(31652): Accessing hidden method Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; (greylist,core-platform-api, linking, allowed)
W/fox.mygardenpr(31652): Accessing hidden method Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V (greylist,core-platform-api, linking, allowed)
W/fox.mygardenpr(31652): Accessing hidden method Ljava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V (greylist, reflection, allowed)
W/fox.mygardenpr(31652): Accessing hidden method Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy; (greylist,core-platform-api, linking, allowed)
W/fox.mygardenpr(31652): Accessing hidden method Ldalvik/system/BlockGuard$Policy;->onNetwork()V (greylist, linking, allowed)
I/System.out(31652): (HTTPLog)-Static: isSBSettingEnabled false
I/flutter (31652): app check token changed
I/flutter (31652): @@@Write WO transaction/2 2022-05-20 18:37:34.814922

Test2
=====
flutter ( 7060): @@@Write WO transaction/1 2022-05-21 07:05:40.170606
W/DynamiteModule( 7060): Local module descriptor class for com.google.android.gms.providerinstaller.dynamite not found.
I/DynamiteModule( 7060): Considering local module com.google.android.gms.providerinstaller.dynamite:0 and remote module com.google.android.gms.providerinstaller.dynamite:0
W/ProviderInstaller( 7060): Failed to load providerinstaller module: No acceptable module com.google.android.gms.providerinstaller.dynamite found. Local version is 0 and remote version is 0.
I/fox.mygardenpr( 7060): The ClassLoaderContext is a special shared library.
V/NativeCrypto( 7060): Registering com/google/android/gms/org/conscrypt/NativeCrypto's 295 native methods...
W/fox.mygardenpr( 7060): Accessing hidden method Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String; (greylist, reflection, allowed)
I/ProviderInstaller( 7060): Installed default security provider GmsCore_OpenSSL
W/fox.mygardenpr( 7060): Accessing hidden field Ljava/net/Socket;->impl:Ljava/net/SocketImpl; (greylist, reflection, allowed)
W/fox.mygardenpr( 7060): Accessing hidden method Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; (greylist,core-platform-api, linking, allowed)
W/fox.mygardenpr( 7060): Accessing hidden method Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V (greylist,core-platform-api, linking, allowed)
W/fox.mygardenpr( 7060): Accessing hidden method Ljava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V (greylist, reflection, allowed)
W/fox.mygardenpr( 7060): Accessing hidden method Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy; (greylist,core-platform-api, linking, allowed)
W/fox.mygardenpr( 7060): Accessing hidden method Ldalvik/system/BlockGuard$Policy;->onNetwork()V (greylist, linking, allowed)
I/fox.mygardenpr( 7060): Background concurrent copying GC freed 66327(5785KB) AllocSpace objects, 20(736KB) LOS objects, 49% free, 4827KB/9654KB, paused 211us total 124.913ms
I/flutter ( 7060): @@@Write WO transaction/2 2022-05-21 07:05:41.398540

We can see the on first test the write takes 7 secons to complete; for the second one it takes 1 second. The difference I can see is the app check token change. So maybe it's related to that token change

darshankawar commented 2 years ago

Thanks for digging in and providing these updates. The 2 tests you did are on mobile or web ? Also, can you compare the test results using your app on both platforms and share results here ?

DanielBFox commented 2 years ago

Hello,

The 2 tests I did were on mobile.

This time I ran the minimal application on the web and the results are :

@@@Write WO transaction/1 2022-05-28 07:52:18.265
@@@Write WO transaction/2 2022-05-28 07:52:18.627
@@@Read/1 2022-05-28 07:52:20.477
@@@Read/2 2022-05-28 07:52:20.727
{born: 1815, first: Ada, last: Lovelace}
@@@Write WITH transaction/1 2022-05-28 07:52:23.341
@@@Write WITH transaction/2 2022-05-28 07:52:23.624
@@@Read/1 2022-05-28 07:52:25.015
@@@Read/2 2022-05-28 07:52:25.111
{first: Ada, last: Lovelace, born: 1815}

As you can see I did not notice any performance issue on the web.

darshankawar commented 2 years ago

Thanks for the update. Keeping this issue open and labeling for further insights from the team.

zthrive commented 2 years ago

On the surface everything looks the same, but ...

There is one more test that I made that makes me believe that this is still a flutter framework issue and not firestore.

I ran Build->GenerateSignedBundle->APK from Android studio that produced a number of apk files (see attached document).

After that, if I deploy app.apk on the device, there are performance issues. But, if I deploy app-release.apk on the same device, there are no performance issues, everything works really good!

Therefore, my claim from before.

Further to this, I am not sure why there are app.apk and app-release.apk files produced? but it seems that app.apk is 'bad' and app-release.apk is 'good'. Therefore if app-release.apk were to end up in the appbundle, all problems would disappear. Unfortunately, when I download the app from Gogle Playstore, it comes with performance issues which tells me that app.apk ends packaged up.

Please let me know what do you think about all this.

Nolan APK .

zthrive commented 2 years ago

There is one more thing that I wanted to advise.

I successfully uploaded the app-release.apk to the Google Playstore, rather than appbundle which I was doing all the time before, since it is recommended by Google. Now, when I download the app from the Playstore (on the same device, of course), everything works just fine. No issues with firestore.

Therefore, my conclusion is that appbundle is broken. Until I hear that it is fixed, I'll be uploading to Google Play the app-release.apk of my app.

zthrive commented 2 years ago

My last comment in this thread. Unfortunately, even after uploading the app-release.apk to Google Playstore once downloaded to the device it shows long delays for events that involve firebase. I was too quick to 'claim victory' in my previous comment. However, if the same apk is downloaded straight to the device, it works perfectly.

Lyokone commented 1 year ago

Closing as per https://github.com/flutter/flutter/issues/105990#issuecomment-1219382133