Practic js scapa de scurgeri de memorie, de exemplu.

JS practice: scapă de scurgeri de memorie în IE

Dezvoltarea de dezvoltare web

În trecut, scurgeri de memorie nu au creat probleme pentru dezvoltatorii web. Paginile au fost extrem de simple, iar trecerea de la un la altul a fost singura modalitate normală de a elibera toată memoria disponibilă. Dacă a survenit scurgeri, a fost atât de nesemnificativ încât a rămas neobservată.

Aplicațiile web moderne ar trebui dezvoltate ținând cont de standarde mai înalte. Pagina poate rula ore întregi fără navigare suplimentară a site-ului, în timp ce va solicita dinamic noi informații prin intermediul serviciilor web. Motorul lingvistic este testat pentru rezistență prin schemele complexe de procesare a evenimentelor, jScript-urile orientate pe obiecte și închiderile, producând aplicații tot mai puternice și mai avansate. Cu toate acestea, având în vedere alte caracteristici, cunoașterea modelelor caracteristice ale scurgerilor de memorie devine din ce în ce mai necesară, chiar dacă acestea au fost ascunse anterior în spatele mecanismului de navigare a site-ului.

Marele plus în această situație este că modelele de pierderi de memorie pot fi ușor detectate dacă știți unde să le căutați. Cea mai dificilă dintre ele, pe care ați întâlnit-o, are metode detaliate de eliminare, care, cel mai probabil, în cazul dumneavoastră, va necesita doar o mică cantitate de muncă suplimentară. În timp ce unele pagini pot să scadă din cauza scurgeri mici, cele mai semnificative pot fi eliminate cu ușurință.

Formele de scurgere

În secțiunile următoare, discutăm modele comune de scurgere de memorie și oferim câteva exemple pentru fiecare. Un exemplu remarcabil de scurgere este cazul închiderii în JScript, un alt exemplu este utilizarea unei închideri pentru a intercepta evenimente. Dacă sunteți familiarizat cu evenimentele de interceptare, puteți găsi cu ușurință și remediați multe pierderi de memorie, totuși, alte cazuri asociate cu închiderile pot trece neobservate.

Să trecem acum la următoarele șabloane:

Link-uri ciclice

Figura 1. Șablon de referință ciclic de bază

Dacă doriți să vedeți cum va arăta acest șablon în HTML, puteți provoca o scurgere utilizând variabila globală și obiectul DOM, după cum se arată mai jos.

Pentru a distruge acest șablon, puteți folosi o atribuire explicită unei proprietăți care "curge", nulă. Astfel, când închideți documentul, spuneți motorului script că nu mai există nicio legătură între elementul DOM și variabila globală. Ca rezultat, toate linkurile vor fi șterse, iar elementul DOM însuși va fi eliberat. În acest caz, dvs. ca dezvoltator de web știți mai multe despre relațiile interne între obiecte decât scriptul însuși și împărtășiți-vă informațiile cu el.

O soluție mai complexă a problemei menționate ar putea fi implicarea procesului de înregistrare a link-urilor, astfel încât cererea să poată fi înștiințată în mod corespunzător care pot fi șterse. În acest caz, atunci când închideți documentul, va trebui să treceți prin toate aceste elemente și să eliminați legăturile de la acestea, cu toate acestea, dacă abordarea este incorectă, nu puteți numai să reduceți, ci chiar să creșteți numărul de referințe ciclice fără a scăpa de problema menționată.

Figura 2. Legături ciclice cu închideri

Blocurile sunt create prin apelarea funcției, astfel încât două apeluri diferite vor genera două închideri independente, fiecare conținând linkuri către parametrii apelului lor. Din cauza acestei transparențe externe, este foarte ușor, de fapt, să permiteți scurgerilor să se scurgă. Următorul exemplu prezintă unul dintre cazurile de bază ale scurgerilor din închideri:

Dacă vă gândiți cum să remediați această scurgere, atunci nu este la fel de simplă ca în cazul unei referințe circulare normale. "Închiderea" poate fi privită ca un obiect temporar care există în scopul funcției. După terminarea funcției, pierdeți referința la închiderea însăși, astfel încât întrebarea este cum să sunați la detachEvent final. Una dintre cele mai interesante abordări este discutată în blogul spațiului MSN, datorită lui Scott Isaacs. Utilizează cea de-a doua închidere, care se lipsește de evenimentul onUnload din întreaga fereastră a browserului. Deoarece are obiecte din același domeniu de aplicare, este posibilă eliminarea prelucrării evenimentului, eliberarea închiderii și finalizarea procesului de curățare. Pentru a clarifica în cele din urmă situația, putem adăuga la exemplul nostru de proprietate suplimentar, care va păstra o referință la circuit, atunci link-ul va elibera închiderea și reseta proprietatea în sine, cum ar fi în următorul exemplu de cod.

Scurgeri paginate

Scurgerile care depind de ordinea adăugării elementelor în arborele DOM sunt întotdeauna cauzate de crearea de obiecte intermediare, care nu sunt șterse în mod corespunzător. Acest lucru se întâmplă de asemenea atunci când creați elemente dinamice, care sunt apoi atașate la DOM. Șablonul de bază constă în conectarea temporară a două elemente nou create, care creează domeniul în care este definit elementul copil. Apoi, cu includerea arborelui cu două elemente la sol, ambele moștenesc contextul întregului document, și există o scurgere în instalația temporară (a cărui context, nu ne-am închis). Următoarea diagramă prezintă două metode pentru atașarea elementelor create dinamic într-un copac comun. În primul model, atașăm elementele copilului părinților lor și, în cele din urmă, arborele rezultat în DOM. Această metodă poate provoca scurgeri de memorie atunci când creați temporar obiecte incorecte. În cel de-al doilea caz, atașăm elementele direct la arborele primar, pornind dinamic creând noduri de la ultimul element până la ultimul element copil. Deoarece fiecare nouă aderare se află în sfera de aplicare a unui obiect global, nu creăm niciodată contexte temporare. Această metodă este mult mai bună, deoarece evită scurgeri de memorie potențiale.

Figura 3. Scurgeri legate de ordinea adăugării elementelor DOM

Apoi, vom analiza un exemplu tipic, care este de obicei trecut cu vederea de majoritatea algoritmilor pentru detectarea scurgerilor. Deoarece nu afectează elementele accesibile publicului și obiectele care cauzează scurgeri, ele sunt foarte mici, probabil că niciodată nu veți observa această problemă. Pentru a face ca exemplul nostru să funcționeze, trebuie să furnizăm elementele create dinamic cu un pointer la o funcție liniară (inline). Astfel, pentru fiecare astfel de apel la o scurgere de memorie va avea loc pe stabilirea unui obiect intern temporar (de exemplu, o tratare a evenimentului), de îndată ce vom atașa obiectul creat la copac totală. Deoarece scurgerea este foarte mică, va trebui să executăm sute de cicluri. De fapt, sunt doar câțiva octeți. Dacă executați un exemplu și reveniți la o pagină goală, puteți măsura diferența dintre cantitatea de memorie dintre aceste două cazuri. Atunci când se utilizează primul model DOM pentru a atașa nodul copil la nodul părinte și apoi părintele la arborele partajat, utilizarea memoriei crește ușor. Aceasta este o scurgere de navigare încrucișată, iar memoria nu este eliberată dacă reporniți procesul IE. Dacă testați exemplul utilizând al doilea model DOM pentru aceleași acțiuni, atunci nu va exista nicio modificare a cantității de memorie. Astfel, este posibil să se remedieze scurgeri de acest fel.

Vreau să vă concentrez atenția asupra acestui punct, deoarece demonstrează că nu toate scurgerile de memorie pot fi detectate atât de ușor. Poate că, pentru a face problema explicită, vor fi necesare mii de iterații. Și poate fi în detaliu pur, de exemplu, în ordinea elementelor în DOM-copac inserarea, dar rezultatul este același: pierderea de productivitate. Dacă sunteți cu scopul de a construi pe programul său numai cu privire la metodele pe scara larga si sfaturi practice pentru cei mai importanți dezvoltatori, rețineți că toate ar putea fi greșit, și chiar cel mai bun sfat poate fi în anumite privințe incorecte. În acest caz, soluția noastră este îmbunătățirea metodei curente sau chiar crearea unei soluții noi care rezolvă problema.

Pseudo scurgeri

Foarte des, comportamentul real și anticipat al anumitor API-uri poate duce la ceea ce numiți în mod eronat scurgeri de memorie. Pseudo-scurgerile apar întotdeauna pe pagina însăși în timpul operațiilor dinamice și foarte rar când pot fi văzute în afara paginii pe care apare alocarea de memorie, în raport cu pagina necompletată. S-ar putea să vă gândiți că în fața dvs. o scurgere tipică a paginii și să începeți să căutați cauzele sale radicale, acolo unde există o utilizare excesivă de memorie. Utilizăm un script pentru a rescrie textul ca exemplu de astfel de pseudo-scurgere.

Această problemă se bazează, precum și situația asociată cu adăugarea de elemente în arborele DOM, crearea obiectelor temporare și duce la o memorie "consumată". Rescriind nodul text în interiorul elementului de script din timp, puteți observa modul în care cantitatea de memorie disponibilă scade treptat, datorită diferitelor obiecte ale motorului intern care au fost legate de conținutul anterior. În special, obiectele responsabile pentru depanarea script-urilor rămân în urmă, deoarece aparțin integral codului precedent.

Dacă executați codul de mai sus, si uita-te in Task Manager, care are loc în timpul tranziției de la pagina „curentă“ pe net, nu veți vedea nici scurgeri. Script-ul de memorie consumă numai în pagina curentă, și când vă mutați la un nou tot timpul folosit de memorie este eliberat. Întreaga eroare constă în așteptarea greșită a unui anumit comportament. S-ar părea că o rescriere a script-ul va avea ca rezultat piesa anterioară va dispărea fără urmă, lăsând doar link-urile ciclice sau circuite. Cu toate acestea, de fapt, nu dispare. După cum puteți vedea, aceasta este o pseudo-scurgere. În acest caz, dimensiunea memoriei alocate pare intimidantă, totuși, pentru acest motiv destul de legitim.

concluzie

Fiecare dezvoltator web este o listă personală de exemple de cod pentru care este cunoscut, „curge“ încearcă să găsească pentru fiecare caz merita o decizie, și, atunci când detectează sursa problemei. Acest lucru este foarte util, și este motivul pentru care astăzi web-ul este relativ lipsit de pierderi de memorie. Gândindu-te la problemele de alocare a memoriei în termeni de șabloane, mai degrabă decât în ​​bucăți individuale de coduri, puteți începe să implementați soluții mult mai productive și mai semnificative. Ideea este că deja în stadiul de proiectare a aplicației dvs. ați avut o idee despre ce scurgeri sunt posibile și cum vor funcționa mai bine. Utilizați tactici "defensive" în timpul dezvoltării și presupuneți că toată memoria utilizată de aplicație trebuie eliberată. Deși aceasta este o exagerare a problemei reale, deoarece este foarte rară atunci când într-adevăr necesită eliberarea memoriei, aceasta devine semnificativă în prezența unor proprietăți variabile și extensibile ale unei potențiale tendințe de scurgere.

Citiți mai multe