Ich habe festgestellt, dass die Verwendung von AngularFireAuthModule
from '@angular/fire/auth';
einen Speicherverlust verursacht, der den Browser nach 20 Stunden zum Absturz bringt.
Ausführung:
Ich verwende die neueste Version, die heute mit ncu -u aktualisiert wurde, für alle Pakete.
Winkelfeuer: "@angular/fire": "^5.2.3",
Firebase-Version : "firebase": "^7.5.0"
,
So reproduzieren Sie:
Ich habe im StackBliztz-Editor einen reproduzierbaren Mindestcode erstellt
Hier ist der Link, um den Fehler direkt StackBlizt-Test zu testen
Symptom:
Sie können selbst überprüfen, ob der Code nichts bewirkt. Es druckt nur Hallo Welt. Der von der Angular App verwendete JavaScript-Speicher erhöht sich jedoch um 11 kb / s (Chrome Task Manager CRTL + ESC). Nach 10 Stunden, in denen der Browser geöffnet ist, erreicht der verwendete Speicher ca. 800 MB (der Speicherbedarf beträgt etwa zweimal 1,6 GB !).
Infolgedessen hat der Browser nicht mehr genügend Speicher und die Chrome-Registerkarte stürzt ab.
Nach weiteren Untersuchungen unter Verwendung des Speicherprofils von Chrome unter der Registerkarte "Leistung" stellte ich klar fest, dass die Anzahl der Listener jede Sekunde um 2 zunimmt und der JS-Heap entsprechend zunimmt.
Code, der den Speicherverlust verursacht:
Ich fand heraus, dass die Verwendung des AngularFireAuthModule
Moduls den Speicherverlust verursacht, unabhängig davon, ob es in einen component
Konstruktor oder in einen injiziert wird 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){
}
}
Frage :
Es könnte ein Fehler in der Implementierung von FirebaseAuth sein, und ich habe bereits ein Github-Problem geöffnet, suche jedoch nach einer Problemumgehung für dieses Problem. Ich bin verzweifelt nach einer Lösung. Es macht mir nichts aus, auch wenn die Sitzungen über Registerkarten nicht synchronisiert sind. Ich brauche diese Funktion nicht. Ich habe das irgendwo gelesen
Wenn Sie diese Funktionalität nicht benötigen, können Sie mit den Modularisierungsbemühungen von Firebase V6 zu localStorage wechseln, das Speicherereignisse zum Erkennen von Kreuztabellen für Änderungen enthält, und möglicherweise die Möglichkeit bieten, Ihre eigene Speicherschnittstelle zu definieren.
Wenn das die einzige Lösung ist, wie kann man das implementieren?
Ich brauche nur eine Lösung, die diese unnötige Erhöhung des Hörers stoppt, weil sie den Computer verlangsamt und meine App zum Absturz bringt. Meine App muss länger als 20 Stunden laufen, damit sie aufgrund dieses Problems nicht mehr verwendet werden kann. Ich bin verzweifelt nach einer Lösung.
Antworten:
TLDR: Das Erhöhen der Listener-Nummer ist ein erwartetes Verhalten und wird bei der Garbage Collection zurückgesetzt. Der Fehler, der zu Speicherverlusten in Firebase Auth führt, wurde bereits in Firebase v7.5.0 behoben. Siehe # 1121. Überprüfen Sie
package-lock.json
, ob Sie die richtige Version verwenden. Wenn Sie sich nicht sicher sind, installieren Sie dasfirebase
Paket erneut.In früheren Versionen von Firebase wurde IndexedDB über Promise Chaining abgefragt, was zu Speicherlecks führt. Weitere Informationen finden Sie im JavaScript Promise Leaks Memory
In nachfolgenden Versionen mit nicht rekursiven Funktionsaufrufen behoben:
In Bezug auf linear ansteigende Hörerzahl:
Es wird erwartet, dass die Anzahl der Listener linear erhöht wird, da Firebase dies tut, um IndexedDB abzufragen. Listener werden jedoch entfernt, wann immer der GC dies wünscht.
Read Issue 576302: Speicherleck (Listener xhr & load) wird falsch angezeigt
Um zu bestätigen, dass getrennte Listener Müll gesammelt haben, habe ich dieses Snippet hinzugefügt, um den JS-Heap unter Druck zu setzen, wodurch GC gezwungen wird, Folgendes auszulösen:
Wie Sie sehen können, werden getrennte Listener regelmäßig entfernt, wenn GC ausgelöst wird.
Ähnliche Stackoverflow-Fragen und GitHub-Probleme bezüglich Listener-Nummer und Speicherlecks:
quelle
this.auth.auth.setPersistence('none')
inngOnInit
anstelle des Konstrukteurs zu deaktivieren Ausdauer.ngOnInit
?setPersistence
Aufrufarten ausgeführt und festgestellt, dass, wenn dies im Konstruktor ausgeführt wird, weiterhin Funktionsaufrufe an IndexedDB ausgeführt werden, während bei dieser AusführungngOnInit
keine Aufrufe an IndexedDB vorgenommen wurden, nicht genau sicher warum aber