Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Cloud Functions - slow response when querying Firestore

I have a simple Cloud Function in Firebase that takes JSON in an http POST and saves it to a Firestore collection. It's allocated 512MB memory.

The performance of this cloud function is very poor. If executed continuously, the round trip varies from 200-600ms and if executed infrequently (every 5-10 mins) it can take 4-10 seconds. I understand the cold start problem but on AWS I've never seen a cold start this slow, nor this frequent.

My code is below - I'd appreciate any insight into how to speed up performance.

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();

const express = require('express');
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// CORS Express middleware to enable CORS Requests.
const cors = require('cors');
app.use(cors({ origin: true }))

app.post('/submitResponse', (req, res) => {
  console.log('/submitResponse');

  if (!req.body.info)
    res.status(422).send()

  const payload = req.body.info;
  console.log(payload);

  const responses = db.collection("responses")

  responses.add({
    payload: payload,
    timestamp: admin.firestore.FieldValue.serverTimestamp()
  }).then(function(docRef) {
    console.log("Response written with ID: ", docRef.id);
    res.status(200).send(JSON.stringify(docRef.id))
  })
  .catch(function(error) {
      console.error("Error adding document: ", error);
  });
});

exports.app = functions.https.onRequest(app);
like image 253
James Beswick Avatar asked Mar 09 '18 16:03

James Beswick


1 Answers

To address some of the comments: at the time of writing Cloud Firestore for Firebase is actually still in beta.

Firestore is in Beta

But Firestore is probably not the culprit in this case. The cold boot time of the cloud function is most likely overshadowing any database operation that you're having.

Cloud functions need time to spin up new instances whenever you have

  1. Deployed new functions / first invocation
  2. Instance has been recycled
  3. Scaling up to handle load (request hitting new instance)

There's a section about Cloud Function performance that mentions potential gains that you can make by minimizing your module dependencies.

Because functions are stateless, the execution environment is often initialized from scratch (during what is known as a cold start). When a cold start occurs, the global context of the function is evaluated.

If your functions import modules, the load time for those modules can add to the invocation latency during a cold start. You can reduce this latency, as well as the time needed to deploy your function, by loading dependencies correctly and not loading dependencies your function doesn't use.

Also check out the awesome Cloud Performance Atlas video on the topic that mentions tips like:

  • Reducing library dependencies
  • Using more (most) popular versions of a package as it is more likely to already be cached
  • Lazy loading modules that are not critical at boot

In case of library dependencies, the lowest hanging fruit is to get rid of dependencies that are either possible to implement yourself and/or only are using one or a few functions but requiring the whole library (I'm looking at you, lodash).

like image 149
Dennis Alund Avatar answered Nov 19 '22 17:11

Dennis Alund