Search Lessons, Code Snippets, and Videos
search by algolia
X
#native_cta# #native_desc# Sponsored by #native_company#

Firebase Database Performance Profiling and Analysis

Episode 49 written by Jeff Delaney
full courses and content on fireship.io

The Firebase database can seem like magic, but it’s important to understand

In this lesson, I am going to show you how to performance test the Firebase realtime database and show a couple important concepts you may not be aware of.

Running a Database Profile

You can run a profile on the firebase database from the command line with…

firebase database:profile

example of firebase database profile

This will give us several pieces of useful information about speed

  1. Write Speed - Time to add new data.
  2. Read Speed - Time to read data (not actually user latency)
  3. Broadcast Speed - Time to update clients listening to data.

And some information about memory

  1. Downloaded bytes
  2. Uploaded bytes

And it can detect other potential problems

  1. Detects permission denied queries.
  2. Detects unindexed queries.

How to Time Round-Trip Firebase Query

For most developers, the single most important thing to know is how long it takes from the point data is requested to the point it is received. Latency has a major impact on the user experience. It’s partially dependent on Firebase, but also depends on how your app was designed and the user’s network speed.

RxJS Stopwatch

To time the round trip Firebase query, I created an Observable interval that will tick every 1ms. You can use it by calling start() before a query, then finish() as soon as you receive data. You could do this will vanilla JS, but I find this solution more readable.

export class StopWatch {
time: number;
interval: any;

start() {
this.interval = Observable.interval(1).subscribe(i => this.time = i)
}

finish() {
this.interval.unsubscribe()
}
}

Non-Blocking Database Queries

One of the coolest things about Firebase is the ability to send and receive requests in a non-blocking manner, known as pipelining. When you query Firebase, you don’t need to wait for response A to send request B. You can send all requests at the same time and Firebase will response with data as soon as it’s ready.

Example in Angular

Imagine we have a list of 50 post push keys from FirebaseListObservable. You would think it’s super inefficient to make 50 individual queries - not true.

<div *ngFor="let post of posts">
<post-info [pushKey]="post.$key"></post-info>
</div>
/// query Firebase object 50 times
this.post = this.db.object('posts/' + pushKey)

how request and responses work in firebase

Notice how we get send six requests, then get them all back at once. Firebase does not force you to wait from a response, rather it sends the responses back when they’re ready. This makes it possible to send multiple queries at the same time without major performance issues.

Indexed vs Non-Indexed

Indexing data can be vastly improve performance when sorting a list by a child value. Here’s an example of a plain Firebase query ordred by a child value.

database.ref('test/').orderByChild('latitude').equalTo(37.8267)

And the same thing with AngularFire2

db.list('test', {
query: {
orderByChild: 'latitude',
equalTo: 37.8267
}
});

If you try to make this query, you will end up with a warning from Firebase in the console and in the database profile. You can create an index by using indexOn in the firebase database rules.

firebase indexon warning how to fix it

Adding the index will vastly improve query performance on large lists.

database.rules.json

To fix the indexOn warning, simply point .indexOn to the child property in the database rules.

"test": {
".write": true,
".indexOn": "latitude"
}

The End

That’s it for Firebase Database profiling. I will be releasing another related post soon that talks about data modeling for optimial performance in NoSQL.