Skip to content

Instantly share code, notes, and snippets.

@puf
Last active September 12, 2023 10:22
Show Gist options
  • Save puf/05cae4c18bb0f031e16d9bc46ed9748a to your computer and use it in GitHub Desktop.
Save puf/05cae4c18bb0f031e16d9bc46ed9748a to your computer and use it in GitHub Desktop.
//
// This script compares the performance of three common ways to perform
// bulk write operations on Firestore.
//
// In test run of this script, it took:
//
// 1. `~105.4s` when using sequential individual write operations
// 2. `~ 2.8s` when using sequential batched write operations
// 3. `~ 1.5s` when using parallel individual write operations
// 4. `~ 1.5s` when using parallel batched write operations
//
// For a full comparison, see
// [What is the fastest way to write a lot of documents to Firestore?](https://stackoverflow.com/q/58897274).
//
// To use this script you will need to set the `GOOGLE_APPLITION_CREDENTIALS
// as described in the Firebase documentation on
// [initializing the SDK](https://firebase.google.com/docs/admin/setup#initialize_the_sdk)
//
(async function() {
var admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
let datas = [];
for (let i=0; i < 1000; i++) {
let data = {};
for (let j=0; j < 10; j++) {
const random = Math.random();
if (random < 0.2) {
data["field"+j] = "";
for (let k=0; k < Math.random()*10; k++) {
data["field"+j] += Math.random().toString(36).substring(2, 15)
if (Math.random() < 0.5) data["field"+j] += " ";
}
}
else if (random < 0.4) {
data["field"+j] = Math.random()
}
else if (random < 0.6) {
data["field"+j] = Math.round(Math.random() * 100000);
}
else if (random < 0.8) {
data["field"+j] = Math.random() < 0.5;
}
else if (random < 0.9) {
data["field"+j] = new Date(Math.random() * Date.now());
}
else {
data["field"+j] = admin.firestore.FieldValue.serverTimestamp()
}
}
datas.push(data);
}
//console.log(datas);
let collection = admin.firestore().collection("58891568");
console.log(`Testing performance of writing ${datas.length} documents...`)
console.log(`There are now ${await getDocumentCount()} documents...\n`)
let timstamp;
timestamp = Date.now();
await testSequentialIndividualWrites(JSON.parse(JSON.stringify(datas)));
console.log(`sequential writes took ${Date.now() - timestamp} ms`);
console.log(`There are now ${await getDocumentCount()} documents...\n`)
timestamp = Date.now();
await testBatchedWrites(JSON.parse(JSON.stringify(datas)));
console.log(`Batched writes took ${Date.now() - timestamp} ms`);
console.log(`There are now ${await getDocumentCount()} documents...\n`)
timestamp = Date.now();
await testParallelBatchedWrites(JSON.parse(JSON.stringify(datas)));
console.log(`Parallel batched writes took ${Date.now() - timestamp} ms`);
console.log(`There are now ${await getDocumentCount()} documents...\n`)
timestamp = Date.now();
await testParallelIndividualWrites(JSON.parse(JSON.stringify(datas)));
console.log(`Parallel writes took ${Date.now() - timestamp} ms`);
console.log(`There are now ${await getDocumentCount()} documents...\n`)
async function testSequentialIndividualWrites(datas) {
while (datas.length) {
await collection.add(datas.shift());
}
}
async function testBatchedWrites(datas) {
let batch = admin.firestore().batch();
let count = 0;
while (datas.length) {
batch.set(collection.doc(Math.random().toString(36).substring(2, 15)), datas.shift());
if (++count >= 500 || !datas.length) {
await batch.commit();
batch = admin.firestore().batch();
count = 0;
}
}
}
async function testParallelIndividualWrites(datas) {
await Promise.all(datas.map((data) => collection.add(data)));
}
async function testParallelBatchedWrites(datas) {
let batches = [];
let batch = admin.firestore().batch();
let count = 0;
while (datas.length) {
batch.set(collection.doc(Math.random().toString(36).substring(2, 15)), datas.shift());
if (++count >= 500 || !datas.length) {
batches.push(batch.commit());
batch = admin.firestore().batch();
count = 0;
}
}
await Promise.all(batches);
}
async function getDocumentCount() {
return (await collection.get()).size;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment