Was ist JavaScript-Speicherbereinigung? Was ist für einen Webprogrammierer wichtig, um die JavaScript-Speicherbereinigung zu verstehen, um besseren Code schreiben zu können?
297
Was ist JavaScript-Speicherbereinigung? Was ist für einen Webprogrammierer wichtig, um die JavaScript-Speicherbereinigung zu verstehen, um besseren Code schreiben zu können?
Antworten:
Eric Lippert hat vor einiger Zeit einen ausführlichen Blog-Beitrag zu diesem Thema geschrieben (zusätzlich zu VBScript ). Genauer gesagt schrieb er über JScript , die Microsoft-eigene Implementierung von ECMAScript, obwohl sie JavaScript sehr ähnlich ist. Ich würde mir vorstellen, dass Sie davon ausgehen können, dass die überwiegende Mehrheit des Verhaltens für die JavaScript-Engine von Internet Explorer gleich ist. Natürlich wird die Implementierung von Browser zu Browser unterschiedlich sein, obwohl ich vermute, dass Sie eine Reihe der gemeinsamen Prinzipien auf andere Browser anwenden können.
Zitiert von dieser Seite:
Der Hauptzweck der Speicherbereinigung besteht darin, dem Programmierer zu ermöglichen, sich keine Gedanken über die Speicherverwaltung der von ihm erstellten und verwendeten Objekte zu machen, obwohl dies natürlich manchmal nicht zu vermeiden ist. Es ist immer von Vorteil, zumindest eine ungefähre Vorstellung davon zu haben, wie die Speicherbereinigung funktioniert .
Historischer Hinweis: Eine frühere Überarbeitung der Antwort hatte einen falschen Verweis auf den
delete
Bediener. In JavaScript entfernt derdelete
Operator eine Eigenschaft aus einem Objekt und unterscheidet sich grundlegend vondelete
C / C ++.quelle
delete
falsch. Beispiel: Im ersten Beispiel sollten Sie stattdessendelete foo
zuerst den Ereignis-Listener über entfernenwindow.removeEventListener()
und dannfoo = null
die Variable überschreiben. im IE hättedelete window.foo
(aber nichtdelete foo
) auch funktioniert, wennfoo
es global gewesen wäre, aber selbst dann würde es nicht in FF oder Opera funktionierendelete
ist ein unärer Operator (ein Ausdruck), keine Anweisung (dh :)delete 0, delete 0, delete 3
. Es sieht aus wie eine Anweisung, wenn sie durch eine Ausdrucksanweisung ausgedrückt wird.Achten Sie auf Zirkelverweise, wenn es sich um DOM-Objekte handelt:
Speicherverlustmuster in JavaScript
Beachten Sie, dass der Speicher nur wiederhergestellt werden kann, wenn keine aktiven Verweise auf das Objekt vorhanden sind. Dies ist eine häufige Gefahr bei Schließungen und Ereignishandlern, da einige JS-Engines nicht prüfen, auf welche Variablen in inneren Funktionen tatsächlich verwiesen wird, sondern nur alle lokalen Variablen der umschließenden Funktionen beibehalten.
Hier ist ein einfaches Beispiel:
Eine naive JS-Implementierung kann nicht erfasst werden,
bigString
solange der Ereignishandler verfügbar ist. Es gibt verschiedene Möglichkeiten, um dieses Problem zu lösen, z. B. die EinstellungbigString = null
am Ende voninit()
(delete
funktioniert nicht für lokale Variablen und Funktionsargumente:delete
Entfernt Eigenschaften von Objekten, und auf das Variablenobjekt kann nicht zugegriffen werden - ES5 im strengen Modus löst sogar ein aus,ReferenceError
wenn Sie es versuchen um eine lokale Variable zu löschen!).Ich empfehle, unnötige Schließungen so weit wie möglich zu vermeiden, wenn Sie den Speicherverbrauch berücksichtigen.
quelle
Gutes Zitat aus einem Blog
Die DOM-Komponente ist "Garbage Collected", ebenso wie die JScript-Komponente. Wenn Sie also ein Objekt in einer der Komponenten erstellen und dann den Überblick über dieses Objekt verlieren, wird es schließlich bereinigt.
Zum Beispiel:
Wenn Sie diese Funktion aufrufen, erstellt die JScript-Komponente ein Objekt (mit dem Namen bigArray), auf das innerhalb der Funktion zugegriffen werden kann. Sobald die Funktion jedoch zurückkehrt, verlieren Sie den Überblick über bigArray, da es keine Möglichkeit mehr gibt, darauf zu verweisen. Nun, die JScript-Komponente erkennt, dass Sie den Überblick verloren haben, und so wird bigArray bereinigt - sein Speicher wird zurückgefordert. Das Gleiche funktioniert in der DOM-Komponente. Wenn Sie sagen
document.createElement('div')
oder etwas Ähnliches, erstellt die DOM-Komponente ein Objekt für Sie. Sobald Sie den Überblick über dieses Objekt verlieren, bereinigt die DOM-Komponente das zugehörige Objekt.quelle
Nach meinem besten Wissen werden die Objekte von JavaScript regelmäßig mit Müll gesammelt, wenn keine Verweise mehr auf das Objekt vorhanden sind. Dies geschieht automatisch, aber wenn Sie mehr über die Funktionsweise auf C ++ - Ebene erfahren möchten, ist es sinnvoll, sich den WebKit- oder V8-Quellcode anzusehen
Normalerweise müssen Sie jedoch nicht darüber nachdenken. In älteren Browsern wie IE 5.5 und früheren Versionen von IE 6 und möglicherweise aktuellen Versionen führen Schließungen jedoch zu Zirkelverweisen, die, wenn sie nicht aktiviert sind, Speicherplatz verbrauchen. In dem speziellen Fall, den ich mit Schließungen meine, haben Sie einen JavaScript-Verweis auf ein Dom-Objekt und ein Objekt auf ein DOM-Objekt hinzugefügt, das auf das JavaScript-Objekt zurückgeht. Grundsätzlich könnte es niemals gesammelt werden und würde schließlich dazu führen, dass das Betriebssystem in Test-Apps instabil wird, die Schleifen bilden, um Abstürze zu verursachen. In der Praxis sind diese Lecks normalerweise klein, aber um Ihren Code sauber zu halten, sollten Sie den JavaScript-Verweis auf das DOM-Objekt löschen.
Normalerweise ist es eine gute Idee, das Schlüsselwort delete zu verwenden, um große Objekte wie JSON-Daten, die Sie zurückerhalten haben, sofort zu de-referenzieren und alles zu tun, was Sie damit tun müssen, insbesondere in der mobilen Webentwicklung. Dies bewirkt, dass der nächste Durchlauf des GC dieses Objekt entfernt und seinen Speicher freigibt.
quelle
mark-and-sweep
Algorithmen sorgen dafür .Garbage Collection (GC) ist eine Form der automatischen Speicherverwaltung, bei der nicht mehr benötigte Objekte entfernt werden.
Jeder Prozess, der sich mit dem Speicher befasst, führt die folgenden Schritte aus:
1 - Weisen Sie Ihren benötigten Speicherplatz zu
2 - etwas verarbeiten
3 - Geben Sie diesen Speicherplatz frei
Es gibt zwei Hauptalgorithmen, mit denen erkannt wird, welche Objekte nicht mehr benötigt werden.
Garbage Collection mit Referenzzählung : Dieser Algorithmus reduziert die Definition von "ein Objekt wird nicht mehr benötigt" auf "ein Objekt hat kein anderes Objekt, das darauf verweist". Das Objekt wird entfernt, wenn kein Referenzpunkt darauf vorhanden ist
Mark-and-Sweep-Algorithmus : Verbinden Sie jedes Objekt mit der Root-Quelle. Jedes Objekt stellt keine Verbindung zu root oder einem anderen Objekt her. Dieses Objekt wird entfernt.
Derzeit verwenden die meisten modernen Browser den zweiten Algorithmus.
quelle
Alle JavaScript-Engines haben ihre eigenen Garbage Collectors und können sich unterscheiden. Meistens muss man sich nicht mit ihnen befassen, weil sie einfach das tun, was sie tun sollen.
Das Schreiben von besserem Code hängt hauptsächlich davon ab, wie gut Sie die Programmierprinzipien, die Sprache und die jeweilige Implementierung kennen.
quelle
Überprüfen Sie dies
In Javascript interessiert Sie die Speicherzuweisung und Freigabe nicht. Das ganze Problem wird vom Javascript-Interpreter verlangt. Lecks sind in Javascript immer noch möglich, aber sie sind Fehler des Interpreters. Wenn Sie sich für dieses Thema interessieren, können Sie mehr unter www.memorymanagement.org lesen
quelle
Unter Windows können Sie Drip.exe verwenden , um Speicherlecks zu finden oder um zu überprüfen, ob Ihre kostenlose Mem-Routine funktioniert.
Es ist ganz einfach, geben Sie einfach eine Website-URL ein und Sie sehen den Speicherverbrauch des integrierten IE-Renderers. Klicken Sie dann auf Aktualisieren. Wenn sich der Speicher vergrößert, haben Sie irgendwo auf der Webseite einen Speicherverlust festgestellt. Dies ist jedoch auch sehr nützlich, um festzustellen, ob Routinen zum Freigeben von Speicher für den Internet Explorer funktionieren.
quelle
Referenztypen speichern das Objekt nicht direkt in der Variablen, der es zugewiesen ist, sodass die Objektvariable in diesem Beispiel die Objektinstanz nicht enthält. Stattdessen enthält es einen Zeiger (oder eine Referenz) auf die Stelle im Speicher, an der das Objekt vorhanden ist
Wenn Sie eine Variable einer anderen zuweisen, erhält jede Variable eine Kopie des Zeigers, und beide verweisen immer noch auf dasselbe Objekt im Speicher.
aus den Prinzipien des objektorientierten JavaScript - NICHOLAS C. ZAKAS
quelle