Hat Javascript Speicherlecks ? Wenn ja, wie kann man es vermeiden? Angesichts der Tatsache, dass mir in letzter Zeit mehrere Leute ähnliche Fragen gestellt haben, scheint es, dass niemand diesen Teil des Inhalts systematisch studiert hat. Daher habe ich vor, einige Informationen, die ich vor einigen Jahren zusammengestellt habe, mit Ihnen zu teilen.
Zunächst kann mit Sicherheit gesagt werden, dass einige Arten, JavaScript zu schreiben, zumindest unter IE6 zu Speicherlecks führen werden. Wenn sich IE6 heute weigert, in den Ruhestand zu gehen, müssen wir daher immer noch das entsprechende Wissen verstehen (obwohl in den meisten Fällen der durch js verursachte Speicherverlust nicht der Hauptgrund für die Verlangsamung des Computers ist). Die relevante Forschung konzentriert sich hauptsächlich auf die Jahre 2005-07. Dieser Artikel enthält keine neuen Ideen. Wenn Sie Freunde haben, die ihn damals studiert haben, können Sie ihn einfach ignorieren.
Wenn Sie als Front-End-Entwickler diese Probleme verstehen möchten, müssen Sie wissen, was sie sind und warum, bevor wir js-Speicherlecks einführen, beginnen wir mit der Frage, warum es Speicherlecks gibt.
Wenn wir über Speicherlecks sprechen, müssen wir über die Art und Weise sprechen, wie Speicher zugewiesen wird. Es gibt drei Möglichkeiten, Speicher zuzuweisen:
1. Statische Zuordnung: Die Zuordnungsform von statischen Variablen und globalen Variablen. Wenn wir uns einen Raum als Programm vorstellen, können wir uns statisch zugewiesenen Speicher als dauerhafte Möbel im Raum vorstellen. Normalerweise müssen sie nicht freigegeben und recycelt werden, da Schränke nicht jeden Tag als Müll aus dem Fenster geworfen werden.
2. Automatische Zuweisung: Eine Methode zum Zuweisen von Speicher für lokale Variablen auf dem Stapel. Der Speicher im Stapel kann mit der Pop-Operation automatisch freigegeben werden, wenn der Codeblock beendet wird.
Dies ist vergleichbar mit Menschen, die in einen Raum kommen, um Dinge zu erledigen. Sobald die Dinge erledigt sind, gehen sie von selbst, und der Raum, den sie einnehmen, wird automatisch freigegeben, wenn diese Menschen gehen.
3. Dynamische Zuweisung: Eine Methode zur dynamischen Zuweisung von Speicherplatz im Heap zum Speichern von Daten. Das heißt, wir müssen den Speicher, der für die Verwendung von malloc oder new verwendet wird, während das Programm ausgeführt wird, selbst mit free oder delete freigeben. Die Lebensdauer des dynamischen Speichers wird vom Programmierer bestimmt. Wenn Sie vergessen, es freizugeben, führt dies unweigerlich zu einem Speicherverlust. In diesem Fall sind die Speicherblöcke im Haufen wie die Servietten, die wir jeden Tag benutzen. Nachdem wir sie benutzt haben, müssen wir sie in den Mülleimer werfen, sonst wird das Haus ein Chaos. Daher träumen faule Menschen davon, einen Haushaltsroboter zum Putzen dabei zu haben. Wenn Sie in der Softwareentwicklung zu faul sind, Speicher freizugeben, benötigen Sie auch einen ähnlichen Roboter – der eigentlich ein Garbage Collector ist, der durch einen bestimmten Algorithmus implementiert wird. Es sind genau einige Fehler im Garbage-Collection-Mechanismus selbst, die zu JavaScript-Speicherlecks führen.
Vor einigen Jahren las ich einen Artikel mit dem Titel „Eine interessante Geschichte des Müllrecyclings“, in dem der Müllsammelmechanismus ausführlich erläutert wurde.
Genau wie die Aufladung, eine Technologie, die vielen Luxusautos als Verkaufsargument dient und die in den 1910er Jahren tatsächlich von Mercedes-Benz eingesetzt wurde, gibt es die Müllrecyclingtechnologie schon seit langer Zeit. Die um 1960 am MIT geborene Lisp-Sprache war die erste Sprache, die sich stark auf die dynamische Speicherzuweisungstechnologie stützte. Fast alle Daten in Lisp erscheinen in Form von „Tabellen“, und der von „Tabellen“ belegte Platz befindet sich im Heap. dynamisch zugewiesen. Die inhärente dynamische Speicherverwaltungsfunktion der Lisp-Sprache erfordert, dass die Designer der Lisp-Sprache das Problem der automatischen Freigabe jedes Speicherblocks im Heap lösen (andernfalls werden Lisp-Programmierer unweigerlich mit unzähligen Frei- oder Löschanweisungen im Programm überfordert). . Dies führte direkt zur Geburt und Entwicklung der Müllabfuhrtechnologie.
Zu dieser Zeit erschienen auch die drei grundlegendsten Garbage-Collection-Algorithmen gemeinsam. Schauen wir sie uns einzeln an:
Referenzzählalgorithmus: Dies ist möglicherweise die erste Methode, die mir in den Sinn kommt. Im übertragenen Sinne kann die Referenzzählung auf diese Weise verstanden werden. Es gibt viele Whitepapers im Haus, und diese Papiere sind wie Erinnerungen. Die Nutzung des Gedächtnisses ist wie das Schreiben auf diese Zettel. Der Speicher kann nach Belieben verwendet werden, es gibt jedoch eine Bedingung: Jeder, der ein Blatt Papier verwendet, muss eine Zählung von 1 auf die Ecke des Papiers schreiben. Wenn zwei Personen gleichzeitig ein Blatt Papier verwenden, wird die Zählung angezeigt 2 und so weiter. Wenn eine Person mit der Verwendung eines Blattes Papier fertig ist, muss die Zählung an der Ecke um 1 verringert werden. Sobald die Zählung 0 wird, sind die Garbage-Collection-Bedingungen erfüllt und der daneben wartende Roboter wirft das Papier sofort in die Ecke Müllkiste. Der auf Referenzzählern basierende Garbage Collector läuft schneller, unterbricht die Programmausführung nicht für längere Zeit und eignet sich für Programme, die in Echtzeit ausgeführt werden müssen. Der Referenzzähler erhöht jedoch den Overhead der Programmausführung; gleichzeitig gibt es ein weiteres großes Problem. Dieser Algorithmus weist einen Fehler auf, nämlich dass der Speicher verloren geht, sobald ein Zirkelverweis generiert wird. Zum Beispiel haben wir zwei neue Objekte a und b. Zu diesem Zeitpunkt sind die Anzahlen von a und b beide 1. Dann zeigen wir ein Attribut von a auf b und ein Attribut von b auf a In der Referenzbeziehung werden die Anzahlen von a und b beide zu 2. Wenn das Programm endet und den Gültigkeitsbereich verlässt, verringert das Programm automatisch die Anzahl von a um 1. Da die Anzahl von a am Ende immer noch 1 ist, wird dies bei a nicht der Fall sein Ebenso ist die endgültige Anzahl von b ebenfalls 1, b wird nicht freigegeben und der Speicher ist einfach durchgesickert!