JS Savet: Merenje performansi

U javaskripti često postoji više načina za implementaciju iste funkcionalnosti, na primer, dodavanje elemenata u DOM. Kada se nađemo u takvoj situaciji, teško je odlučiti koju implementaciju da iskoristimo. Iz tog razloga, javaskripta nam pruža Performance API, pomoću kog možemo meriti performanse.

Merenje performansi

Recimo da hoćemo iskoristiti naš primer od ranije, dodavanje elemenata u DOM. Postoji par načina da se to implementira

  1. Korišćenjem innerHTML
  2. Korišćenjem createElement() i appendChild()
  3. Korišćenjem insertAdjacentHTML()

Svaki test će da doda 1000 DOM (li) elemenata. Postavka je sledeća

<ul id="list">
    <!-- Ubaci stvari ovde -->
</ul>

Testovi izgledaju ovako. Za prvi slučaj:

const list = document.getElementById('list');

const start = performance.now();
let html = '';
for(let i = 0; i < 1000; i++) {
    html += '<li>' + i + '</li>';
}

list.innerHTML = html;

const end = performance.now();
console.log('innerHTML ' + (end - start) + 'ms');

Ako napišemo kôd za svaki od slučajeva, dobijamo sledeći rezultat:

Slučaj Vreme
innerHTML 3.4549999982118607ms
appendChild 4.28000000101747ms
insertAdjacentHTML 2.8750000019499566ms

Zahvaljujući performans APIu smo lako videli koja implementacija je najbrža.

Implementacija

Možda se pitate zašto nam je potreban još jedan intefejs, kada imamo Date.now(). Postojeći Date interfejs vraća vreme u milisekundama što je već dovoljno precizno.

const start = Date.now();
longToDoTask();
const duration = Date.now() - start;

U ovom slučaju su milisekunde dosta neprecizna jedinica. Ono što performanse API koristi su isto milisekunde, ali na drugačiji način. Metoda performance.now() vraća DOMHighResTimeStamp, što garantuje preciznost u 5 mikrosekundi.

Još jedna, verovatno mnogo bitnija razlika je, to što se vrednost performance.now() metode konstantno povećava, nezavisno od sata na računaru. To ustvari i jeste glavni problem kod Date.now() metode. Ako tokom testiranja izmenimo vreme na računaru, prilikom uzimanja krajnjeg vremena naše merenje neće biti tačno.  

Eksterni alati

Ako ne želimo da radimo testove lokalno ili pak želimo da podelimo testove sa nekim da i on može testirati, možemo da koristimo eksterne alate za testiranje. Jedan on najstarijih i sigurno najpoznatijih je JSPerf. Iako je par puta bio nedostupan zbog problema servera i finansijskih problem, ostao je sigurno jedan on najboljih.

Evo kako na JSPerfu izgleda naš primer, https://jsperf.com/inesering-dom. Rezultati su isti, samo je sada merena jedinica broj operacija u sekundi.

Slučaj Ops/s
innerHTML 19,201
appendChild 53,707
insertAdjacentHTML 57,434

Eksterna biblioteka

Kad već pričamo o merenju performansi, mislim da je bitno pomenuti biblioteku koja predstavlja zlatan standard za merenje. Biblioteka Benchmark.js nam pruža značajno veću fleksibilnost nego kada sami koristimo Performans API, zato što se kod izvršava više puta, sve dok se ne dođe do minimalnog vremena, potom se to pokrene više puta kako bismo dobili prosek.

JSPerf koristi Benchmark.js kao glavnu biblioteku za testiranje. Zato je moje lično mišljenje da je bolje koristiti JSPerf nego sami da pišete testove koristeći Benchmark.js. JSPerf ima jednu veliku prednost, a to je da možemo lako podeliti test sa nekim i da testove možemo da pokrenemo i uporedimo na različitim veb pregledačima.