更新:2018年2月12日-iOS Firestore SDK v0.10.0
与其他一些评论者相似,我也注意到对第一个get请求的响应速度较慢(后续请求大约需要100毫秒)。对我来说,这不像30s那样糟糕,但是当我拥有良好的连接性时,它可能约为2-3s,这足以在我的应用程序启动时提供糟糕的用户体验。
Firebase建议他们知道此“冷启动”问题,并且正在为此进行长期修复-不幸的是,没有ETA。我认为这是一个单独的问题,当我的连接性较差时,获取请求决定从缓存中读取数据可能要花一些时间(超过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 Pod。我的应用程序响应速度明显更快-类似于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次测试。每次新运行之前,现有的观察者和听众都被摧毁了。
实时数据库的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中卡住的位置?