chevron-left chevron-right

[JS] Wykrywanie wydajności urządzeń mobilnych za pomocą HTML5 i JS

Projektując nowoczesne interfejsy użytkownika strony internetowej, aż się prosi aby dodawać małe subtelne animacje elementów znajdujących się na stronie, aby zwiększyć przyjemność korzystania z interfejsu. Lecz takie podejście może mieć ogromny wpływ na płynność działania strony.

Jednym ze sposobów na ograniczenie liczby efektów może być wykrywanie wielkości ekranu, tym samym zakładając że urządzenie mobilne (w przypadku ekranu o małej rozdzielczości) nie będzie wystarczająco mocne aby uciągnąć wszystkie efekty. Takie podejście już teraz może być błędne, ze wzgędu na to, że urządzenia już teraz mogą mieć duże ekrany, nie posiadając wymaganej mocy obliczeniowej. W przyszłości może również dojść do sytuacji, że urządzenia mobilne będą dorównywały mocą laptopom i większość z nich będzie posiadało ekrany o dużej rozdzielczości, tj. powyżej 1024x768px.

Na szczęście istnieje inny sposób na wykrycie wydajności danego urządzenia. W tym celu wykorzystałem element <canvas/> oraz requestAnimationFrame API a do zebrania danych wykorzystałem Google Analytics API.

Mechanizm sprawdzenia wydajności

Przykładowy kod HTML, który stanowi bazę dla naszego mechanizmu sprawdzenia wydajności urządzenia mobilnego wygląda następująco:

1
<canvas id="board" width="300" height="300"></canvas>

Jest to element o wymiarach 300 pikseli na 300 pikseli. Następnie trzeba sprawdzić, czy requestAnimationFrame API jest dostępne w przeglądarce:

1
2
3
4
5
6
7
8
9
10
11
12
window.requestAnimFrame = (function () {
  return  window.requestAnimationFrame        ||
          window.webkitRequestAnimationFrame  ||
          window.mozRequestAnimationFrame     ||
          window.oRequestAnimationFrame       ||
          window.msRequestAnimationFrame      ||
          function (callback, element) {
            window.setTimeout(function () {
                callback(+new Date);
            }, 1000 / 60);
          };
})();

Z racji tego, że API w każdej przeglądarce może mieć inną nazwę (z dodanym prefiksem), to trzeba kod ujednolicić dla ułatwienia.

Mając już tak przygotowaną bazę, możemy przystąpić do pisania kodu odpowiedzialnego za wykonanie pomiaru i przesłanie wyniku za pomocą Google Analytics.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
(function (window, document, undefined) {
  var isAnimationRunning  = true;
  var isResultDisplayed   = false;
  var oldtime       = +new Date;
  var fps           = 0;
  var checkCount    = 0;
  var maxCheckCount = 100;
  var results  = [];
 
  var showScore = function (score) {
    var boardCanvas   = document.getElementById('board');
    var boardContext  = boardCanvas.getContext('2d');
    var boardWidth    = boardCanvas.width;
    var boardHeight   = boardCanvas.height;
 
    boardContext.clearRect(0, 0, boardWidth, boardHeight);
    boardContext.fillStyle = '#000000';
    boardContext.font      = 'normal 1rem Arial';
    boardContext.fillText(score + ' fps', 10, 26);
  };
 
  var checkLoop = function (time) {
    time = parseInt(time, 10);
 
    if (!isNaN(time)) {
      fps     = parseInt(1000 / (time - oldtime), 10);
      oldtime = time;
    }
 
    if (isAnimationRunning &amp;&amp; checkCount &lt; maxCheckCount) {
      checkCount++;
      results.push(fps);
      requestAnimFrame(checkLoop);
    } else {
      if (!isResultDisplayed) {
        var sum = results.reduce(function (a, b) {
          return a + b;
        }, 0);
        var score = sum / maxCheckCount;
 
        isResultDisplayed = true;
        ga('send', 'event', 'performance', 'result', navigator.userAgent, score);
        showScore(score);
      }
      requestAnimFrame(checkLoop);
    }
  }
 
  checkLoop();
 
})(this, this.document);

Zdefiniowałem dwie funkcje checkLoop() oraz showScore(). Pierwsza z nich uruchamia pętlę, która zbiera pomiary czasu do tablicy results. Po wykonaniu wymaganej liczby powtórzeń pomiaru - maxCheckCount, następuje sprawdzenie czy wynik został wyświetlony. Jeśli nie, to następuje wyliczenie średniej z zebranych wyników i wyświetlenie jej na stronie oraz wysłanie zdarzenia do Google Analytics z danymi dotyczącymi wyniku oraz rodzaju przeglądarki.

Eksperyment można wzbogacić za pomocą dodania dodatkowego elementu <canvas/>, która będzie wykonywała zaawansowaną animację, np. animację zegarka.

Wyniki pomiarów

Na podstawie zebranych wyników (51 niezależnych pomiarów - różnych urządzeń mobilnych) mogłem wywnioskować, że im nowsze urządzenie mobilne tym lepiej sobie radzi z obsługą animacji. Najgorszy wynik miały Blackberry Bold 9900 - 14,61fps (frame per second), Samsung i5510 - 14,32fps oraz Nokia Lumia 710 - 31fps.

Zauważyłem jeszcze jedną rzecz, że przeglądarki internetowe (nie ważne czy na urządzeniach mobilnych czy też na standardowym komputerze) mają górne ograniczenie liczby FPS i średnie wyniki oscylują w okolicach 60fps. Większość urządzeń jednak ma wydajność na poziomie między 50fps a 60fps.

Podsumowanie

Tego typu funkcjonalność można wykorzystać, aby sprawdzić czy dane urządzenie w danym momencie jest w stanie uruchomić zaawansowane animacje po stronie interfejsu. Jeśli na przykład użytkownik ma kilka programów uruchomionych w tle, np. gry i akurat chce przejrzeć wiadomości na stronie internetowej, to wtedy warto sprawdzić czy przeglądarka będzie w stanie płynnie wyświetlić zaawansowane animacje na naszej stronie. Żaden użytkownik nie będzie lubił gdy przewinięcie w dół lub przełączenie się między widokami danych będzie trwało długo lub będzie jeszcze bardziej spowalniało urządzenie.

Co myślisz o tego typu rozwiązaniu? Zapraszam do komentowania.