Speed โ€‹โ€‹up message retrieval for my application on the social network by using a query instead of re-observing a single event

I have an array of keys that lead to the publication of objects for my social network, for example, / posts / id / (publication information)

When I load posts, I load / posts / 0 and then / posts / 1 etc. Using the observeSingleEventOfType(.Value) method.

I am using lazyTableView to load 30 at the same time, and it is rather slow. Is there a way that I can use one of the request methods or another way to do it faster even if I have to restructure the data in my JSON tree.

I come from Parse, re-deploy my application, and so far the experience has been pretty good. Only one thing I'm stuck on a bit. Thanks in advance for your help!

EDIT:

 func loadNext(i: Int) { // check if exhists let ideaPostsRef = Firebase(url: "https://APPURL") ideaPostsRef.childByAppendingPath(i.description).observeSingleEventOfType(.Value, withBlock: { (snapshot) in if i % 29 == 0 && i != 0 && !self.hitNull { return } // false if nil // true if not nil if !(snapshot.value is NSNull) { let postJSON = snapshot.value as! [String: AnyObject] print("GOT VALID \(postJSON)") let post = IdeaPost(message: postJSON["message"] as! String, byUser: postJSON["user"] as! String, withId: i.description) post.upvotes = postJSON["upvotes"] as! Int self.ideaPostDataSource.append(post) self.loadNext(i + 1) } else { // doesn't exhist print("GOT NULL RETURNING AT \(i)") self.doneLoading = true self.hitNull = true return } } } 

This recursive function, in fact, starts getting the value for key number i from firebase. If it's NSNULL, he knows this is the last possible post to download, and never does again. If NSNULL is not received, but i % 29 == 0 it is returned as the base case, so only 30 messages are loaded at the same time (indexed 0). When I set doneLoading to true , tableView.reloadData() is called using the property observer.

Here is an example of what the array I select looks like

 "ideaPosts" : [ { "id" : 0, "message" : "Test", "upvotes" : 1, "user" : "Anonymous" }, { "id" : 1, "message" : "Test2", "upvotes" : 1, "user" : "Anonymous" } ] 
+80
ios swift firebase
Mar 11 '16 at 3:11
source share
1 answer

Update: Now we also address this issue in the AskFirebase episode.

Loading many items from Firebase does not have to be slow, because you can pipelining requests. But your code makes this impossible, which will really lead to suboptimal performance.

In your code, you request an item from the server, wait for that item to return, and then download the next one. In a simplified sequence diagram that looks like this:

 Your app Firebase Database -- request item 1 --> SL eo ra vd ei <- return item 1 -- rn g -- request item 2 --> SL eo ra vd ei rn <- return item 2 -- g -- request item 3 --> . . . -- request item 30--> SL eo ra vd ei rn g <- return item 30 -- 

In this scenario, you expect 30 times your time to capture + 30 times the time it takes to load data from disk. If (for simplicity) we say that roundtrips take 1 second, and loading an item from disk also takes one second, which is less than 30 * (1 + 1) = 60 seconds.

In Firebase applications, you will get much better performance if you send all the requests (or at least a reasonable number of them) at once:

 Your app Firebase Database -- request item 1 --> -- request item 2 --> SL -- request item 3 --> eo . ra . vd . ei -- request item 30--> rn g <- return item 1 -- <- return item 2 -- <- return item 3 -- . . . <- return item 30 -- 

If we again take the 1 second circuit and 1 second boot, you wait 30 * 1 + 1 = 31 seconds.

So: all requests go through the same connection. Given this, the only difference between get(1) , get(2) , get(3) and getAll([1,2,3]) are some overhead for frames.

I installed jsbin to demonstrate the behavior . The data model is very simple, but it shows the difference.

 function loadVideosSequential(videoIds) { if (videoIds.length > 0) { db.child('videos').child(videoIds[0]).once('value', snapshot => { if (videoIds.length > 1) { loadVideosSequential(videoIds.splice(1), callback) } }); } } function loadVideosParallel(videoIds) { Promise.all( videoIds.map(id => db.child('videos').child(id).once('value')) ); } 

For comparison: sequential loading of 64 elements takes 3.8 seconds on my system, and when loading them pipeline (since the Firebase client is executed initially), it takes 600 ms. The exact numbers will depend on your connection (latency and bandwidth), but the pipelined version should always be significantly faster.

+104
Mar 11 '16 at 5:18
source share
โ€” -



All Articles