JavaScript-Speicherleck mit HTML5 getImageData

8

Ich habe daran gearbeitet, einige visuelle Effekte für ein JavaScript-Spiel zu erzeugen, das ich erschaffe, und ich habe bemerkt, dass ein Code, mit dem ich die Farbe meiner Sprites moduliere, den Speicherverbrauch meines Browsers erhöht und auf, scheinbar ohne Grenzen.

Sie können den Code und das Speicherleck hier sehen: Ссылка

Dieser Speicherverlust tritt nur in meiner Funktion updimeimage () auf, wenn ich getImageData aus meinem Canvas-Kontext jedes Bild (über setInterval) aufrufe, um ein neues ImageData-Objekt zum Umfärben zu machen. Ich hätte gedacht, dass der Garbage Collector von JavaScript den alten zerstören würde, aber wenn nicht, habe ich keine Ahnung, wie ich es manuell zerstören könnte. Jede Hilfe, die herausfindet, warum es das tut oder wie man es repariert, würde geschätzt werden.

Meine Frage ist der folgenden sehr ähnlich: Was ist mit dieser Verwendung von getImageData, Javascript, HTML5 Canvas undichtem Speicher jedoch , Ich brauche meinen Code, um jedes Bild in der Funktion ausgeführt von SetInterval, seine Lösung der Verschiebung es außerhalb der SetInterval-Funktion ist keine Option für mich, und ich kann keinen Kommentar hinterlassen Fragen, ob er eine andere Methode der Lösung gefunden es.

Hinweis für Leute, die es ausprobieren: Da dieses Beispiel getImageData verwendet, kann es nicht lokal getestet werden, nur indem es in eine .html Datei geworfen wird, ein Webserver ist erforderlich. Außerdem verwendet es offensichtlich HTML5-Elemente, so dass einige Browser nicht damit arbeiten können.

Bearbeiten: * Gelöst * Danke, die Lösung unten behoben. Ich wusste nicht, dass Sie ein Canvas-Element genauso verwenden können, wie Sie ein Bild in drawImage () verwenden könnten. Ich habe meinen Code neu strukturiert, so dass er jetzt erheblich weniger Speicher benötigt. Ich habe diesen geänderten Code auf die oben verlinkte Seite hochgeladen, falls jemand sie sehen möchte.

    
zookatron 03.10.2011, 16:42
quelle

1 Antwort

12

Sie erhalten von Ihren Aufrufen in getImageData() kein Speicherleck. Die Quelle Ihres Problems ist diese Zeile:

TempImg.src = ImgCanvas.toDataURL("image/png");

Jedes Mal, wenn diese Codezeile ausgeführt wird, "lädt" der Browser ein anderes Bild herunter und speichert es im Speicher. Also, was Sie eigentlich haben, ist ein Cache, der sehr schnell wächst. Sie können dies leicht überprüfen, indem Sie die Website in Chrome öffnen und die Ressourcenregisterkarte der Entwicklerwerkzeuge ( ctrl+shift+i ) überprüfen.

Sie können dies umgehen, indem Sie TempImgCanvas erstellen und Ihre Bilddaten auf dieser Zeichenfläche speichern, anstatt ein Bildobjekt nach jedem Aufruf Ihrer updateimage() Schleife zu aktualisieren.

Ich muss für eine Weile weggehen, aber ich kann ein Beispiel in ein paar Stunden aufarbeiten, wenn ich zurückkomme, wenn Sie möchten.

Bearbeiten: Ich habe die Dinge ein wenig umstrukturiert und das Caching-Problem beseitigt. Sie müssen nur zwei Änderungen vornehmen. Die erste ersetzt Ihre updateimage() Funktion durch diese:

%Vor%

Die Sekunde aktualisiert die letzte Zeile in draw() wie folgt:

drawImg(ImgCanvas, Positions[i].x, Positions[i].y, Positions[i].x+Positions[i].y);

Unter Verwendung dieses aktualisierten Codes beziehen wir uns einfach auf die ursprünglichen (weißen) Basisbilddaten und berechnen neue Werte basierend darauf jedes Mal, wenn wir die Funktion updateimage() durchlaufen. Wenn Sie getImageData() aufrufen, erhalten Sie eine Kopie der Bilddaten auf der Zeichenfläche. Wenn Sie also die Zeichenfläche oder die Daten bearbeiten, bleibt die andere unverändert. Sie haben bereits die ursprünglichen Basis-Bilddaten abgegriffen, daher war es sinnvoll, sie nur zu verwenden, anstatt sie bei jeder Aktualisierung neu zu erfassen.

Sie werden auch bemerken, dass ich Ihre Schleife geändert habe, die die Bildfarbe leicht verändert. Wenn Sie ein Handle für das tatsächliche Datenarray erhalten, auf das Sie zugreifen / ändern möchten, müssen Sie nicht jedes Mal den Array-Speicherort vom übergeordneten Objekt auflösen, wenn Sie die Schleife durchlaufen. Diese Technik führt tatsächlich zu einem ziemlich schönen Leistungsschub. Ihre Leistung war am Anfang in Ordnung, aber es kann nicht schaden, effizienter zu sein, da es ziemlich einfach ist.

    
Xenethyl 03.10.2011, 20:37
quelle