Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Dynamic Pages using Cloud Functions with Firestore are slow

We have dynamic pages being served by Firebase Cloud Functions, but the TTFB is very slow on these pages with TTFB of 900ms - 2s, at first we just assumed it to be a cold start issue, but even with consistent traffic it is very slow at TTFB of 700ms - 1.2s.

This is a bit problematic for our project since it is organic traffic dependent and Google Pagespeed would need a server response of less than 200ms.

Anyway, we tried to check what might be causing the issue and we pinpointed it with Firestore, when a Cloud Function accesses Firestore, we noticed there are some delays. This is a basic sample code of how we implement Cloud Function and Firestore:

dynamicPages.get('/ph/test/:id', (req, res) => {

    var globalStartTime = Date.now();
    var period = [];

    db.collection("CollectionTest")
        .get()
        .then((querySnapshot) => {

            period.push(Date.now() - globalStartTime);

            console.log('1', period);

            return db.collection("CollectionTest")
                .get();

        })
        .then((querySnapshot) => {

            period.push(Date.now() - globalStartTime);

            console.log('2', period);

            res.status(200)
                .send('Period: ' + JSON.stringify(period));

            return true;

        })
        .catch((error) => {

            console.log(error);
            res.end();

            return false;

        });

});

This is running on Firebase + Cloud Functions + NodeJS

CollectionTest is very small with only 100 documents inside, with each document having the following fields:

directorName: (string)
directorProfileUrl: (string)
duration: (string)
genre: (array)
posterUrl: (string)
rating: (string)
releaseDate: (string)
status: (int)
synopsis: (string)
title: (string)
trailerId: (string)
urlId: (string)

With this test, we would get the following results:

[467,762] 1.52s
[203,315] 1.09s
[203,502] 1.15s
[191,297] 1.00s
[206,319] 1.03s
[161,267] 1.03s
[115,222] 843ms
[192,301] 940ms
[201,308] 945ms
[208,312] 950ms

This data is [Firestore Call 1 Exectution Time, Firestore Call 2 Exectution Time] TTFB

If we check the results of the test, there are signs that the TTFB is getting lower, maybe that is when the Cloud Function has already warmed up? But even so, Firestore is eating up 200-300ms in the Cloud Function based on the results of our second Firestore Call and even if Firestore took lesser time to execute, TTFB would still take up 600-800ms, but that is a different story.

Anyway, can anyone help how we can improve Firestore performance in our Cloud Functions (or if possible, the TTFB performance)? Maybe we are doing something obviously wrong that we don't know about?

like image 598
Jo E. Avatar asked Jun 03 '18 11:06

Jo E.


1 Answers

I will try to help, but maybe lacks a bit of context about what you load before returning dynamicPages but here some clues:

First of all, the obvious part (I have to point it anyway):

1 - Take care how you measure your TTFB:

Measuring TTFB remotely means you're also measuring the network latency at the same time which obscures the thing TTFB is actually measuring: how fast the web server is able to respond to a request.

2 - And from Google Developers documentation about Understanding Resource Timing (here):

[...]. Either:

Bad network conditions between client and server, or
A slowly responding server application

To address a high TTFB, first cut out as much network as possible. Ideally, host the application locally and see if there is still a big TTFB. If there is, then the application needs to be optimized for response speed. This could mean optimizing database queries, implementing a cache for certain portions of content, or modifying your web server configuration. There are many reasons a backend can be slow. You will need to do research into your software and figure out what is not meeting your performance budget.

If the TTFB is low locally then the networks between your client and the server are the problem. The network traversal could be hindered by any number of things. There are a lot of points between clients and servers and each one has its own connection limitations and could cause a problem. The simplest method to test reducing this is to put your application on another host and see if the TTFB improves.

Not so obvious ones:

You can take a look at the official Google documentation regarding Cloud Functions Performance here: https://cloud.google.com/functions/docs/bestpractices/tips

Did you require some files before?

According to this answer from Firebase cloud functions is very slow: Firebase cloud functions is very slow:

Looks like a lot of these problems can be solved using the hidden variable process.env.FUNCTION_NAME as seen here: https://github.com/firebase/functions-samples/issues/170#issuecomment-323375462

Are these dynamic pages loaded being accessed by a guest user or a logged user? Because maybe the first request has to sort out the authentication details, so it's known to be slower...

If nothing of this works, I will take a look at the common performance issues like DB connection (here: Optimize Database Performance), improving server configuration, cache all you can and take care of possible redirections in your app...

To end, reading through Internet, there are a lot of threads with your problem (low performance on simple Cloud Functions). Like this one: https://github.com/GoogleCloudPlatform/google-cloud-node/issues/2374 && in S.O: https://stackoverflow.com/search?q=%5Bgoogle-cloud-functions%5D+slow

With comments like:

since when using cloud functions, the penalty is incurred on each http invocation the overhead is still very high (i.e. 0.8s per HTTP call).

or:

Bear in mind that both Cloud Functions and Cloud Firestore are both in beta and provide no guarantees for performance. I'm sure if you compare performance with Realtime Database, you will see better numbers.

Maybe it is still an issue.

Hope it helps!

like image 68
JP. Aulet Avatar answered Oct 21 '22 09:10

JP. Aulet