TSR*_*TSR 16 firebase angularfire angular
我发现使用AngularFireAuthModulefrom '@angular/fire/auth';会导致内存泄漏,导致 20 小时后浏览器崩溃。
版本:
我使用今天更新的最新版本,对所有软件包使用 ncu -u。
角火: "@angular/fire": "^5.2.3",
Firebase 版本: "firebase": "^7.5.0",
如何重现:
我在StackBliztz 编辑器上做了一个最小的可重现代码
这里是直接测试bug的链接StackBlizt test
症状:
您可以自己检查代码是否没有任何作用。它只是打印 hello world。但是,Angular App 使用的 JavaScript 内存增加了11 kb/s(Chrome 任务管理器 CRTL+ESC)。打开浏览器 10 小时后,使用的内存达到约800 mb(内存占用量约为1.6 Gb 的两倍!)
结果,浏览器内存不足,chrome 选项卡崩溃。
在性能选项卡下使用chrome的内存分析进一步调查后,我清楚地注意到侦听器的数量每秒增加2个,因此JS堆相应增加。
导致内存泄漏的代码:
我发现使用该AngularFireAuthModule 模块会导致内存泄漏,无论是在component构造函数中还是在service.
import { Component } from '@angular/core';
import {AngularFireAuth} from '@angular/fire/auth';
import {AngularFirestore} from '@angular/fire/firestore';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'memoryleak';
constructor(public auth: AngularFireAuth){
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
这可能是 FirebaseAuth 实现中的一个错误,我已经打开了一个 Github 问题,但我正在寻找解决此问题的方法。我迫切需要一个解决方案。即使跨选项卡的会话不同步,我也不介意。我不需要那个功能。我在某处读到
如果您不需要此功能,Firebase V6 模块化工作将允许您切换到 localStorage,它具有用于检测交叉表更改的存储事件,并且可能会为您提供定义自己的存储接口的能力。
如果这是唯一的解决方案,那么如何实施?
我只需要任何解决方案来阻止这种不必要的侦听器增加,因为它会减慢计算机速度并使我的应用程序崩溃。我的应用程序需要运行 20 多个小时,因此由于此问题,它现在无法使用。我迫切需要一个解决方案。
package-lock.json以确认您使用的是正确的版本。如果不确定,请重新安装firebase软件包。以前版本的 Firebase 通过 Promise 链轮询 IndexedDB,这会导致内存泄漏,请参阅JavaScript 的 Promise Leaks Memory
var repeat = function() {
self.poll_ =
goog.Timer.promise(fireauth.storage.IndexedDB.POLLING_DELAY_)
.then(goog.bind(self.sync_, self))
.then(function(keys) {
// If keys modified, call listeners.
if (keys.length > 0) {
goog.array.forEach(
self.storageListeners_,
function(listener) {
listener(keys);
});
}
})
.then(repeat)
.thenCatch(function(error) {
// Do not repeat if cancelled externally.
if (error.message != fireauth.storage.IndexedDB.STOP_ERROR_) {
repeat();
}
});
return self.poll_;
};
repeat();
Run Code Online (Sandbox Code Playgroud)
在使用非递归函数调用的后续版本中修复:
var repeat = function() {
self.pollTimerId_ = setTimeout(
function() {
self.poll_ = self.sync_()
.then(function(keys) {
// If keys modified, call listeners.
if (keys.length > 0) {
goog.array.forEach(
self.storageListeners_,
function(listener) {
listener(keys);
});
}
})
.then(function() {
repeat();
})
.thenCatch(function(error) {
if (error.message != fireauth.storage.IndexedDB.STOP_ERROR_) {
repeat();
}
});
},
fireauth.storage.IndexedDB.POLLING_DELAY_);
};
repeat();
Run Code Online (Sandbox Code Playgroud)
预计会线性增加侦听器数量,因为 Firebase 正在这样做以轮询 IndexedDB。但是,只要 GC 需要,就会删除侦听器。
阅读问题 576302:错误地显示内存(侦听器 xhr 和负载)泄漏
V8 会定期执行 Minor GC,这会导致堆大小的小幅下降。您实际上可以在火焰图上看到它们。然而,次要 GC 可能不会收集所有垃圾,这显然发生在侦听器上。
工具栏按钮调用能够收集侦听器的 Major GC。
DevTools 尽量不干扰正在运行的应用程序,因此它不会自行强制执行 GC。
为了确认分离的侦听器被垃圾收集,我添加了这个片段来对 JS 堆施压,从而强制 GC 触发:
var x = ''
setInterval(function () {
for (var i = 0; i < 10000; i++) {
x += 'x'
}
}, 1000)
Run Code Online (Sandbox Code Playgroud)
如您所见,触发 GC 时会定期删除分离的侦听器。
关于监听器数量和内存泄漏的类似 stackoverflow 问题和 GitHub 问题:
| 归档时间: |
|
| 查看次数: |
758 次 |
| 最近记录: |