更新:2018 年 2 月 12 日 - iOS Firestore SDK v0.10.0
与其他一些评论者类似,我也注意到第一个 get 请求的响应较慢(后续请求需要大约 100 毫秒)。对我来说,它没有 30 秒那么糟糕,但是当我有良好的连接性时可能会在 2-3 秒左右,这足以在我的应用程序启动时提供糟糕的用户体验。
Firebase 已经告知他们已经意识到这个“冷启动”问题,并且他们正在努力解决这个问题——不幸的是没有 ETA。我认为这是一个单独的问题,当我的连接性较差时,在 get 请求决定从缓存中读取之前可能需要很长时间(超过 30 秒)。
虽然火力地堡修复所有这些问题,我一直在使用新开工disableNetwork()
和enableNetwork()
方法(在公司的FireStore v0.10.0可用),手动控制火力地堡的在线/离线状态。尽管我在代码中使用它时必须非常小心,因为在某些情况下有一个 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):
我在 iOS Swift 中使用 RTDB 和 Firestore 设置了一个测试项目,并对每个项目运行了 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)")
}
}
}
实时数据库观察方法:
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 时间戳。我取了初始时间戳和最后一个时间戳之间的差异来返回。
结果 - 磁盘持久性禁用:
结果 - 启用磁盘持久性:
数据结构:
当 Firestore getDocument / addSnapshotListener 方法卡住时,它似乎卡住了大约 30 秒的倍数的持续时间。也许这可以帮助 Firebase 团队隔离它在 SDK 中卡住的位置?