更新:2018年2月12日 - iOS Firestore SDK v0.10.0
与其他评论者类似,我也注意到第一次获取请求的响应速度较慢(后续请求大约需要100毫秒)。对我来说并不像30秒那么糟糕,但是在我有良好的连接时可能需要2-3秒,这足以在应用程序启动时提供不良用户体验。
Firebase表示他们已经意识到这个“冷启动”问题,并且正在为其寻求长期解决方案-不幸的是没有时间表。我认为当我连接质量差时,可能需要很长时间(超过30秒)才能从缓存中读取获取请求,这是一个单独的问题。
在Firebase解决所有这些问题之前,我开始使用新的disableNetwork()
和enableNetwork()
方法(在Firestore v0.10.0中可用)手动控制Firebase的在线/离线状态。尽管我必须在我的代码中非常小心地使用它,因为有一个Firestore错误,可以在某些情况下导致崩溃。
更新:2017年11月15日 - iOS Firestore SDK v0.9.2
似乎已经修复了性能缓慢的问题。我重新运行了下面描述的测试,现在Firestore返回100个文档所需的时间似乎始终稳定在约100毫秒左右。
不确定这是最新SDK v0.9.2中的修复还是后端的修复(或两者都有),但我建议每个人都更新他们的Firebase pods。我的应用程序响应速度明显更快-类似于Realtime DB。
我还发现Firestore比Realtime DB慢得多,特别是在读取大量文档时。
使用最新的iOS Firestore SDK v0.9.0进行更新测试:
我使用iOS Swift在RTDB和Firestore中设置了一个测试项目,并在每个数据库上运行了100个连续读取操作。对于RTDB,我测试了每个100个顶级节点上的observeSingleEvent和observe方法。对于Firestore,我在TestCol集合的每个100个文档中使用了getDocument和addSnapshotListener方法。我打开和关闭了磁盘持久性选项,并请参考附图,该图显示了每个数据库的数据结构。
我在同一设备和稳定的wifi网络上为每个数据库运行了10次测试。在每次新运行之前,销毁现有的观察者和监听器。
Realtime DB 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中的问题所在?