Dësen Artikel ass d'Fortsetzung vum Artikel "déi 4 Aarte vu Memory Leaks"

Dat onintuitivt Verhalen vun de Gerempels Sammler
Obwuel Garbage Collectors ganz praktesch sinn, si kommen mat hiren Deel vun Kompromëss. Ee vun dëse Kompromëss ass hiren Net-Determinismus. An anere Wierder, Dreck Sammler sinn onberechenbaren. Et ass allgemeng net méiglech mat Sécherheet festzestellen, wéini eng Müllsammlung duerchgefouert gëtt. Dëst implizéiert datt an e puer Fäll de Programm méi Erënnerung benotzt wéi néideg. An anere Fäll kann ee kuerz Ënnerbriechungen an sensiblen Uwendungen bemierken. Obwuel Net-deterministesch heescht, datt een ni sécher gin kann wann d'Kollektioun duerchgefouert ginn, deelen meescht GC Implementatioune engem gemeinsame Muster vun enger Leeschtung der Kollektioun während Allocatioun. Wann keng Allokatioun gemaach gëtt, bleiwen déi meescht GS Idle.
Bedenkt de folgende Szenario:
- Eng konsequent Set vun Allocatioune gëtt gemaach
- Déi meescht (oder all) vun dësen Elementer sinn als onzougänglech markéiert (stellt Iech vir, eng Referenz ze nulléieren déi op e Cache weist deen net méi gebraucht gëtt)
- Keng Erlaabnes méi ginn gemaach
An dësem Szenario wäert déi meescht GCs net méi sammelen. Dat ass, och wann et onzougänglech Saache fir Sammlung verfügbar sinn, gi se net vum Sammler behaapt. Dëst sinn net Leckage per se, awer d'Resultat ass méi héich wéi normal Erënnerungsverbrauch.
Google bitt e super Beispill vun dësem Verhalen an hiren JavaScript Memory Profiling Dokumenter, Beispill #2.
Aféierung vum Chrome Memory Profiling Tools
Chrome bitt e gudde Set vun Tools fir d'Erënnerungsverbrauch vum JavaScript Code ze diagnostizéieren. Et ginn haaptsächlech zwou Meenungen am Zesummenhang mat Erënnerung: d'Timeline Vue an d'Profil Vue.
Timeline Vue
D'Timeline Vue ass wesentlech fir ongewéinlech Erënnerungsmuster an eisem Code z'entdecken. Wa mir no engem grousse Leck sichen, sollten déi periodesch Spréng, déi net sou vill reduzéieren wéi se no der Sammlung gewuess sinn, Iech alarméieren. An dëser Erfaassung gesi mir wéi de stännege Wuesstum vun engem leaky Objet ausgesäit. Och no der leschter grousser Sammlung ass de Gesamtbetrag u benotzt Erënnerung méi um Enn wéi am Ufank. D'Zuel vun Noden och. Sou vill Hiweiser vun DOM Fuite iergendwou am Code.
Profil Vue
Et ass dës Vue déi Dir vill Zäit verbréngt ze kucken. D'Profiler Vue erlaabt Iech e Snapshot ze kréien an Snapshots vun der Erënnerungsverbrauch vun Ärem JavaScript Code ze vergläichen.
Dëst erlaabt Iech Allocatioune mat der Zäit ze späicheren. An all Resultatvisioun ginn et verschidden Aarte vu Lëschten, awer déi relevantst fir eis Aufgab sinn d'Resumélëscht an d'Vergläichslëscht.
D'Zesummefaassung gëtt eis en Iwwerbléck iwwer déi verschidden Aarte vun zougewisenen Objeten an hir aggregéiert Gréisst: flächeg Gréisst (d'Zomm vun all Objete vun engem spezifeschen Typ) an erhale Gréisst (déi flächeg Gréisst plus d'Gréisst vun aneren Objeten, déi wéinst dësem Objet zréckbehale ginn. ). Dëst gëtt och eng Notioun vun der Distanz vun dësem Objet vu senger Wuerzel GC (d'Distanz).
D'Vergläichslëscht gëtt eis déiselwecht Informatioun awer erlaabt eis déi verschidde Schnappschëss ze vergläichen. Dëst ass besonnesch nëtzlech fir Leckage ze fannen.
Beispill: Leckage fannen mat Chrome
Et ginn haaptsächlech zwou Aarte vu Leckage: Leckage déi periodesch Erhéijunge vun der Erënnerungsverbrauch verursaachen, a Leckage déi eemol geschéien an net weider Erhéijunge vun der Erënnerungsverbrauch verursaachen. Aus offensichtleche Grënn ass et méi einfach Leckage ze fannen wa se periodesch sinn. Si sinn och am meeschte problematesch, wann d'Erënnerung mat der Zäit eropgeet, Lecke vun dësem Typ kënnen de Browser verlangsamen oder d'Skript ophalen. Net-periodesch Fuite kënnen einfach ze fannen sinn wa se grouss genuch sinn fir ënner anerem Allokatiounen ze bemierken. Dëst ass normalerweis net de Fall, sou datt se onnotéiert ginn. An engem Sënn, Leckage déi just eemol geschéien kéinten als Optimisatiounsprobleemer kategoriséiert ginn. Dat gesot, periodesch Fuite si Bugs a solle fixéiert ginn.
Fir ze illustréieren, huelen mir e Beispill am Chrome doc. De Code gëtt hei ënnen kopéiert:
var x = [];
function createSomeNodes() {
var div,
i = 100,
frag = document.createDocumentFragment();
for (;i > 0; i--) {
div = document.createElement("div");
div.appendChild(document.createTextNode(i + " - "+ new Date().toTimeString()));
frag.appendChild(div);
}
document.getElementById("nodes").appendChild(frag);
}
function grow() {
x.push(new Array(1000000).join('x'));
createSomeNodes();
setTimeout(grow,1000);
}
Wann wuessen genannt gëtt, fänkt et un andeems Dir DIV Noden erstellt an se un den DOM befestegt. Et wäert och e grousst Array verdeelen an dozou bäidroen eng Array, déi vun enger globaler Variabel referenzéiert gëtt. Dëst wäert eng stänneg Erhéijung vun der Erënnerung verursaachen, déi mat den uewe genannten Tools ka fonnt ginn.
Mir beobachten allgemeng en oszilléierend Erënnerungsverbrauchsmuster a Garbage Collection-baséiert Sproochen. Dëst ass wat erwaart gëtt wann de Code op enger Loop leeft déi d'Allokatioune produzéiert, wat normalerweis de Fall ass. Mir sichen no periodesche Erënnerungsboost, déi no der Sammlung net op virdrun Niveauen zréckfalen.
Als éischt, kuckt ob d'Erënnerung periodesch eropgeet.
D'View Timeline ass super fir dat. Öffnen d'Beispill am Chrome, öffnen d'Dev Tools, gitt op d'Timeline, wielt Erënnerung a klickt op de Rekord Knäppchen. Da gitt op d'Säit a klickt op De Knäppchen fir d'Erënnerungsleck unzefänken. Waart e bëssen dann stoppt opzehuelen a kuckt d'Resultat:
Erënnerung Leck an Timeline Vue
Dëst Beispill wäert weiderhin all Sekonn Erënnerung lekken. Nodeems Dir d'Opname gestoppt hutt, füügt e Breakpoint an der Wuessfunktioun un fir ze verhënneren datt de Skript Chrome forcéiert d'Säit zouzemaachen. Et ginn 2 grouss Hiweiser an dësem Bild déi weisen datt mir e Leck Erënnerung hunn. D'Grafike vun Noden (gréng Linn) an JS Heap (blo Linn). D'Knuet ginn stänneg erop an kommen ni erof. Dëst ass e grousse roude Fändel.
De JS Heap weist och eng stänneg Erhéijung vun der Erënnerungsverbrauch. Et ass méi schwéier ze gesinn wéinst den Effekter vum Garbage Collector. Dir kënnt e Muster vum initialen Erënnerungswuesstem beobachten, gefollegt vun enger grousser Reduktioun, gefollegt vum Wuesstum, dann e Spike, gefollegt vun enger anerer Reduktioun. De Schlëssel an dësem Fall ass datt no all Reduktioun vun der Erënnerungsverbrauch d'Koupgréisst méi grouss bleift wéi déi virdru Kéier. Dat heescht, datt obwuel de Gerempels Sammelstécker erfollegräich vill Erënnerung reclaims, e puer ass regelméisseg verluer.
Mir sinn elo sécher datt et e Leck ass. Loosst eis et fannen.

Maacht zwee Schnappschëss
Fir de Leck ze fannen, gi mir elo op d'Profil Sektioun vu Chrome Dev Tools. fir d'Erënnerungsverbrauch op e verwaltbaren Niveau ze halen, lued d'Säit virun dësem Schrëtt nei. Mir wäerten d'Funktioun Take Heap Snapshot benotzen.
Luet d'Säit nei an huelt e Heap Snapshot direkt nodeems se fäerdeg ass. Mir wäerten dëse Snapshot als Referenz benotzen. Elo klickt nach eng Kéier op de Knäppchen, waart e puer Sekonnen, an huelt en neie Schnappschëss. Nodeems Dir de Snapshot gemaach hutt, ass et eng gutt Iddi e Breakpoint am Skript ze setzen fir ze vermeiden datt de Leck méi Erënnerung verbraucht.
Heap Snapshots
Et ginn zwou Weeër fir d'Allokatiounen tëscht zwee Schnappschëss ze kucken. Entweder Dir klickt op Resumé a gitt dann no riets a wielt Objekter déi tëscht Snapshot 1 a Snapshot 2 zougewisen sinn, oder Dir klickt op Comparison amplaz Resumé. A béide Fäll wäerte mir eng Lëscht vun Objeten gesinn, déi tëscht den zwee Schnappschëss verdeelt goufen.
An dësem Fall ass et ganz einfach d'Lecke ze fannen: si si grouss. Kuckt d'Gréisst Delta vum (String) Konstruktor. 8MBs fir 58 nei Elementer. Dëst gesäit verdächteg aus: nei Objete ginn zougewisen awer net befreit an 8MB ginn verbraucht.
Wa mir d'Lëscht vun den Allokatioune fir den (String) Konstruktor opmaachen, wäerte mir feststellen datt et e puer grouss Allokatiounen tëscht de ville klengen sinn. Déi grouss gräifen direkt eis Opmierksamkeet. Wa mir ee vun hinnen auswielen, fanne mir eppes interessant domat an der Retainers Sektioun just hei ënnen.
Retainers fir de gewielten Objet
Mir gesinn datt déi gewielte Allokatioun Deel vun enger Array ass. Am Tour gëtt d'Array vun der Variabel x am globale Fënsterobjekt referenzéiert. Dëst gëtt eis de ganze Wee vun eisem groussen Objet op seng net sammelbar Root (Fënster). Mir hunn eise potenzielle Leck fonnt a wou et referenzéiert ass.
Sou wäit, sou gutt. Awer eist Beispill war einfach: grouss Allokatiounen wéi am Beispill sinn net d'Norm. Glécklecherweis leeft eist Beispill och DOM Noden, déi méi kleng sinn. Et ass einfach dës Noden ze fannen mat dem Snapshot hei uewen, awer op gréissere Site ginn d'Saache méi komplizéiert. Rezent Versioune vu Chrome bidden en zousätzlecht Tool dat gutt fir eis Aarbecht passt: d'Funktioun Record Heap Allocations.
Späichert Heap Allocatioun fir Leckage ze fannen
Deaktivéiert den Breakpoint deen Dir virdru festgestallt hutt, loosst de Skript lafen, a gitt zréck an d'Profil Sektioun vu Chrome Dev Tools. Elo tippen op Record Heap Allocations. Wéi de Tool leeft, gesitt Dir blo Spikes an der ieweschter Grafik. et duerstellt Subventiounen. All Sekonn gëtt eng grouss Allokatioun vum Code produzéiert. Loosst et fir e puer Sekonnen lafen a stoppt et (vergiesst net e Breakpoint derbäi ze ginn fir ze verhënneren datt Chrome méi Erënnerung verbraucht).
Heap gespäichert Erlaabnes.
An dësem Bild kënnt Dir d'Killer Feature vun dësem Tool gesinn: wielt en Deel vun der Timeline fir ze kucken wéi eng Allocatioune während där Zäit gemaach goufen. Mir definéieren d'Auswiel am nootsten un de grousse Peaks. Nëmmen dräi Konstrukteuren erschéngen an der Lëscht. Ee vun hinnen ass deen am Zesummenhang mat eisem grousse Leck ((String)), deen nächsten ass mat DOM Allokatiounen am Zesummenhang, an dee leschte ass den Textkonstruktor (de Konstruktor fir DOM Blatknäppchen mat Text).
Wielt ee vun den HTMLDivElement Konstruktoren aus der Lëscht a klickt dann op wielt Allocation Stack.
Ausgewielt Element an Heap Allocatioun Resultater
BAM! Mir wëssen elo wou dëst Element zougewisen gouf (grow -> createSomeNodes). Wa mir suergfälteg op all Peak an der Grafik kucken, wäerte mir feststellen datt den HTMLDivElement Konstruktor vill genannt gëtt. Wa mir zréck op d'Snapshot Verglach Vue, wäerte mir bemierken datt dëse Konstruktor vill Allocatioun opdeckt awer keng Läschung. An anere Wierder, et verdeelt regelméisseg Erënnerung ouni datt de GC all zréckgeet. Dëst sinn all Symptomer vun engem Leck an zousätzlech wësse mir genau wou dës Objete zougedeelt sinn (d'CreateSomeNodes Funktioun). Elo ass et Zäit fir zréck op de Code ze kommen, et ze studéieren an d'Leckage ze fixéieren.
- Eng aner nëtzlech Feature:
An der Heap Allocations Resultat Vue kënne mir Allocation View auswielen anstatt Resumé.
Dës Vue gëtt eis eng Lëscht vu Funktiounen an der Zesummenhang Erënnerung Allocatioune. Mir kënnen direkt gesinn wuessen a schafenSomeNodes erausstinn. Wa mir wielen wuessen, kucke mir d'Konstruktoren vun den assoziéierten Objeten, déi vun et genannt ginn. Mir bemierken (String), HTMLDivElement an Text déi mir scho wësse sinn d'Konstrukteuren vun de leckende Objeten.
D'Kombinatioun vun dësen Tools kann e laange Wee goen fir Leckage ze fannen. Spillt domat, laaft verschidde Profiler op Äre Produktiounsplazen (ideal Code, net miniméiert oder obfuscéiert). Kuckt ob Dir Leckage oder Elementer fannt déi méi laang gehale ginn wéi se sollten (Hipp: se si méi schwéier ze fannen).
Fir dës Funktiounen ze benotzen, gitt op Dev Tools -> Astellungen an aktivéiert "Record Heap Allocation Stack Traces". Et ass néideg dëst virum Opnam ze maachen.
- Fir weider:
Memory Management - Mozilla Developer Network
JScript Memory Leaks - Douglas Crockford (al, a Relatioun zu Internet Explorer 6 Leck)
JavaScript Memory Profiling - Chrome Entwéckler Docs
Memory Diagnos - Google Entwéckler
Eng interessant Aart vu JavaScript Memory Leak - Meteor Blog
Grokking V8 Zoumaache
Conclusioun
Erënnerungslecks kënnen a geschéien a Gerempels gesammelt Sprooche wéi JavaScript. Si kënnen eng Zäit laang verstoppt liewen a schlussendlech zerstéieren. Aus dësem Grond sinn Memory Profiling Tools wesentlech fir Erënnerungslecks ze fannen. Profiléiere soll en Deel vun Entwécklungszyklen sinn, besonnesch fir mëttel bis grouss Uwendungen.Start elo un fir Äre Benotzer déi beschtméiglech Erfahrung ze ginn.
Gutt Debug!
Fannt den 1. Artikel zu dësem Thema ICI !
[Trennungstyp ="" Gréisst ="" Ikon = "Stär"] [actionbox Faarf = "Standard" Titel ="" Beschreiwung ="JS-REPUBLIC ass eng Servicefirma spezialiséiert op JavaScript Entwécklung. Mir sinn eng guttgeheescht Training Zentrum. Fannt all eis technesch Formatiounen op eisem Partner Site gewidmet fir Training” btn_label=”Eis Training” btn_link=”http://training.ux-republic.com” btn_color=”primary” btn_size=”big” btn_icon=”star” btn_external = "1"]
