Das schnelle Aktualisieren des Images mit dem Daten-URI führt zu Caching und Speicherlecks
Ich habe eine Webseite, mit schnell-streams JSON vom server und zeigt die bits, über 10-mal/Sekunde. Ein Teil ist base64-kodierte PNG-Bild. Ich habe ein paar verschiedene Möglichkeiten, um das Bild anzuzeigen, aber alle von Ihnen führen unbounded memory usage. Er steigt von 50 MB auf 2 GB innerhalb von Minuten. Passiert mit Chrome, Safari und Firefox. Habe nicht versucht, DH.
Entdeckte ich die Speicherauslastung zunächst durch einen Blick in die Aktivitätsanzeige.app -- Google Chrome Renderer-Prozess kontinuierlich frisst Speicher. Dann sah ich auf Chrome Ressource-Inspektor (View
> Developer
> Developer Tools
Resources
), und ich sah, dass es Zwischenspeichern der Bilder. Jedes mal, wenn ich änderte die img src
oder erstellt ein neues Image (), und legen Sie seine src
Chrome-Cache. Ich kann mir nur vorstellen, dass die anderen Browser tun das gleiche.
Gibt es eine Möglichkeit, dies zu kontrollieren Zwischenspeichern? Kann ich Sie ausschalten, oder etwas tun, hinterhältige, damit es nie passiert?
Edit: ich möchte in der Lage sein, um die Technik zu nutzen, die in Safari/Safari (Mobil). Auch, ich bin offen für andere Methoden, die schnell eine erfrischende Bild, wenn jemand eine Idee hat.
Hier sind die Methoden, die ich ausprobiert habe. Jeder befindet sich in einer Funktion, die aufgerufen wird, die auf AJAX-Abschluss.
Methode 1 - Direkt auf das src
- Attribut auf eine img
tag
Schnell. Zeigt sich sehr schön. Lecks wie verrückt.
$('#placeholder_img').attr('src', 'data:image/png;base64,' + imgString);
Methode 2 - Ersetzen img
mit einem canvas
und verwenden Sie drawImage
Zeigt feine, aber immer noch leckt.
var canvas = document.getElementById("placeholder_canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "data:image/png;base64," + imgString;
Methode 3 - in binary Konvertieren und ersetzen canvas
Inhalt
Mache ich etwas falsch hier-die Bilder zeigen klein und sehen aus wie Rauschen. Diese Methode verwendet eine kontrollierte Menge an Speicher (wächst auf 100 MB und Stoppt), aber es ist langsam, vor allem in Safari (~50% CPU-Auslastung gibt es, 17% Chrom). Die Idee kam aus dieser ähnlichen Frage ALSO: Daten URI Leck in Safari (war: Speicherverlust mit HTML5 canvas)
var img = atob(imgString);
var binimg = [];
for(var i = 0; i < img.length; i++) {
binimg.push(img.charCodeAt(i));
}
var bytearray = new Uint8Array(binimg);
//Grab the existing image from canvas
var ctx = document.getElementById("placeholder_canvas").getContext("2d");
var width = ctx.canvas.width,
height = ctx.canvas.height;
var imgdata = ctx.getImageData(0, 0, width, height);
//Overwrite it with new data
for(var i = 8, len = imgdata.data.length; i < len; i++) {
imgdata.data[i-8] = bytearray[i];
}
//Write it back
ctx.putImageData(imgdata, 0, 0);
InformationsquelleAutor der Frage Dave | 2012-03-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Versuchen Sie, Bild.src = "" nach Zeichnung.
Dadurch geholfen werden könnte
InformationsquelleAutor der Antwort Jakke
Ich glaube nicht, dass es irgendwelche Garantien über die Speichernutzung von data-URLs. Wenn Sie herausfinden können, einen Weg, um Sie zu Verhalten in einem browser, garantiert es wenig, wenn nicht nichts zu anderen Browsern oder Versionen.
Wenn Sie Ihre Bild-Daten in ein blob und dann erstellen Sie ein blob-URL können Sie dann freigeben von Daten.
Hier ist ein Beispiel, das sich ein Daten-URI in eine blob-URL, die Sie benötigen, zu ändern /löschen der
webkit-
&WebKit-
Präfixe, die auf anderen Browsern als Chrome und möglicherweise in zukünftigen Versionen von Chrome.Freigeben ist so einfach wie :
Und Sie können Ihren blob-URL als Ihre
img
'ssrc
.Leider blob-URLs, die anscheinend nicht unterstützt in IE vor v10.
API Referenz:
http://www.w3.org/TR/FileAPI/#dfn-createObjectURL
http://www.w3.org/TR/FileAPI/#dfn-revokeObjectURL
Kompatibilität Referenz:
http://caniuse.com/#search=blob%20url
InformationsquelleAutor der Antwort ellisbben
Ich hatte ein sehr ähnliches Problem.
Einstellung img.SRK an dataUrl Speicherverluste
Lange Geschichte kurz, ich habe einfach gearbeitet, um das Image-element. Ich benutze einen javascript-decoder zum decodieren und anzeigen der Bilddaten auf eine Leinwand. Es sei denn, der Benutzer versucht, das Bild herunterladen, Sie werden nie wissen, den Unterschied. Der andere Nachteil ist, dass Sie gehen nur auf modernen Browsern. Die bis Seite ist, dass diese Methode nicht Leck wie ein Sieb 🙂
InformationsquelleAutor der Antwort Paul Milham
Flicken ellisbben Antwort, da BlobBuilder ist veraltet und https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView bietet, was scheint, eine schöne schnelle Konvertierung von base64 zu UInt8Array:
in html:
in js:
Ich verstehe immer noch nicht, es wirklich zu aktualisieren das Bild in Safari mobile, aber chrome kann erhalten dataurls rapid-fire über websocket und halten mit Ihnen weit besser, als wenn man manuell Durchlaufen der Schnur. Und wenn Sie wissen, Sie haben immer die gleiche Art von dataurl, man könnte ja tauschen Sie die regex für eine substring (wahrscheinlich schneller...?)
Laufen einige quick-memory-profile, es sieht aus wie Chrom ist auch in der Lage zu halten mit deallocations (wenn Sie sich erinnern, Sie zu tun...):
InformationsquelleAutor der Antwort user3669490
Ich habe verwendet verschiedene Methoden, um dieses problem zu lösen, keiner von Ihnen arbeitet. Es scheint, dass memory leaks bei img.src = base64string und diese Speicher nie freigegeben. Hier ist meine Lösung.
Beachten Sie, dass Sie sollten base64 konvertieren, um jpeg-Puffer.
Mein Elektron app aktualisieren img jeden 50ms, und der Speicher nicht Auslaufen.
Vergessen Sie über die Auslastung des Laufwerks. Chrome memory-management-piss mich Weg.
InformationsquelleAutor der Antwort Keven Sun
Ich weiß, es ist Jahre her, seit dieses Thema gepostet wurde, aber das problem besteht immer noch in neueren Versionen des Safari-Browsers. So habe ich eine endgültige Lösung, die in allen Browsern funktioniert, und ich glaube, das könnte Arbeitsplätze gesichert oder Leben!.
Kopieren Sie den folgenden code irgendwo in Ihre html-Seite:
Dann, wenn Sie erhalten einen neuen Rahmen/Bild
base64Image
im base64-format (z.B.data:image/jpeg;base64, LzlqLzRBQ...
) und Sie aktualisieren möchten, ein html -<img />
ObjektimageElement
dann verwenden Sie diesen code:Wiederholen Sie diesen letzten code so viel wie nötig und keine memory leaks angezeigt. Diese Lösung erfordert nicht die Verwendung des canvas-element, aber können Sie sich den code, damit es funktioniert.
InformationsquelleAutor der Antwort Panchosoft
Es sei denn, Safari oder Mobile Safari nicht Leck data-urls, server-Seite könnte der einzige Weg, dies zu tun, auf allen Browsern.
Wohl einfachste wäre eine URL für dein Bild-stream
GET
ting gibt es ein 302 oder 303 Antwort umleiten zu einer single-use-URL, geben Sie das gewünschte Bild. Sie werden wahrscheinlich haben, zu zerstören und neu erstellen, die image-tags zu zwingen, ein reload der URL.Werden Sie auch auf die Gnade des Browsers in Bezug auf seine
img
caching-Verhalten. Und die Gnade, mein Verständnis (oder Unverständnis) der HTTP-spec. Immer noch, es sei denn, server-side-Betrieb passen nicht Sie Ihre Anforderungen, versuchen, diese zuerst. Es erhöht die Komplexität der server, aber dieser Ansatz nutzt die browser viel mehr natürlich.Aber was ist mit dem browser un-natürlich? Je nachdem, wie Browser implementieren
iframe
s und behandeln Ihre zugehörigen Inhalte, die Sie könnte in der Lage sein, Daten mit urls arbeiten, ohne undicht Speicher. Dies ist ein bisschen Frankenstein Scheiße und das ist genau die Art von Unsinn, der niemand zu tun haben sollte. Vorteil: es könnte funktionieren. Nachteil: es gibt eine bazillion Möglichkeiten, es zu versuchen und uneben, undokumentierte Verhalten ist genau das, was ich erwarten würde.Einer Idee: einbetten eines
iframe
mit einer Seite, diese Seite und die Seite, es ist eingebettet in die Nutzung cross-document messaging (beachten Sie die GRÜNEN in der compatibility matrix!); embeddee wird die PNG-string und übergibt es zusammen, um das eingebettete Seite, das macht dann eine entsprechendeimg
tag. Wenn die embeddee muss eine neue Mitteilung angezeigt wird, zerstört Sie die eingebetteteiframe
(hoffentlich Freigabe von Speicher der data-url), dann eine neue erstellt und übergibt es dem neuen PNG-string.Wenn Sie wollen geringfügig mehr kluge, könnte man tatsächlich Betten Sie die Quelle für das eingebettete Bild in der embeddee Seite als data-url; aber dies könnte Auslaufen, die Daten-url, die ich denke, wäre poetic justice für den Versuch, eine solche reacharound.
"Etwas, das funktioniert in Safari besser wäre." Browser-Technologie hält auf Bewegung ungleichmäßig. Wenn Sie nicht hand die Funktionalität, um Sie auf einer Platte, du musst uns verschlagen.
InformationsquelleAutor der Antwort ellisbben
Arbeitete für mich auf einem memory leak Dank dude.
InformationsquelleAutor der Antwort Jay