Creșteți performanța părții client a aplicației web

Una dintre principalele reguli pentru dezvoltarea unui frontend al unei aplicații web este de a se asigura că utilizatorul se simte controlat deplin asupra interfeței sale. Și pentru a face acest lucru, aplicația trebuie făcută să reacționeze instantaneu la acțiunile utilizatorului, adică să facă o întârziere între acțiunea utilizatorului și răspunsul la interfață care nu este sensibil. În acest articol, voi descrie mai multe tehnici de optimizare a performanței, care vor ajuta la crearea unei aplicații lentă.







Explicați faptul că variabilele globale sunt rele, nu este necesar - acest lucru este de înțeles. Dar de ce rău și cât de mare este, vom încerca să ne dăm seama. Luați, de exemplu, un cod simplu care traversează o matrice și produce unele acțiuni simple cu fiecare element. Să creăm o serie de 100 000 de elemente și să scriem un număr aleatoriu în fiecare dintre ele.

Aici, funcția traversează o matrice în domeniul global. Interpretul, după ce a văzut în starea arr.length, începe căutarea pentru variabila arr. Primul lucru pe care îl caută în domeniul local, adică în interiorul funcției. Cu toate acestea, variabila arr nu este declarată în interiorul funcției. Apoi interpretul merge într-un lanț de domenii la un nivel superior (în cazul nostru, din fericire - imediat în domeniul global, deși ar putea fi mai rău) și căutări acolo. Aici găsește în cele din urmă variabila arr și caută lungimea proprietății conținută în ea. Căutarea fiecărui domeniu necesită un timp prețios. Să încercăm să rescriem funcția astfel încât să nu treacă la alte domenii la fiecare iterație a buclei.

Această optimizare aparent superficială oferă Chrome un câștig uimitor de performanță - de 2,5 ori (35 ms în loc de 81). În Firefox, incrementul este mai puțin tangibil, dar există și: 54 ms în loc de 60, adică 10%. În Opera 12 timpul de execuție este redus și mai puțin semnificativ: de la 99 la 95 ms.

În ceea ce privește lucrul cu o matrice, putem optimiza în continuare corpul bucla folosind metoda push în locul accesării fiecărui element specific al matricei:

Ori de câte ori este posibil (și acest lucru este practic peste tot), merită transferat datele la cel mai local domeniu de aplicare. De exemplu, utilizați un șablon de funcții imediat numite. Aceasta este, în loc de acest cod:

este mai bine să scrieți acest lucru:

Mai bine, faceți ca și pentru a obține obiectul documentului, funcția nu trebuie căutată în spațiul de nume global:

Aici am trecut obiectul documentului la o funcție anonimă ca argument, așa că am mutat-o ​​în spațiul de nume local pentru această funcție. Același model este utilizat în pluginurile jQuery:

Anticipând o virgulă în jQuery-plugins elimina posibilele erori care apar atunci când combinarea plugin-uri minifikatorami și preprocesoare, atunci când la capătul uneia dintre virgulă plug-in cod nu este la sfârșit.

Creșterea productivității părții client a aplicației web
Timpul de acces la diferite domenii în diferite browsere, ms

Pentru a reduce timpul ciclului, este evident că este necesar să se reducă fie numărul de operații din fiecare iterație, fie numărul de iterații în sine. Și chiar dacă ați optimizat deja corpul bucla și performanța este încă inadecvată, există o cale de ieșire. Puteți reduce numărul de operații care nu sunt evidente efectuate de către interpret. Anterior am forțat deja interpretul să nu meargă la fiecare iterație în zone externe de vizibilitate, acum vom încerca să continuăm optimizarea.

O metodă simplă și foarte frumoasă de scurtare a timpului ciclului este de a schimba direcția ocolului spre opus, adică în loc de

Aplicând această optimizare la exemplul anterior obținem:







În Chrome această metodă, în acest caz, dă o creștere a performanței de 10% (de la 32 la 29 ms) în Opera 12 runtime practic nici o schimbare (923 și 939), dar în Firefox și IE este înjumătățită: c 1 030-525 ms pentru Firefox și de la 1705 la 812 pentru IE. Pentru a înțelege cauzele acestui efect, vom explica toate operațiunile care produce un interpret la fiecare iterație a buclei.

În primul caz, succesiunea acțiunilor va fi după cum urmează:

  1. Calculați valoarea expresiei booleene i <10000000.
  2. Comparați valoarea obținută cu valoarea adevărată.
  3. Creșteți i.

În al doilea caz, acesta este:

  1. Comparați valoarea lui i cu adevărat.
  2. Scade i.

În conformitate cu "regula minciunii", orice valoare numerică diferită de zero a lui i este redusă la adevărată. Pentru a falsifica, îmi amintesc, doar 0, NaN, null, undefined și un șir gol sunt date.

O metodă mai puțin elegantă, dar destul de eficientă pentru optimizarea buclelor este extinderea corpului bucla, crescând numărul de operații în fiecare iterație, dar reducerea numărului de iterații. Această tehnică se numește "serviciul lui Duff". Pentru el este necesar să se sacrifice frumusețea și laconismul codului, dar în cazurile în care productivitatea este mai importantă decât cea mai scurtă, această tehnică va fi utilă. De exemplu, putem înlocui acest cod:

Acest lucru va reduce timpul de execuție cu 10% în Opera 12, iar în Chrome și Firefox - cu 20%. Am redus numărul de iterații este de opt ori ca o consecință - în opt același timp reduce numărul de inspecții efectuate de regie în mod inevitabil, în timpul fiecărei iterație a buclei. Ei bine, pentru a asigura funcționarea corectă a numărului de repetiții nu este un multiplu de opt, a făcut uz de un comutator c care se încadrează prin“la următorul caz« (să acorde o atenție faptul că, la sfârșitul fiecărui caz, nu există nici o directivă pauză).

Putem face același lucru mai scurt prin înlocuirea comutatorului cu o buclă, practic fără pierderi de performanță:

Această tehnică este eficientă numai atunci când există un număr mare de iterații.

Creșteți performanța părții client a aplicației web
Durata ciclului în diferite browsere, ms

Atunci când aceeași funcție este numită în mod repetat, va fi utilă utilizarea metodei "memo" sau, mai simplu, memorarea în cache a valorii returnate. Mai ales această metodă este utilă în cazul în care funcția efectuează unele operații de lungă durată. Luați în considerare exemplul de calcul al factorialului unui număr. Funcția clasică recursivă de calcul al factorială arată astfel:

Se face destul de repede, însă cu exemplul ei puteți demonstra frumos acceptarea memoriei.

Valorile de numerar disponibile prin circuit, acest lucru exclude o schimbare neintenționată - acces la ea are doar funcția factorial. Să presupunem că avem nevoie pentru a calcula în mod constant factorialul 100, 101 și 102. Dacă utilizați o funcție recursivă clasic, vom calcula mai întâi factorialul numărului de 100 (100 = 100 * 99 * 98 ... * 1 * 99 sau 100!), Și apoi - numărul de 101 (101! = 101 * 99 * 100 ... * 101 sau 1 * 100), și apoi -! factorial 102 (102 = 102 * 101 * 100 ... * 102 sau 1 * 101!). Astfel, factorul 101 este calculat de două ori, iar numărul 100 este calculat de trei ori. Memorializarea valorilor permite evitarea acestei situații. Când folosim cache-ul de rezultate, calculăm mai întâi valoarea 100. și în calculul de 101! calculele repetate nu vor fi efectuate. În schimb, valoarea deja calculată 100 este extrasă din memoria cache, înmulțită cu 101 și returnată. Astfel, evităm un număr imens de calcule opționale. Memoization efect deosebit de clar perceptibil la efectuarea operațiunilor lente, mari consumatoare de resurse (de exemplu, cu DOM-tree). Cu toate acestea, atunci când se utilizează această metodă trebuie să fie sigur că, pentru fiecare apel în funcție ulterioară cu aceleași argumente returnează rezultatul său trebuie să fie aceeași ca și în momentul precedent. Prin urmare, cache-ul nu este potrivit pentru procesarea datelor în schimbare dinamică.

Totuși, asta nu este totul. Atâta timp cât operațiile de recuperare a elementului DOM sunt efectuate operațiile de redirecționare a paginii. Pagina redată de fiecare dată când modificați forma elementelor: modificați blocurile de text în blocuri, adăugați blocuri noi în aspectul paginii, schimbați stilurile elementelor. Pentru a minimiza timpul pe care un browser îl cheltuiește pentru a redrafla o pagină, este necesar să combinați mai multe operații succesive care schimbă forma documentului, la una ori de câte ori este posibil.

Dacă dintr-un motiv oarecare nu puteți face acest lucru și mai trebuie să adăugați conținut la elementul de mai multe ori la rând, este mai bine să eliminați elementul din flux, să efectuați toate acțiunile necesare pe acesta și apoi să nu îl observați pentru al readuce la loc. Astfel de operațiuni simple, de regulă, se desfășoară foarte repede, astfel încât utilizatorul cel mai probabil nu o va observa nici măcar.

Minor și non-evidente la prima vedere, tehnici de programare poate asigura cererea dvs. la mai multe câștiguri de performanță și de a salva utilizatorii de încetinire enervant și obositoare de așteptare, și - de la problemele de suport tehnic și utilizatorilor nesatisfăcute. Desigur, dacă aplicați aceste tehnici cu înțelepciune.

Mărirea duratei de execuție a scriptului

Cea mai ușoară modalitate de a măsura timpul de lucru:

Creșteți performanța părții client a aplicației web
Măsurarea timpului de mers în consola

Cărți bune despre optimizarea interfeței

Distribuiți acest articol cu ​​prietenii dvs.:







Trimiteți-le prietenilor: