AndroidAndroid开发经验谈首页投稿(暂停使用,暂停投稿)

[译]FaceBook出品:开始用FlatBuffers替换老旧

2016-07-30  本文已影响1893人  豆沙包67

原文地址

人们通过FaceBook关注家人朋友的动态更新,浏览他们上传的照片。我们的后端存储了组成社交媒介的数据结构。在移动手机端,我们不能拉取整个数据结构,所以只拉取某个节点和其相关的联系构成的树状结构。

下图说明了一条带图朋友圈的工作原理。John发了一条朋友圈,之后他的朋友进行了点赞和评论,左边的图是社交图,用于后端的关系展示。当Android应用查询这条朋友圈时,就可以拉取到树状结构,包括作者信息,反馈和图片信息(右图展示)。

tree structure

应用的关键在于展现和存储信息。使用SQLite数据库把全部数据持久化是不现实的,因为有很多方法从后端获取到某个节点的树状数据。其中一个可行的方法是使用Json来存储树状信息,但是UI展示数据时,需要额外的开销把Json解析成为Java对象,包括时间,我们在Android上使用Jackson Json解析器,有如下缺点:

我们希望有一个更好的存储格式来提高Android应用的体验。

FlatBuffers

在可行的替代格式的探索中,我们碰到了 FlatBuffers,Google的一个开源项目。FlatBuffers是协议缓冲区的一个演化,它包括了元数据,可以在不反序列化整个对象的前提下,直接取到这个对象中的某个子数据(例如上述的树状结构)。

想象一个简单的类,有四个变量:姓名,关系,配偶,朋友列表。其中配偶和朋友也是Person对象,所以构成了一个树状结构。下面简单地分析,如何使用FlatBuffers来表示一个人,John,他的配偶,Mary。

class Person {
    String name;
    int friendshipStatus;
    Person spouse;
    List<Person>friends;
}
Show FlatBuffers

注意上述结构的几个方面:

下面的代码片段展示了如何在这个数据结构中取得John的配偶信息:

// Root object position is normally stored at beginning of flatbuffer.
int johnPosition = FlatBufferHelper.getRootObjectPosition(flatBuffer);
int maryPosition = FlatBufferHelper.getChildObjectPosition(
   flatBuffer,
   johnPosition, // parent object position
   2 /* field number for spouse field */);
String maryName = FlatBufferHelper.getString(
   flatBuffer,
   johnPosition, // parent object position
   2 /* field number for name field */);

注意并没有涉及中间对象,节省了内存分配。更进一步,可以使用FlatBuffers数据进行存储,直接映射到内存中。这意味着我们只需要加载我们需要的部分数据,大大减少了过度的数据加载。

更重要的是,在读取变量之前不需要反序列整个对象。这减少了UI层和数据层之间的交互时间,提高了性能。

FlatBuffers的动态更新

数据是随着时间改变的,所以要更新FlatBuffers中存储的数据。因为FlatBuffers是设计为不可变的,所以没有直接的方法实现动态更新。解决方案是使用原始FlatBuffers数据进行比较。

FlatBuffer中每一块数据拥有独一无二的绝对位置,为了不需要每次都下载整个数据块,希望实现动态更新——例如关系的变更,下面举例子说明如何进行比较的:

friend status

当查询FlatBuffer数据时,可以计算出数据的绝对位置,查看Mutation Buffer看是否有动态更新,如果没有则返回Base Buffer

扁平化Models

FlatBuffer可以作为应用的内存格式来处理数据存储和网络请求。它消除了从后端数据转化成前端UI展示的额外开销,也让我们转向于更为简洁的扁平化Models的架构,减少了UI层和数据层之间的复杂性。

使用Json作为数据格式时,为了用户体验,通常会在反序列化的时候做一些缓存,UI层和数据层之间添加了应用和网络的逻辑。

Json Architecture

iOS和桌面应用采用这种三层架构很普遍,在Android上就有缺点了:

使用扁平化Models,UI层和数据层的交互就更为简单了,像下面图示:


Flat Models

结论

FlatBuffers减少了UI层和数据层之间数据转换的花销,同样驱动了应用的架构升级。动态更新策略可以随时了解后端数据的更新,而本地状态统统存储在一个小小的数据结构中,大大减少了额外的花销。

我们用六个月时间完成了大部分Facebook的Android应用使用FlatBuffers作为存储格式,发现:

很兴奋使用一个新的数据结构,让用户在看到朋友的动态如此迅速,感谢FlatBuffers

上一篇 下一篇

猜你喜欢

热点阅读