Oli*_*r P 67 javascript performance firebase angularfire2 google-cloud-firestore
与具有1/10比率的实时数据库相比,我检索存储在文档中的基本数据时,Firestore的性能问题很慢.
使用Firestore,第一次调用平均需要3000毫秒
this.db.collection(‘testCol’)
.doc(‘testDoc’)
.valueChanges().forEach((data) => {
console.log(data);//3000 ms later
});
Run Code Online (Sandbox Code Playgroud)
使用实时数据库,第一次调用平均需要300毫秒
this.db.database.ref(‘/test’).once(‘value’).then(data => {
console.log(data); //300ms later
});
Run Code Online (Sandbox Code Playgroud)
这是网络控制台的屏幕截图:
我正在使用AngularFire2 v5.0 rc.2运行Javascript SDK v4.50.
有没有人遇到过这个问题?
Sau*_*aul 41
更新:2018年2月12日 - iOS Firestore SDK v0.10.0
与其他一些评论者类似,我也注意到第一个获取请求的响应速度较慢(后续请求需要大约100毫秒).对我而言,它并不像30秒那么糟糕,但是当我有良好的连接时,可能大约2-3秒,这足以在我的应用程序启动时提供糟糕的用户体验.
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容器.我的应用程序响应速度明显更快 - 类似于Realtime DB上的应用程序.
我还发现Firestore比Realtime DB慢得多,特别是在阅读大量文档时.
更新的测试(使用最新的iOS Firestore SDK v0.9.0):
我使用RTDB和Firestore在iOS Swift中设置了一个测试项目,并对每个项目运行了100次顺序读取操作.对于RTDB,我测试了observeSingleEvent并观察了100个顶级节点中每个节点的方法.对于Firestore,我在TestCol集合中的每个文档中使用了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)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
实时数据库观察方法:
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)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
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)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
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)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
当方法开始执行时,每种方法基本上以毫秒为单位打印unix时间戳,然后在每次读取操作返回时打印另一个unix时间戳.我取了初始时间戳和最后一个时间戳之间的差异来返回.
结果 - 禁用磁盘持久性:
结果 - 启用磁盘持久性:
数据结构:
当Firestore getDocument/addSnapshotListener方法卡住时,似乎卡住了大约30秒的倍数的持续时间.也许这可以帮助Firebase团队隔离SDK卡在哪里?
Ter*_*nce 19
更新日期2018年3月2日
看起来这是一个已知问题,Firestore的工程师正在努力修复.在这个问题上与Firestore工程师进行了几次电子邮件交流和代码共享后,这是他今天的回复.
"你实际上是正确的.进一步检查后,getDocuments()API的这种缓慢是Cloud Firestore beta中的已知行为.我们的工程师意识到这个性能问题标记为"冷启动",但不要担心我们正在做我们最好的提高Firestore查询性能.
我们已经在进行长期修复,但目前我无法分享任何时间表或细节.虽然Firestore仍处于测试阶段,但预计会有更多改进."
所以希望这很快就会被淘汰出局.
使用Swift/iOS
在处理了这个约3天之后,似乎问题肯定是get()即.getDocuments和.getDocument.我认为的事情导致极端但间歇性的延迟,但似乎并非如此:
我能够将所有这些都排除在外,因为我注意到这个问题并没有发生在我正在制作的每个Firestore数据库调用中.仅使用get()进行检索.对于踢,我用.addSnapshotListener替换.getDocument来检索我的数据和瞧.每次包括第一次通话即时检索.没有感冒开始.到目前为止,.addSnapshotListener没有任何问题,只有getDocument(s).
现在,我只是简单地删除.getDocument(),其中时间至关重要,并用.addSnapshotListener替换它然后使用
for document in querySnapshot!.documents{
// do some magical unicorn stuff here with my document.data()
}
Run Code Online (Sandbox Code Playgroud)
...为了继续前进,直到Firestore解决了这个问题.
直到今天早上我才遇到这个问题.我通过iOS/Swift查询Firestore大约需要20秒才能完成一个简单的完全索引查询 - 返回1个项目的非比例查询时间 - 一直到3,000.
我的解决方案是禁用脱机数据持久性.就我而言,它不适合我们的Firestore数据库的需求 - 每天都有大部分数据更新.
iOS和Android用户默认启用此选项,而Web用户默认禁用此选项.如果您查询大量文档,它会使Firestore看起来非常慢.基本上它会缓存您查询的任何数据的副本(以及您查询的任何集合 - 我相信它会缓存所有文档),这会导致内存使用率过高.
在我的情况下,它导致了每个查询的巨大等待,直到设备缓存了所需的数据 - 因此,从完全相同的集合返回的越来越多的项目的非比例查询时间.这是因为在每个查询中缓存集合花费的时间相同.
我执行了一些基准测试,以便从同一个查询集合中显示此效果(启用了脱机持久性),但使用.limit参数返回的项目数量不同:
现在返回100个项目(禁用离线持久性),我的查询完成时间不到1秒.
我的Firestore查询代码如下:
let db = Firestore.firestore()
self.date = Date()
let ref = db.collection("collection").whereField("Int", isEqualTo: SomeInt).order(by: "AnotherInt", descending: true).limit(to: 100)
ref.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
let data = document.data()
//Do things
}
print("QUERY DONE")
let currentTime = Date()
let components = Calendar.current.dateComponents([.second], from: self.date, to: currentTime)
let seconds = components.second!
print("Elapsed time for Firestore query -> \(seconds)s")
// Benchmark result
}
}
Run Code Online (Sandbox Code Playgroud)
差不多 3 年后,firestore 已经完全退出测试版,我可以确认这个可怕的问题仍然存在;-(
在我们的移动应用程序中,我们使用 javascript / node.js firebase 客户端。在经过大量测试以找出为什么我们的应用程序的启动时间约为 10 秒后,我们确定了将 70% 的时间归因于……嗯,firebase 和 firestore 的性能和冷启动问题:
因此,用户初始化总共需要 6 - 7 秒,这是完全不可接受的。我们对此无能为力。我们无法测试禁用持久性,因为在 javascript 客户端中没有这样的选项,默认情况下始终启用持久性,因此不调用 enablePersistence() 不会改变任何内容。
归档时间: |
|
查看次数: |
23032 次 |
最近记录: |