Skip to content

Provider init very slow during cold start #768

@acorn1010

Description

@acorn1010

Related issues

I couldn't find any open perf-related issues

[REQUIRED] Version info

node: 10.18.1

firebase-functions: 3.11.0

firebase-tools: 8.7.0

firebase-admin: 9.1.1

[REQUIRED] Test case

import * as functions from 'firebase-functions';

// May need to call admin#initializeApp. I left it out of this example.

const scope = {time: Date.now()};  // Only for logging purposes to help you see where the perf issue is.
const sometimesSlow = functions.firestore.document('foo/{bar}').onWrite(async (change, context) => {
  console.log('COLD STARTS ARE SLOW: ' + (Date.now() + scope.time));
});
const wrappedSometimesSlow = async(input: any, context?: any) => {
  scope.time = Date.now();
  return sometimesSlow(input, context);
};
exports.sometimesSlow = wrappedSometimesSlow;

[REQUIRED] Steps to reproduce

Write something to Firestore that matches foo/{bar} above. The path doesn't matter, and having a wildcard in the path doesn't matter.

[REQUIRED] Expected behavior

Since the above code doesn't require any sort of initialization once wrappedSometimesSlow is called, I'd expect this code to run in < 5ms. In reality, cold starts take between 900–4000+ ms. For most use cases, this initialization is unnecessary unless you need to access something like change.before.ref.firestore (it'd be nice if this returned a promise that could be lazy-loaded).

[REQUIRED] Actual behavior

Cold starts take between 900–4000+ ms. This is because a lot of things are being initialized, such as the Firestore instance (which in my benchmarks takes ~600+ ms to initialize).

I've experienced these very slow cold start times with a lot of the firebase-functions providers for different reasons. For example, the https onCall provider is slow because apps().admin.auth().verifyIdToken can take over a second to run, and the CORS preflight can add an additional 350-1200ms to cold starts.

The CORS preflight delay happens for custom domains because the Authorization header that's used by Firebase isn't one of the allowed simple request headers. The preflight delay can be overcome by monkey patching the firebase.functions(app)._url method in the client, but it'd be nice if there was an official way of doing this (or if Firebase just used simple requests for cloud function calls).

Were you able to successfully deploy your functions?

Yes.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions