Pomiary i wydajność#
Czas wysokiej rozdzielczości#
Grupa robocza odpowiedzialna za rozwój standardów dotyczących wydajności Webu wprowadziła możliwość pomiaru czasu z dokładniejszą precyzją niż umożliwiały to dotychczasowe mechanizmy. Całość opisywana jest w następujących specyfikacjach W3C:
Druga wersja specyfikacji jest rozszerzeniem pierwszego standardu, a jedyna różnica polega na udostępnieniu metody Performance.now()
w wątkach roboczych.
Dotychczasowy pomiar czasu względem nowego podejścia#
Od dawien dawna pomiar czasu w trakcie profilowania sprowadzał się do wykorzystania obiektu Date
z języka ECMAScript. Obiekt ten może wyrazić czas w milisekundach (typ Number
), jaki upłynął od 00:00:00 UTC 1 stycznia 1970 roku aż do chwili obecnej. W większości zastosowań definicja ta jest wystarczająca ponieważ reprezentuje czas z dokładnością do milisekundy dla każdego przypadku, który wystąpił ok. 285,616 lat po 1970 roku.
Na podobnej zasadzie zdefiniowano typ DOMTimeStamp
wykorzystywany w zdarzeniach (właściwość Event.timeStamp
), chociaż w tym przypadku oczekuje się, że w niedalekiej przyszłości właściwość zostanie zmodyfikowana.
Prosty przykład:
<script>
// Analogiczne polecenia
var time1 = Date.now();
var time2 = +new Date();
var time3 = new Date().getTime();
document.write(time1); // liczba całkowita
document.write("<br>");
document.write(time2); // liczba całkowita
document.write("<br>");
document.write(time3); // liczba całkowita
document.write("<br>");
document.write(typeof time1); // number
document.write("<br><br>");
document.write(time1 == time2); // true
</script>
Rozwiązanie to posiadam kilka istotnych wad. Oto najważniejsze z nich:
- Aktualne maszyny JS są na tyle wydajne, że pomiar czasu z dokładnością do milisekundy jest niewystarczający. Widać to w powyższym przykładzie, gdzie utworzenie dwóch obiektów
Date
i pobranie z nich czasu zwraca identyczne wartości. - Zakres dla typu
Number
jest skończony i kiedyś okaże się niewystarczający (bardzo odległy problem i z pewnością nie będzie dotyczył osób czytających tę stronę). - Zwracana liczba milisekund jest bardzo duża, ulega ciągłemu zwiększaniu przez co trudniej ją analizować i przechowywać.
- Czas jest podatny na synchronizację (clock skew) i korektę zegara systemowego. W praktyce oznacza to, że w pewnych sytuacjach zwracana wartość może być mniejsza lub równa wartość wcześniejszej.
Powyższe problemy ma wyeliminować nowy typ DOMHighResTimeStamp
, zwany potocznie czasem wysokiej rozdzielczości. Jest to liczba rzeczywista w zakresie double
(typ Number
), która wyraża ilość milisekund jaka upłynęła względem rozpoczęcia nawigacji w aktualnym dokumencie (właściwość PerformanceTiming.navigationStart
) aż do chwili obecnej. Zwracana wartość zazwyczaj wyrażana jest z dokładnością do mikrosekundy. Czas wysokiej rozdzielczości można uzyskać za pomocą metody Performance.now()
.
Prosty przykład:
<script>
var time1 = performance.now();
var time2 = performance.now();
document.write(time1); // liczba rzeczywista
document.write("<br>");
document.write(time2); // liczba rzeczywista
document.write("<br>");
document.write(typeof time1); // number (zakres double)
document.write("<br><br>");
document.write(performance.timing.navigationStart); // liczba całkowita
document.write("<br>");
document.write(time1 == time2); // false (chociaż w Chrome true)
</script>
Specyfikacja nie proponuje zmiany zachowania dla metody Date.now()
i jej podobnych, bo są one naprawdę przydatne w ustalaniu aktualnej wartości czasu kalendarzowego i mają długą historię użycia. Typ DOMHighResTimeStamp
i metoda Performance.now()
ma zapewnić monotonicznie rosnącą wartość z dokładnością do mikrosekundy, niezależnie od zegara systemowego. Będzie to szczególnie użyteczne przy:
- Wszelkich mikrobenchmarkach, gdzie dokładność milisekundowa jest niewystarczająca.
- Obliczaniu stanu animacji ze skryptu, gdzie deweloperzy muszą znać dokładny czas, który upłynął w animacji w celu prawidłowej aktualizacji następnej sceny animacji.
- Obliczaniu klatek w animacji bazującej na skrypcie, gdzie deweloperzy potrzebują dokładniejszej rozdzielczości w celu ustalenia, czy animacja jest rysowana z częstotliwością 60 FPS. Bez dokładniejszej precyzji deweloperzy mogą jedynie określić, czy liczba klatek animacji wynosi 58,8 FPS lub 62,5 FPS.
- Synchronizacji dźwięku z określonym punktem w animacji.