invertase / react-native-firebase

πŸ”₯ A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.71k stars 2.22k forks source link

[πŸ›] [Android] Same query takes 58 seconds longer on Android #5941

Closed OscarWoHA closed 1 year ago

OscarWoHA commented 2 years ago

Issue

We received feedback that a Firebase firestore query in our app was taking very long time to load on Android.

After investigating we figured out that using the traditional one-time .get() method on the query instead of .onSnapshot() and instantly cancelling the listener has a huge difference in load time: The onSnapshot() promise takes 100 ms to resolve and the get() promise upwards of 1 minute to resolve.

What could cause this? This issue does not happen on iOS, so it is probably related to the Android SDK somehow.

I'll happily provide as much detail as possible to debug this - please do not hesitate to ask for more!

Query

export async function getOrgEvents(
    org: SPOrganization,
    startAt: WithReferences<OrgEvent> | undefined,
    direction: 'asc' | 'desc' = 'asc',
): Promise<WithReferences<OrgEvent>[]> {
    const today = new Date();
    today.setHours(0);
    const events: WithReferences<OrgEvent>[] = [];
    let query = org.ref()!.collection('events').where('active', '==', true).orderBy('time_end', direction);
    if (startAt) {
        query = query.startAfter(startAt.time_end);
    } else {
        query = query.startAt(today);
    }

    query = query.limit(8);

    // This query takes 1 minutes, with onSnapshot it takes 100ms
    const postSnapshot = await query
        .get()
        .then((value) => {
            return value;
        })
        .catch((reason) => {
            console.log(reason);
            return;
        });

    if (!postSnapshot || (postSnapshot && postSnapshot.empty)) {
        return [];
    }
    await postSnapshot.docs.map(async (receiver) => {
        const docSnap = receiver;
        const orgEvent: WithReferences<OrgEvent> = {
            ...(docSnap.data() as OrgEvent),
            querySnap: docSnap,
            parentID: docSnap.ref.parent.parent!.id,
            ref: receiver.ref,
        };
        events.push(orgEvent);
    });

    return events;
}

Project Files

Javascript

Click To Expand

#### `package.json`: ```json { "name": "app-shared", "version": "1.0.82", "description": "Shared code between styreportalen apps", "private": true, "main": "index.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+ssh://git@github.com/Styreportalen-AS/app-shared.git" }, "author": "Henning Berge", "license": "ISC", "bugs": { "url": "https://github.com/Styreportalen-AS/app-shared/issues" }, "homepage": "https://github.com/Styreportalen-AS/app-shared#readme", "dependencies": { "firebase": "^8.4.1", "i18next": "^20.2.1", "md5": "^2.3.0", "moment": "^2.29.1", "react-i18next": "^11.8.13", "react-intl": "^5.15.8" }, "peerDependencies": { "@react-native-community/clipboard": "^1.5.1", "@react-native-community/masked-view": "^0.1.11", "@react-native-picker/picker": "^1.16.3", "@react-native-firebase/app": "^12.1.0", "@react-native-firebase/auth": "^12.1.0", "@react-native-firebase/crashlytics": "^12.1.0", "@react-native-firebase/database": "^12.1.0", "@react-native-firebase/dynamic-links": "^12.1.0", "@react-native-firebase/firestore": "^12.1.0", "@react-native-firebase/functions": "^12.1.0", "@react-native-firebase/in-app-messaging": "^12.1.0", "@react-native-firebase/messaging": "^12.1.0", "@react-native-firebase/perf": "^12.1.0", "@react-native-firebase/remote-config": "^12.1.0", "@react-native-firebase/storage": "^12.1.0", "native-base": "^2.15.2", "react-native": "^0.64.2", "react-native-device-info": "^8.1.3", "react-native-elements": "^3.4.2", "react-native-fit-image": "^1.5.5", "react-native-fs": "^2.18.0", "react-native-image-crop-picker": "^0.36.2", "react-native-image-zoom-viewer": "^3.0.1", "react-native-input-scroll-view": "^1.11.0", "react-native-linear-gradient": "^2.5.6", "react-native-localize": "^2.1.1", "react-native-markdown-display": "^6.1.6", "react-native-photo-grid-frame": "git+ssh://git@github.com:Styreportalen-AS/react-native-photo-grid-frame.git", "react-native-remote-svg": "git+ssh://git@github.com:Styreportalen-AS/react-native-remote-svg.git", "react-native-web-swiper": "^2.2.1", "react-native-timeago": "^0.5.0", "@styreportalen/common": "^2.1.336" }, "devDependencies": { "@react-native-community/clipboard": "^1.5.1", "@react-native-community/masked-view": "^0.1.11", "@react-native-picker/picker": "^1.16.3", "@react-native-firebase/analytics": "^12.1.0", "@react-native-firebase/app": "^12.1.0", "@react-native-firebase/auth": "^12.1.0", "@react-native-firebase/crashlytics": "^12.1.0", "@react-native-firebase/database": "^12.1.0", "@react-native-firebase/dynamic-links": "^12.1.0", "@react-native-firebase/firestore": "^12.1.0", "@react-native-firebase/functions": "^12.1.0", "@react-native-firebase/in-app-messaging": "^12.1.0", "@react-native-firebase/messaging": "^12.1.0", "@react-native-firebase/perf": "^12.1.0", "@react-native-firebase/remote-config": "^12.1.0", "@react-native-firebase/storage": "^12.1.0", "native-base": "3.0.3", "react-native": "^0.64.2", "react-native-device-info": "^8.1.3", "react-native-elements": "^3.4.2", "react-native-fit-image": "^1.5.5", "react-native-fs": "^2.18.0", "react-native-image-crop-picker": "^0.36.2", "react-native-image-zoom-viewer": "^3.0.1", "react-native-input-scroll-view": "^1.11.0", "react-native-linear-gradient": "^2.5.6", "react-native-localize": "^2.1.1", "react-native-markdown-display": "^6.1.6", "react-native-photo-grid-frame": "git+ssh://git@github.com:Styreportalen-AS/react-native-photo-grid-frame.git", "react-native-remote-svg": "git+ssh://git@github.com:Styreportalen-AS/react-native-remote-svg.git", "react-native-svg": "^12.1.1", "react-native-web-swiper": "^2.2.1", "react-native-timeago": "^0.5.0", "@react-native-community/eslint-config": "^3.0.0", "@types/i18next": "^13.0.0", "@types/md5": "^2.3.0", "@types/react-intl": "^3.0.0", "@types/react-native": "^0.64.2", "@typescript-eslint/eslint-plugin": "^4.22.0", "@typescript-eslint/parser": "^4.22.0", "eslint": "^7.24.0", "prettier": "^2.2.1", "typescript": "^4.2.4", "@styreportalen/common": "^2.1.336" } } ``` #### `firebase.json` for react-native-firebase v6: ```json # N/A ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby # N/A ``` #### `AppDelegate.m`: ```objc // N/A ```


Android

Click To Expand

#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [ ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`: ```groovy // N/A ``` #### `android/app/build.gradle`: ```groovy // N/A ``` #### `android/settings.gradle`: ```groovy // N/A ``` #### `MainApplication.java`: ```java // N/A ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

**`react-native info` output:** ``` // N/A ``` - **Platform that you're experiencing the issue on**: - [ ] iOS - [x] Android - [ ] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - 14.0.0 - **`Firebase` module(s) you're using that has the issue:** - `Firestore` - **Are you using `TypeScript`?** - `Y` & `4.2.4`


mikehardy commented 2 years ago

What in the :fearful: :sweat_smile:

First things first is to get current and make sure you are not overriding firebase-android-sdk, we want to make sure you are using up to date code here (14.0.0 right now) and up to date firebase-android-sdk (29.0.2 now)

Frequently these things are fixed "before you get there" if you stay on the release train and keep current. I do issue major version semi-frequently but that's an abundance of caution - each one is usually a small, tiny thing and even the one about ios number formats should not actually break people as anyone actually relying on the old behavior of integer mis-formatting is really unexpected - https://invertase.io/blog/react-native-firebase-versioning

Please let me know how that goes

Second approach if up to date code works is to separate concerns - the biggest is: is it this wrapper? or the underlying SDK? The underlying SDK seems most likely since you say it works on iOS. That argues for a quickstart on the underlying SDK directly to focus effort: https://github.com/firebase/quickstart-android/tree/master/firestore

OscarWoHA commented 2 years ago

We've verified that this still happens on react-native-firebase@14.0.0 and firebase-android-sdk@29.0.2.

Will try the quickstart approach and see if the issue persists there.

ptreitler commented 2 years ago

I noticed the same thing in my app. Loading times with several get() calls take longer by a factor of 8(!) on Android vs. iOS, leading to a total loading time of several minutes.

I just updated to the current versions, still the same: react-native-firebase: 14.5.0 Firebase Android SDK: 29.1.0

@OscarWoHA have you made any progress on this issue?

OscarWoHA commented 2 years ago

@ptreitler Haven't had enough available resources to investigate this issue unfortunately. I do think this is something maintainer should try to investigate themselves as well though, due to the broad impact it might have.

In regards to details about our tech stack feel free to contact me directly, I will happily elaborate - unfortunately posting it here would be outside of my scope.

mikehardy commented 2 years ago

I do think this is something maintainer should try to investigate themselves as well though, due to the broad impact it might have.

It's too project-specific in my opinion. We need a reproduction - https://stackoverflow.com/help/minimal-reproducible-example / https://github.com/mikehardy/rnfbdemo/blob/main/make-demo.sh

sruli commented 2 years ago

We were also having the same experience for as far as I can remember (at least a year). I was trying my latest attempt at debugging and I found that, as @mikehardy suggested, it was an issue with the underlying SDK. There are issues in flutterfire: 4305 and 6355. Also in firebase-android-sdk: 2637.

The good news is that it has been fixed and has been released in firebase-android-sdk 24.0.2

Looks like latest react-native-firebase is on firebase sdk 29.1.0.

Comparing 29.1.0 with the latest android sdk release shows that 29.1.0 is using firestore 24.0.1, one minor release before the 24.0.2, which contains the fix.

In the meantime, I've add implementation platform('com.google.firebase:firebase-bom:29.2.1') to android/app/build.gradle as per the directions for setting up Firebase in 'SDK setup and configuration' in your Firebase console settings. This has fixed the problem for us.

Hope this helps.

ptreitler commented 2 years ago

Unfortunately the queries are still slow for me. Tried firebase-bom v29.2.1 and v29.3.0. react-native-firebase is @14.7.0

I'm not sure if it's the same issue either, for me it doesn't just occur "after app returns to the foreground" as described in the issue tracker.

dev-andremonteiro commented 2 years ago

Also experiencing this problem using react-native-firebase ( v14.7.0 ) , changed back to firebase ( v8.2.3 ) and query times went back down. From a query that takes 21s with the RNF, it took 9s with Firebase. Tried changing the default firebase-bom version too like @sruli suggested, using both version 29.2.1 and latest 30.0.1 and multiple RNF versions ( v12, v13, v14 ) but nothing seems to work. @ptreitler Did you manage to find a way to solve this ? I am using firebase library for now until this gets fixed.

mikehardy commented 2 years ago

@dev-andremonteiro interesting - I would be interested in knowing if the new offline / on-device indexing capabilities could help at all - Reason 2 here https://medium.com/firebase-developers/why-is-my-cloud-firestore-query-slow-e081fb8e55dd

We do not yet expose this API (yet!), but you could crudely hack it in to the java files without too much trouble I think? (by which I mean: reach right in to node_modules/@react-native-firebase/firestore and just mash it in somewhere during init with a hard-coded string for the JSON on-device index you get from firebase-cli: https://github.com/firebase/firebase-android-sdk/blob/master/firebase-firestore/CHANGELOG.md#2410

Or if you try it and it is awesome I would be overjoyed to have a PR for it so it was formally supported :-)

mikehardy commented 2 years ago

that version of firestore will only come in with the latest react-native-firebase though - fair warning - as otherwise there were problems with auth emulator connections in BoMs 29.2.x through 30.0.1, only with 30.0.1 was I comfortable doing a release that bumped the firebase-android-sdk bom

github-actions[bot] commented 1 year ago

Hello πŸ‘‹, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

shubhamdeol commented 1 year ago

Adding some findings from my project on Android.

With each firebase version update it seems that query response time is increasing.

mikehardy commented 1 year ago

our implementation here has not changed structurally over that time with the exception of adding a configurable worker pool (you can read about it in the docs on rnfirebase.io for firebase.json inside the core/app package - you may configure more workers now, might help). The default remains the same though. I wonder if this relates to the underlying firebase-android-sdk then and you can reproduce perhaps with https://github.com/firebase/quickstart-android/tree/master/firestore

github-actions[bot] commented 1 year ago

Hello πŸ‘‹, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

gaganIcodelabs commented 1 year ago

Anyone got solution of this issue ?? Please reply

singhayush1403 commented 1 year ago

This is happening with me as well. Response Times in android are quite large as compared to iOS. Any solution?

jeffinhk commented 1 year ago

my current understanding with this issue so far is that there has been a HUGE issue with rendering, navigating, and many other issues since React Native 0.71.x specifically harsh on Androids. I have tried pumping up performance limitations with firebase.json file, moving around service point countries (e.g. from hong kong to tokyo to seoul etc) but it seems like it's really about react native's problem for now. I'll come back after I try downgrading my react native version to 0.70.x and even 0.69.x if necessary and come back if any progress has been found. I'm leaving the issue I found from other repo : https://github.com/facebook/react-native/issues/36296

dahed92 commented 1 week ago

Here’s how I fixed the issue:

Create a firebase.json file (or open it if it already exists) in the root folder of your project, and add the following configuration: { "react-native": { "android_task_executor_maximum_pool_size": 50, // I don’t recommend setting this higher than 50 "android_task_executor_keep_alive_seconds": 5 } }

After making this change, rebuild your app, and everything should work fine.