通过使用查询而不是重复观察单个事件来加快获取我的社交网络应用程序的帖子 [英] Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly

查看:19
本文介绍了通过使用查询而不是重复观察单个事件来加快获取我的社交网络应用程序的帖子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组键,这些键可以为我的社交网络发布对象,例如/posts/id/(post info)

I have an array of keys which lead to post objects for my social network like so /posts/id/(post info)

当我加载帖子时,我使用 observeSingleEventOfType(.Value) 方法加载/posts/0 然后/posts/1 等.

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

我使用 lazyTableView 一次加载 30 个,而且速度很慢.有什么方法可以使用其中一种查询方法或另一种使其更快的方法,即使我必须重组 JSON 树中的数据.

I use a lazyTableView to load 30 at a time and it is quite slow. Is there any way I can use one of the query methods or another way of making it faster even if I have to restructure the data in my JSON tree.

我来自 Parse,正在重新实现我的应用程序,到目前为止体验非常好.只是这一件事我有点坚持.提前感谢您的帮助!

I am coming from Parse re-implementing my app and so far the experience as been quite good. Just this one thing I am a bit stuck on. Thanks in advance for the help!

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
        }
    }
}

这个递归函数本质上是从 firebase 获取键号 i 的值.如果它是 NSNULL 它知道这是最后可能加载的帖子并且永远不会再加载.如果 NSNULL 没有被命中但 i % 29 == 0 则它作为基本情况返回,因此一次只加载 30 个帖子(0 索引).当我将 doneLoading 设置为 true 时,会使用属性观察器调用 tableView.reloadData().

This recursive function essentially runs getting the value for key number i from firebase. If it is NSNULL it knows that is the last possible post to load and never does again. If NSNULL doesn't get hit but i % 29 == 0 then it returns as a base case so only 30 posts are loaded at a time (0 indexed). When I set doneLoading to true, tableView.reloadData() is called using a property observer.

这是我正在获取的数组的示例

Here is a sample of what the array I am fetching looks like

"ideaPosts" : [ {
    "id" : 0,
    "message" : "Test",
    "upvotes" : 1,
    "user" : "Anonymous"
  }, {
    "id" : 1,
    "message" : "Test2",
    "upvotes" : 1,
    "user" : "Anonymous"
  } ]

推荐答案

更新:我们现在也在 AskFirebase 剧集.

从 Firebase 加载许多项目不必很慢,因为您可以通过管道传输请求.但是您的代码使这成为不可能,这确实会导致性能欠佳.

Loading many items from Firebase doesn't have to be slow, since you can pipeline the requests. But your code is making this impossible, which indeed will lead to suboptimal performance.

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

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

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 秒,从磁盘加载项目也需要 1 秒,那么至少 30 * (1 + 1) = 60 秒.

In this scenario you're waiting for 30 times your roundtrip time + 30 times the time it takes to load the data from disk. If (for the sake of simplicity) we say that roundtrips take 1 second and loading an item from disk also takes one second that least to 30 * (1 + 1) = 60 seconds.

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

In Firebase applications you'll get much better performance if you send all the requests (or at least a reasonable number of them) in one go:

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 秒.

If we again assume a 1 second roundtrip and 1 second of loading, you're waiting for 30*1 + 1 = 31 seconds.

所以:所有请求都通过同一个连接.鉴于此,get(1)get(2)get(3)getAll([1,2,3]) 是帧的一些开销.

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

我设置了一个 jsbin 来演示该行为.数据模型非常简单,但它展示了差异.

I set up a jsbin to demonstrate the behavior. The data model is very simple, but it shows off 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'))
  );
}

为了比较:在我的系统上顺序加载 64 个项目需要 3.8 秒,而通过管道加载它们(就像 Firebase 客户端本机那样)需要 600 毫秒.确切的数字取决于您的连接(延迟和带宽),但流水线版本应该总是更快.

For comparison: sequentially loading 64 items takes 3.8 seconds on my system, while loading them pipelined (as the Firebase client does natively) it takes 600ms. The exact numbers will depend on your connection (latency and bandwidth), but the pipelined version should always be significantly faster.

这篇关于通过使用查询而不是重复观察单个事件来加快获取我的社交网络应用程序的帖子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆