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

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

问题描述

我有一个键数组,导致我的社交网络,如so / posts / id /(发布信息)post对象

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

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

我是从Parse重新实现我的应用程序,到目前为止经验相当不错。只是这一点我有点卡住了。

编辑:

  func loadNext(i:Int)
{
//检查是否存在
让ideaPostsRef = Firebase(url:https:// APPURL)
ideaPostsRef .childByAppendingPath(i.description).observeSingleEventOfType(.Value,withBlock:{
(snapshot)in
if i%29 == 0&& i!= 0&&!self。 hitNull {return}
// false如果nil
// true如果不是n
if!(snapshot.value是NSNull)
{
let postJSON = snapshot。值为![String:AnyObject]
print(GOT VALID \(postJSON))
let post = IdeaPost(message:postJSON [message] as!String,byUser:postJSON [用户] as!String,withId:i.description)
post.upvotes = postJSON [upvotes] as!Int
self.ideaPostDataSource.append(post)
self.loadNext(i + 1)
}
else
{
//不存在
print(GOT NULL RETURNING AT \(i) )
self.doneLoading = true
self.hitNull = true
return
}
})

这个递归函数本质上是从firebase获取关键字i的值。如果它是NSNULL它知道这是最后一个可能的职位加载,永远不会再次。如果NSNULL没有被击中,但是我%29 == 0然后它返回作为一个基本情况,所以一次只加载30个职位(索引0)。当我设置doneLoading为真 tableView.reloadData()是使用属性观察器调用的。



下面是我要读取的数组的示例:

 ideaPosts:[{
id:0,
message:Test,
upvotes:1,
user:Anonymous

id:1,
message:Test2,
upvotes:1,
user:Anonymous
]


解决方案

:我们现在也在 AskFirebase插曲中讲述这个问题。



从Firebase加载多个项目不一定很慢,因为您可以管理请求。但是,你的代码使得这是不可能的,这确实会导致性能不理想。



在你的代码中,你从服务器请求一个项目,等待这个项目返回然后加载下一个。在一个简化的顺序图,看起来像:

 您的应用程序Firebase 
数据库

- - 请求项目1 - >
SL
eo $ b $文胸
vd
ei
< - 退货商品1 - 商品
g
- 商品2 - > ;
SL
eo $ b $文胸
vd
ei
rn
< - 退换商品2 - g
- 要求商品3 - > ;



- 申请项目30 - >
SL
eo
ra
vd
ei
rn
g
< - 退货产品30 -

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

 您的应用程序Firebase 
数据库

- 请求项目1 - >
- 要求项目2 - > S L
- 要求项目3 - > e o
。 r a
。 v d
。 e i
- 请求项目30 - > r n
g
< - 退货项目1 -
< - 退货项目2 -
< - 退货项目3 -



< - 退货项目30 -

如果我们再次假设1秒的往返1秒的加载,你正在等待30 * 1 + 1 = 31秒。

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



我设置了一个 jsbin来演示行为。数据模型非常简单,但它显示了差异。
$ b $ pre $ 函数loadVideosSequential(videoIds){
if(videoIds.length> 0){
db。 (videoIds.length> 1){
loadVideosSequential(videoIds.splice(')')。 1),回调)
}
});



函数loadVideosParallel(videoIds){
Promise.all(
videoIds.map(id => db.child('videos ').child(id).once('value'))
);



$ b

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


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

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

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.

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!

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

解决方案

Update: we now also cover this question in an AskFirebase episode.

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

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.

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

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

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.

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

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天全站免登陆