更新:2018 年 2 月 12 日 - iOS Firestore SDK v0.10.0
与其他一些评论者类似,我也注意到第一个 get 请求的响应速度较慢(后续请求大约需要 100 毫秒)。对我来说,它没有 30 秒那么糟糕,但当我连接良好时,可能需要大约 2-3 秒,这足以在我的应用程序启动时提供糟糕的用户体验。
Firebase 表示他们已经意识到这个“冷启动”问题,并且正在努力解决该问题 - 不幸的是,没有预计到达时间。我认为这是一个单独的问题,当我的连接较差时,获取请求可能需要很长时间(超过 30 秒)才能决定从缓存中读取。
虽然 Firebase 解决了所有这些问题,但我已经开始使用新的disableNetwork()
and enableNetwork()
方法(在 Firestore v0.10.0 中提供)手动控制 Firebase 的在线/离线状态。虽然我不得不这样very请小心我在代码中使用它的地方,因为存在一个 Firestore 错误,在某些情况下可能会导致崩溃。
更新:2017 年 11 月 15 日 - iOS Firestore SDK v0.9.2
看来性能缓慢的问题现已得到解决。我重新运行了下面描述的测试,Firestore 返回 100 个文档所需的时间现在似乎始终在 100 毫秒左右。
不确定这是否是最新 SDK v0.9.2 中的修复或后端修复(或两者),但我建议每个人都更新其 Firebase pod。我的应用程序的响应速度明显更快 - 类似于实时数据库上的方式。
我还发现 Firestore 比实时数据库慢得多,尤其是在读取大量文档时。
更新的测试(使用最新的 iOS Firestore SDK v0.9.0):
我使用 RTDB 和 Firestore 在 iOS Swift 中设置了一个测试项目,并在每个项目上运行了 100 个顺序读取操作。对于 RTDB,我在 100 个顶级节点中的每一个上测试了observeSingleEvent 和observe 方法。对于 Firestore,我对 TestCol 集合中的 100 个文档中的每一个都使用了 getDocument 和 addSnapshotListener 方法。我在打开和关闭磁盘持久性的情况下运行了测试。请参阅附图,其中显示了每个数据库的数据结构。
我在同一设备和稳定的 WiFi 网络上对每个数据库运行了 10 次测试。现有的观察者和听众在每次新运行之前都会被销毁。
实时数据库observeSingleEvent方法:
func rtdbObserveSingle() {
let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
print("Started reading from RTDB at: \(start)")
for i in 1...100 {
Database.database().reference().child(String(i)).observeSingleEvent(of: .value) { snapshot in
let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
let data = snapshot.value as? [String: String] ?? [:]
print("Data: \(data). Returned at: \(time)")
}
}
}
实时DB观察方法:
func rtdbObserve() {
let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
print("Started reading from RTDB at: \(start)")
for i in 1...100 {
Database.database().reference().child(String(i)).observe(.value) { snapshot in
let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
let data = snapshot.value as? [String: String] ?? [:]
print("Data: \(data). Returned at: \(time)")
}
}
}
Firestore getDocument 方法:
func fsGetDocument() {
let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
print("Started reading from FS at: \(start)")
for i in 1...100 {
Firestore.firestore().collection("TestCol").document(String(i)).getDocument() { document, error in
let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
guard let document = document, document.exists && error == nil else {
print("Error: \(error?.localizedDescription ?? "nil"). Returned at: \(time)")
return
}
let data = document.data() as? [String: String] ?? [:]
print("Data: \(data). Returned at: \(time)")
}
}
}
Firestore addSnapshotListener 方法:
func fsAddSnapshotListener() {
let start = UInt64(floor(Date().timeIntervalSince1970 * 1000))
print("Started reading from FS at: \(start)")
for i in 1...100 {
Firestore.firestore().collection("TestCol").document(String(i)).addSnapshotListener() { document, error in
let time = UInt64(floor(Date().timeIntervalSince1970 * 1000))
guard let document = document, document.exists && error == nil else {
print("Error: \(error?.localizedDescription ?? "nil"). Returned at: \(time)")
return
}
let data = document.data() as? [String: String] ?? [:]
print("Data: \(data). Returned at: \(time)")
}
}
}
每个方法本质上都会在方法开始执行时打印以毫秒为单位的 unix 时间戳,然后在每个读取操作返回时打印另一个 unix 时间戳。我获取了初始时间戳和最后一个时间戳之间的差异来返回。
结果 - 磁盘持久性已禁用:
![Disk persistence disabled](https://i.stack.imgur.com/bol1S.png)
结果 - 启用磁盘持久性:
![Disk persistence enabled](https://i.stack.imgur.com/ZBdTB.png)
数据结构:
![Data Structure](https://i.stack.imgur.com/bDGDM.png)
当 Firestore getDocument / addSnapshotListener 方法卡住时,卡住的持续时间大约为 30 秒的倍数。也许这可以帮助 Firebase 团队隔离 SDK 中遇到问题的位置?