通过使用查询而不是反复观察单个事件,加快为我的社交网络应用程序提取帖子

时间:2016-03-11 03:11:32

标签: ios swift firebase

我有一系列键可以导致我的社交网络的帖子对象如/ post / id /(发布信息)

当我加载帖子时,我使用def index amount = BigDecimal.new(params[:amount]).to_i if amount < 0 if !cancel_processing(amount) return end else process(amount) end render json: {success: true} end def cancel_processing(amount) response = CancelProcessingService.call(amount) if response log_stuff else render json: {error: true} end response end 方法加载/发布/ 0然后/ posts / 1等。

我使用observeSingleEventOfType(.Value)一次加载30,而且速度很慢。有没有什么方法可以使用其中一种查询方法或其他方法使其更快,即使我必须重构我的JSON树中的数据。

我来自Parse重新实现我的应用程序,到目前为止,经验非常好。只有这一点我有点坚持。在此先感谢您的帮助!

修改

lazyTableView

这个递归函数基本上运行从firebase获取密钥号i的值。如果它是NSNULL,它知道这是最后一个可能加载的帖子,永远不会再做。如果NSNULL没有被击中但是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 } } } 则它作为基本案例返回,因此一次只加载30个帖子(0索引)。当我将i % 29 == 0设置为doneLoading时,使用属性观察者调用true

以下是我所获取的数组的示例

tableView.reloadData()

1 个答案:

答案 0 :(得分:106)

更新:我们现在还在AskFirebase episode中介绍了这个问题。

从Firebase加载许多项目并不一定很慢,因为您可以对请求进行管道传输。但是你的代码使这个变得不可能,这确实会导致性能欠佳。

在您的代码中,您从服务器请求一个项目,等待该项目返回,然后加载下一个项目。在简化的序列图中,如下所示:

Your app                     Firebase 
                             Database

        -- request item 1 -->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
        <-  return item  1 --  r  n
                                  g
        -- request item 2 -->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
                               r  n
        <-  return item  2 --     g
        -- request item 3 -->
                 .
                 .
                 .
        -- request item 30-->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
                               r  n
                                  g
        <-  return item 30 --

在这种情况下,您需要等待30倍的往返时间+ 30倍于从磁盘加载数据所需的时间。如果(为了简单起见)我们说往返需要1秒钟,从磁盘加载一个项目也需要一秒钟,最少到30 *(1 + 1)= 60秒。

在Firebase应用程序中,如果您一次性发送所有请求(或至少合理数量的请求),您将获得更好的性能:

Your app                     Firebase 
                             Database

        -- request item 1 -->
        -- request item 2 -->  S  L
        -- request item 3 -->  e  o
                 .             r  a
                 .             v  d
                 .             e  i
        -- request item 30-->  r  n
                                  g
        <-  return item  1 --     
        <-  return item  2 --      
        <-  return item  3 --
                 .
                 .
                 .
        <-  return item 30 --

如果我们再次假设1秒钟的往返和1秒钟的加载,那么您需要等待30 * 1 + 1 = 31秒。

所以:所有请求都通过相同的连接。鉴于此,get(1)get(2)get(3)getAll([1,2,3])之间的唯一区别是帧的开销。

我设置了jsbin to demonstrate the behavior。数据模型非常简单,但它显示了差异。

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'))
  );
}

为了进行比较:在我的系统上顺序加载64个项目需要3.8秒,而加载它们是流水线的(因为Firebase客户端本身就是这样)需要600毫秒。确切的数字取决于您的连接(延迟和带宽),但流水线版本应该总是快得多。