firebase / firebase/firebase-admin-node

Individual Firestore get() calls exceeding one second

Aperta
#2,357 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub
needs-triage
Lingua principale
TypeScript
Stelle
1.7k
Fork
419
Merge medio
3g 10h
PR unite (30g)
16

Descrizione

* Operating System version: Google App Engine (Windows 10.0.19045 in dev)
* Firebase SDK version: firebase-admin@11.9.0
* Firebase Product: Firestore
* Node.js version: 16 (16.17.0 in dev)
* NPM version: 9.5.1

I use Firestore as my database for a simple backend server, and very slow reads are causing my API requests to take several seconds to complete.

My backend is an always-running GraphQL server running in Google App Engine, so it is not suffering from cold-start issues. The GAE instance and the selected Firestore instance are both running in US-central (nam5), so transfer delay should be negligible. Document sizes are 2-10KB, so large transfers should not be an issue. All other external REST calls complete in 50-120ms, so I don't believe it's a network saturation issue. My keys are generated UUIDs, so I don't believe it's a hotspotting issue.

My typical API processing makes 1-5 calls in parallel to documents to determine what the user is requesting, then gets 20-80 documents in parallel to build the response - i.e. a single waterfall. Using @opentelemetry/instrumentation-grpc@0.27.0, I am tracing these calls from within the server (and batching the traces). Typically the first batch of reads completes in 300-700ms, and the second batch takes 600-1200ms. This far exceeds what I would consider viable performance.

For the user to not be interrupted, I try to keep my P50 performance <300ms. With these numbers, I'm not even close. API calls that take 5+ seconds are not uncommon.

I feel like I've eliminated every possible variable, and all that is left is:
a) an issue with the node package, perhaps straining under 20+ simultaneous reads, or
b) misrepresented data coming from the instrumentation-grpc package, or
c) mismatched expectations of Firestore's capabilities. Unfortunately, it seems Firestore doesn't publish any SLAs or expectations. Is a single Firestore read taking 300ms expected, or an outlier needing investigation? I do see some reads happening in <40ms, which is far closer to my expectation.

Here's one of the simplest APIs I have, and it completes in 568ms. There are 56 reads across 6 batches. Shortest read time is 23ms (the first one), longest is 307ms. Most reads are >180ms.

![image](https://github.com/firebase/firebase-admin-node/assets/30424941/3efddbb7-484f-4c78-a264-bcd6e0e7fe3d)
![image](https://github.com/firebase/firebase-admin-node/assets/30424941/cbf47f68-3f8c-4026-8bdd-0be83069b351)

Here's a taste of a more complex API that has 41 reads, and completes in 3298ms:
![image](https://github.com/firebase/firebase-admin-node/assets/30424941/1971bba7-4ff5-4764-b315-b336e083ccb7)

For reference, here's an API call that doesn't call Firestore. It completes in 9ms.
![image](https://github.com/firebase/firebase-admin-node/assets/30424941/6dac58f0-5705-4616-ac91-e26296946813)

From these traces, it seems that the read times scales linearly with the number of reads in flight. Information online suggests that the firebase-admin package uses a GRPC pool under the hood, so I would expect the read time to be static until the GRPC connection pool is exhausted, then scale linearly after that point. Is there a way to configure or inspect what's happening with the GRPC connection pool?

Here's the code used to initialize the package.

firestore.ts
```
import {initializeApp} from 'firebase-admin/app';
import {CollectionReference, DocumentReference, FieldPath, getFirestore} from 'firebase-admin/firestore';

initializeApp();

export const db = getFirestore();
db.settings({ignoreUndefinedProperties: true, maxIdleChannels: 500});
```

TL;DR: How do I get my read times lower, or is this as good as I can expect them to be?

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.