Firebase Android:使用许多侦听器缓慢"加入",似乎与文档相矛盾

Kar*_*pka 7 android join database-performance firebase firebase-realtime-database

实施一个Android +火力地堡的应用程序,其具有多对多的关系:用户< - >窗口小部件(窗口小部件可被共享的多个用户).

注意事项:

  1. 列出用户拥有的所有小部件.
  2. 用户只能看到与他/她共享的小部件.
  3. 能够看到共享给定Widget的所有用户.
  4. 单个Widget可以由具有相同权限的多个用户拥有/管理(修改Widget并更改共享对象).与Google云端硬盘与特定用户共享的方式类似.

实现提取(join-style)的方法之一是遵循以下建议:https://www.firebase.com/docs/android/guide/structuring-data.html(" Joining Flattened Data"):

// fetch a list of Mary's groups
ref.child("users/mchen/groups").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
    // for each group, fetch the name and print it
    String groupKey = snapshot.getKey();
    ref.child("groups/" + groupKey + "/name").addListenerForSingleValueEvent(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot snapshot) {
        System.out.println("Mary is a member of this group: " + snapshot.getValue());
      }
      @Override
      public void onCancelled(FirebaseError firebaseError) {
        // ignore
      }
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

这引发了一个问题,即是否有许多听众会对性能产生负面影响,或者可能会达到一些硬限制.

但我们在文档中得到了保证:

单独查找每条记录真的可以吗?是.Firebase协议使用Web套接字,客户端库对传入和传出请求进行大量内部优化.在我们进入成千上万的记录之前,这种方法是完全合理的.实际上,下载数据所需的时间(即字节数)会使关于连接开销的任何其他问题黯然失色.

但是,可以肯定的是,我做了一个小测试应用程序,比较了两种方法:

  1. ValueEventListener一对一地将多个-s 附加到所有小部件(根据上面提到的Firebase的"结构化数据"指南)
  2. 将单个附加ChildEventListener到承载所有小部件的节点(需要在一个节点下充分构造用户的小部件)

测试了4种不同的设备和Android版本(4.x - 5.x).Firebase lib : 'com.firebase:firebase-client-android:2.3.1'.
在第一种方法中,表现相当令人失望.我一直看到~15-100个事件/秒.最低的性能,大约15个事件/ s经常出现,所以看起来应该认真对待.在这种情况下,如果用户有100个小部件,则需要大约6秒来获取有关所有小部件的信息(例如,滚动列表).这太慢了.使用1000个小部件,通过单独的侦听器获取其信息通常需要多达40秒.方式太慢了.

在第二种方法中,我观察到200-3000个事件/秒.因此比第一种方法快15-30倍!
因此看起来Firebase doc中的保证[...] Until we get into tens of thousands of records, this approach is perfectly reasonable [...]并不是真正准确的,因为它的工作速度有多慢.

鉴于这一切,我有4个相互关联的问题.

  1. 根据自己的经验/基准,任何人都可以确认/反驳我的发现吗?有关其他平台的信息也欢迎,因为有计划在多个平台上开发此应用程序.
  2. 可能出现如此显着的性能差异的原因是什么?内部数据结构可能呢?
  3. 有没有办法在保持第一种(多听众)方法的同时提高性能?
  4. 是否应该完全抛弃多侦听器方法,而采用Firebase + Udacity教程(https://github.com/udacity/ShoppingListPlusPlus在"userLists"节点中)中提供的非规范化多拷贝方法-用户的购物清单信息副本)?我在另一个问题中询问这种方法的含义 - Firebase:通过每用户副本构建数据?数据损坏的风险?.

任何其他提示/考虑因素欢迎.TIA.

Ale*_*amo 1

"This prompts the question whether having potentially many listeners will have a negative impact on performance or perhaps would hit some hard limit."

答案与Firebase Realtime database新的相同Cloud Firestore database

我不关心你有多少个连接或有多少个侦听器,重要的是你在客户端处理多少数据。

因此,如果您有 100 个侦听器,侦听 100 位小数据,那么这会非常便宜,但如果每个侦听器都侦听不断变化的数据流,那么对于客户端处理它来说,这会变得非常昂贵迅速地。

而且由于移动设备差异很大,因此很难知道有多少是太多。因此,如果您针对的是往往拥有非常高端手机的美国用户,那么如果我们针对的是手机功率低得多的国家/地区,这将是一个不同的限制。

因此,如果您根据活动的生命周期相应地删除侦听器,那么您可以拥有任意数量的侦听器,如此处所述

还有另一种方法,使用addListenerForSingleValueEvent. 在这种情况下,无需删除侦听器。