Home > Software engineering >  Firestore write functions taking too long when using for-loop
Firestore write functions taking too long when using for-loop

Time:12-20

I am running a for-loop function to create/add new documents to existing collection within Firestore from iOS app. Although I am only creating about 48 documents, which is much lower than stated write limit (500 documents per second) based on the documentation - enter image description here

Is this something that is normal? or is it that my swift code were not "optimized"? '

With advice from @Joakim Danielson, I tried to ADD/CREATE smaller number of documents to the Firestore, but the latency or the creation rate stayed about the same where each document took about 0.2 seconds to be created.

I am getting quite worried for the user experience of the app although it is only once that such creation process take place for a new user, I foresee larger number of documents being created a new user. Please review my code below and let me konw if there is any other best practice I can utilize.

Below is a screenshot of the Xcode console for reference on the time the documents get created.

enter image description here

func createAndReadUserSpecificDayProgramDataToFirestore() {
        print("codementor: createAndReadUserSpecificDayProgramDataToFirestore started")
        let tabbar = tabBarController as! MainTabBarController
        
        guard let userID = Auth.auth().currentUser?.uid else {
            print("no current user logged in")
            return
        }
        
        print("create user specific dayprogram profile using for loop and dayprogram list in tabbar")
        
        if tabbar.dayProgramList.count == 0 {
            
            print("tabbar day program list has no day program profile")
            return
        }
        
        startActivityIndicator()

        for dayprogram in tabbar.dayProgramList {
            
            print("dayprogram forloop executed")
            
            var ref: DocumentReference? = nil
            print("codementor: document is adding")
            ref = self.db.collection("Day").addDocument(data: [
                "author_uid": dayprogram.author_uid ?? "",
                "barbellWeight": dayprogram.barbellWeight ?? "",
                "benchWeight": dayprogram.benchWeight ?? "",
                "createDate": dayprogram.createDate ?? Date(),
                "dayId": dayprogram.dayId ?? "",
                "dayIntensity": dayprogram.dayIntensity ?? "",
                "daySequence": dayprogram.daySequence ?? "",
                "deadliftWeight": dayprogram.deadliftWeight ?? "",
                "defaultRestTime": dayprogram.defaultRestTime ?? "",
                "isPublicFlag": dayprogram.isPublicFlag ?? "",
                "lastUpdatedBy": dayprogram.lastUpdatedBy ?? "",
                "numberOfExercise": dayprogram.numberOfExercise ?? "",
                "overheadWeight": dayprogram.overheadWeight ?? "",
                "prcntComplete": dayprogram.prcntComplete ?? "",
                "squatWeight": dayprogram.squatWeight ?? "",
                "status": dayprogram.status ?? "",
                "targetRestEndHR": dayprogram.targetRestEndHR ?? "",
                "workoutDate": dayprogram.workoutDate ?? "",
                "workoutId": dayprogram.workoutId ?? "",
                "userID": userID
            ], completion: { err in
                
                self.programCount  = 1
                
                if self.programCount == tabbar.dayProgramList.count {
                    print("dayprogram forloop function, which is to create user specific profile completed at \(CFAbsoluteTimeGetCurrent())")
                    self.createAndOrReadUserSpecificDayProgramData()
                    self.stopActivityIndicator()
                    print("forlopp dayprogram all calls finished")
                }

                if let err = err {
                    print("Error adding user specific dayprogram profile: \(err)")
                } else {
                    print("timestamp successfully adding: \(CFAbsoluteTimeGetCurrent())")
                    print("User specific dayprogram profile added with ID: \(ref!.documentID)")
                }
                print("forlopp dayprogram \(ref!.documentID) finished")
                
            })

           print("forlopp dayprogram `dispatchGroup.leave()` was here, but this was the wrong place")
        }
        
        print("forlopp dayprogram more exucution if there was any")
        
    }

CodePudding user response:

Using batches instead of uploading individual documents

func createAndReadUserSpecificDayProgramDataToFirestore() {
    print("codementor: createAndReadUserSpecificDayProgramDataToFirestore started")
    let tabbar = tabBarController as! MainTabBarController
    
    guard let userID = Auth.auth().currentUser?.uid else {
        print("no current user logged in")
        return
    }
    
    print("create user specific dayprogram profile using for loop and dayprogram list in tabbar")
    
    if tabbar.dayProgramList.count == 0 {
        print("tabbar day program list has no day program profile")
        return
    }
    
    startActivityIndicator()
    let batch = db.batch()
    for dayprogram in tabbar.dayProgramList {
        print("dayprogram forloop executed")
        var ref: DocumentReference = db.collection("myCollection").document()
        batch.setData([
            "author_uid": dayprogram.author_uid ?? "",
            "barbellWeight": dayprogram.barbellWeight ?? "",
            // your data
            "workoutId": dayprogram.workoutId ?? "",
            "userID": userID
        ], forDocument: ref)
        self.programCount  = 1
    }
    // this writes everything to the database all at once.
    // if ANY of them fail, an error will be thrown
    // and the entire operation fails
    batch.commit { err in
        if self.programCount == tabbar.dayProgramList.count {
            print("dayprogram forloop function, which is to create user specific profile completed at \(CFAbsoluteTimeGetCurrent())")
            self.createAndOrReadUserSpecificDayProgramData()
            self.stopActivityIndicator()
            print("forlopp dayprogram all calls finished")
        }
    }
    print("forlopp dayprogram more exucution if there was any")
}
  • Related