Preskoči na sadržaj

Mjerenje i tehnike poboljšanja performansi web aplikacija

doc. dr. sc. Vedran Miletić, vmiletic@inf.uniri.hr, vedran.miletic.net

Fakultet informatike i digitalnih tehnologija Sveučilišta u Rijeci, akademska 2021./2022. godina


Korisnička percepcija brzine rada web sjedišta

Nielsen Norman Group, istraživači u domeni korisničkog iskustva, su u članku iz 1997. godine kao najveći razlog za sporost web sjedišta istaknuli velike slike.

13 godina kasnije, nakon prodora broadband pristupa kod velikog broja korisnika interneta, ponovno su razmotrili problem i objavili članak o vremenima odgovora na zahtjeve od strane web sjedišta u kojemu kažu:

Slow page rendering today is typically caused by server delays or overly fancy page widgets, not by big images. Users still hate slow sites and don't hesitate telling us.


Ograničenja vremena odgovora na zahtjev (1/2)

Isti autori su u starijem članku iz 1993. godine zaključili na temelju istraživanja ljudskih faktora u korištenju tehnologije da postoje ograničenja vremena odgovora na zahtjev:

  • 0,1 sekunda daje osjećaj trenutnog odgovora -- to jest, ishod se čini kao da ga je uzrokovao korisnik, a ne računalo. Ova je razina odzivnosti ključna za podršku osjećaju izravne manipulacije (izravna manipulacija jedna je od ključnih GUI tehnika za povećanje angažmana i kontrole korisnika).
  • 1 sekunda održava tijek misli korisnika besprijekornim. Korisnici mogu osjetiti kašnjenje i tako znaju da računalo generira ishod, ali i dalje osjećaju kontrolu nad ukupnim iskustvom i da se slobodno kreću, a ne čekaju na računalo. Ovaj stupanj odziva potreban je za dobru navigaciju.

Ograničenja vremena odgovora na zahtjev (2/2)

  • 10 sekundi zadržava pažnju korisnika. Nakon 1–10 sekundi korisnici definitivno osjećaju da su prepušteni na milost i nemilost računala i priželjkuju da je brže, ali mogu se nositi s tim. Nakon 10 sekundi počinju razmišljati o drugim stvarima, što otežava vraćanje na razmišljanje o problemu koji rješavaju nakon što računalo napokon reagira. Dodatno o tome kažu:

    A 10-second delay will often make users leave a site immediately. And even if they stay, it's harder for them to understand what's going on, making it less likely that they'll succeed in any difficult tasks. Even a few seconds' delay is enough to create an unpleasant user experience. Users are no longer in control, and they're consciously annoyed by having to wait for the computer. Thus, with repeated short delays, users will give up unless they're extremely committed to completing the task.


Jednostavno mjerenje vremena odgovora na zahtjev

Iskoristimo Network Monitor (Firefox Developer Tools) za mjerenje brzine prikaza kućne stranice nekoliko web sjedišta:


Stvaranje opterećenja i mjerenje vremena odgovora na zahtjev

Dosad smo mjerili vrijeme odgovora na zahtjev jednog korisnika. Moguće je simulirati opterećenje većeg broja istovremenih korisnika i mjeriti vrijeme odgovora na zahtjev. Alati koji se pritom koriste su:


Druga motivacija osim korisničkog iskustva

When real users have a slow experience on mobile, they're much less likely to find what they are looking for or purchase from you in the future. For many sites this equates to a huge missed opportunity, especially when more than half of visits are abandoned if a mobile page takes over 3 seconds to load.

Users want to find answers to their questions quickly and data shows that people really care about how quickly their pages load. The Search team announced speed would be a ranking signal for desktop searches in 2010 and as of this month (July 2018), page speed will be a ranking factor for mobile searches too.

Izvor: Speed is now a landing page factor for Google Search and Ads (Addy Osmani and Ilya Grigorik, Google Developers, July 2018)

Googleovi alati za developere: Make the Web Faster, PageSpeed Insights


Brzina prikaza stranice kao faktor u rangiranju

Google has indicated that site speed (and as a result, page speed) is one of the signals used by its algorithm to rank pages. And research has shown that Google might be specifically measuring time to first byte as when it considers page speed. In addition, a slow page speed means that search engines can crawl fewer pages using their allocated crawl budget, and this could negatively affect your indexation.

Izvor: Page Speed (Moz)

Drugi članci na Moz blogu u kojima govori o brzini prikaza web stranica: Winning the Page Speed Race: How to Turn Your Clunker of a Website Into a Race Car, Better Site Speed: 4 Outside-the-Box Ideas


Web Vitals

Web Vitals inicijativa je Googlea za pružanje jedinstvenih smjernica za kvalitetne signale koji su neophodni za pružanje izvrsnog korisničkog iskustva na webu.


Smanjenje broja HTTP zahtjeva

  • Inline JavaScript koda (ako nije velik) u HTML datotekama
  • Korištenje CSS Sprites za prikaz slika (naročito ikona, simbola)
  • Korištenje manjeg broja CSS/JavaScript biblioteka i okvira
  • Spajanje CSS/JavaScript datoteka
    • npr. Font Awesome (izvorno 6 CSS i 7 JavaScript datoteka se distribuira kao 1 JavaScript i 1 CSS datoteka)
  • Korištenje manjih CSS/JavaScript biblioteka i okvira
    • npr. Ionicons (1 JavaScript datoteka, 1300 ikona) umjesto Font Awesome (1 JavaScript i 1 CSS datoteka, 7800 ikona)

Smanjenje veličine CSS i JavaScript datoteka

Alati kao minify s npm-a mogu iz CSS i JavaScript datoteka bez promjene značenja napisanog koda maknuti:

  • Neke razmake
  • Znakove novog retka
  • Komentare
  • Neke znakove za blok koda

Yet Gmail downloads about three megabytes worth of JavaScript to render its inbox. HEY downloads less than sixty kilobytes. If you can build a Gmail rival with this stack, and have it be met with broad applaud by tens of thousands of paying customers, you can probably build just about anything with it.

Izvor: Rails 7 will have three great answers to JavaScript in 2021+ (DHH, HEY World)


Resursi koji blokiraju prikaz stranice

CSS:

JavaScript:

  • Moguće je postaviti <script></script> na dnu stranice da izvođenje skripte ne prekida nastavak učitavanja HTML-a i resursa koje HTML navodi
  • <script async src="..."></script> asinkrono učitava skriptu
  • <script defer src="..."></script> odgađa izvođenje skripte dok se stranica ne učita

Korištenje mreže za distribuciju sadržaja

Mreža za isporuku sadržaja ili mreža za distribuciju sadržaja (engl. content delivery network, kraće CDN) je geografski distribuirana mreža proxy poslužitelja i njihovih podatkovnih centara. Cilj je pružiti visoku dostupnost i performanse distribucijom usluge prostorno blizu krajnjih korisnika. (Wikipedia)

Rad CDN-ova omogućen je korištenjem Cross-Origin Resource Sharinga (CORS-a).

Popularni CDN-ovi:


Smanjenje korištenja HTTP 301 Moved Permanently


Eliminacija polomljenih poveznica (HTTP 404 Not Found)

Web poslužitelji i web aplikacije izvode usmjeravanje na način:

  • potraži statičku datoteku (web poslužitelj izvodi usmjeravanje),
  • ako ne postoji datoteka, potraži dinamički resurs (web aplikacija izvodi usmjeravanje, npr. Django URL dispatcher, Rails router, Laravel router),
  • ako ne postoji putanja koju web aplikacija poznaje, vrati HTTP statusni kod 404 Not Found i pripadnu stranicu

Keširanje

Web aplikacije koje uključuju Memcached kao potpornu uslugu na način kako to propisuje dvanaest faktora se zasigurno nekad pitaju:

Muči me pitanje
O da li bi me volela i da nemam keš?

Izvor: GAZDA PAJA x MARLON BRUTAL -- DIZEL (OFFICIAL VIDEO)

Keširanje je jedna od najvažnijih, ako ne i najvažnija tehnika za postizanje visokih performansi web aplikacije. Razlikujemo nekoliko vrsta keširanja:

  • keširanje resursa u pregledniku (kod korisnika)
  • keširanje odgovora ispred web poslužitelja
  • keširanje odgovora u web aplikaciji
  • keširanje operacija u interpreteru programskog jezika

Keširanje u pregledniku (1/3)

HTTP zaglavlje Pragma (dokumentacija na MDN-u) je HTTP/1.0 ekvivalent zaglavlja Cache-Control i koristi se samo za kompatibilnost sa starijim sustavima.

HTTP zaglavlje Cache-Control (dokumentacija na MDN-u):

  • public, private, no-cache, no-store
  • max-age, s-maxage (vrijeme u sekundama)
  • must-revalidate, proxy-revalidate, immutable

Provjerimo zaglavlja (naredba curl -I) na:


Keširanje u pregledniku (2/3)

Primjer u Apache HTTP Serveru s uključenim mod_headers:

<IfModule mod_headers.c>
    Header set Cache-Control "max-age=84600, public"
</IfModule>

Ilustrativan primjer u čistom PHP-u (Laravel ima klasu SetCacheHeaders):

<?php

header('Cache-Control: max-age=86400, public');

Okviri za razvoj aplikacija brinu o keširanju na višoj razini i pritom u odgovorima postavljaju adekvatna HTTP zaglavlja (o tome programeri uglavnom ne brinu).


Keširanje u pregledniku (3/3)

HTTP zaglavlje Expires (dokumentacija na MDN-u) navodi vrijeme isteka resursa (standardna specifikacija dozvoljava do godinu dana); ako Cache-Control navodi max-age ili s-maxage, sadržaj zaglavlja Expires se ignorira.

Primjer postavki koje generiraju zaglavlje Expires u web poslužitelju Apache HTTP Server koji koristi mod_expires:

ExpiresByType text/html "access plus 1 seconds"
ExpiresByType image/x-icon "access plus 2592000 seconds"
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType text/css "access plus 604800 seconds"
ExpiresByType application/x-javascript "access plus 604800 seconds"
ExpiresByType application/javascript "access plus 604800 seconds"
ExpiresByType application/ecmascript "access plus 604800 seconds"
ExpiresByType application/font-woff "access plus 604800 seconds"
ExpiresByType font/woff2 "access plus 604800 seconds"

Keširanje ispred web poslužitelja

Obrnuti HTTP proxy poslužitelj s keširanjem nalazi se ispred web poslužitelja tako da korisnik koji pristupa web poslužitelju prvo pristupa tom proxyju.

Taj proxy služi da korisnicima koji zahtijevaju isto što su oni ili drugi već ranije zahtijevali vrati stvoreni keširani odgovor (npr. rezultat pretrage za artiklima u web trgovini).

Primjer takvog poslužitelja je Varnish.

Wikipedia webrequest flow 2020 bg right 90%


Keširanje u web aplikaciji

Kako vidimo na primjeru Wikipedije, aplikacija može i sama spremiti generirani odgovor na primljeni zahtjev u sustav za keširanje i dohvatiti ga kad ponovno dobije isti zahtjev.

Popularni okviri za razvoj aplikacija imaju gotove implementacije sustava za keširanje koji onda umjesto programera brinu o spremanju i dohvaćanju sadržaja te postavljanju odgovarajućih zaglavlja u HTTP odgovorima. Primjeri takvih sustava su:


Keširanje operacija u interpreteru programskog jezika

Interpretirani programski jezici pretvaraju kod koji je programer napisao u vlastiti interni kod (bytecode u Pythonu, opcode u PHP-u) koji onda izvode njihove implementacije (CPython u Pythonu, Zend Engine u PHP-u). Te kodove je moguće keširati:


Korak dalje: just-in-time (JIT) prevođenje u strojni kod

Just-in-time (JIT) prevoditelj unutar interpretera omogućuje prevođenje (dijela) koda dok se interpretirani program izvodi u strojni kod za izravno izvođenje bez interpretera (više detalja na Wikipediji).

Implementacije JIT prevoditelja:


Brzina rada interpretera programskog jezika

It's important to be realistic: most people don't care about program performance most of the time.

Izvor: Laurence Tratt, What Challenges and Trade-Offs do Optimising Compilers Face?

Django overview: "Ridiculously fast. Django was designed to help developers take applications from concept to completion as quickly as possible."

The Rails Doctrine: 'One of the early productivity mottos of Rails went: "You're not a beautiful and unique snowflake". It postulated that by giving up vain individuality, you can leapfrog the toils of mundane decisions, and make faster progress in areas that really matter.'


Problemi mjerenja brzine interpretera programskog jezika (1/2)

Our results show that real web applications behave very differently from the benchmarks and that there are definite ways in which the benchmark behavior might mislead a designer.

Izvor: Paruj Ratanaworabhan, Benjamin Livshits, Benjamin G. Zorn: JSMeter: Comparing the Behavior of JavaScript Benchmark swith Real Web Applications (2010 USENIX conference on Web application development) Više informacija: JSMeter: Measuring JavaScript Web Applications (Microsoft Research)


Problemi mjerenja brzine interpretera programskog jezika (2/2)

Our results indicate that just-in-time compilation often increases the execution time for web applications, and that there are large differences in the execution behavior between benchmarks and web applications at the bytecode level.

Izvor: Jan Kasper Martinsen, Håkan Grahn, Anders Isberg: A Comparative Evaluation of JavaScript Execution Behavior (11th International Conference on Web Engineering -- ICWE 2011)


Dohvaćanje imena domene unaprijed (dns-prefetch)

Dohvaćanje imena domene unaprijed dobro je rješenje za pronalaženje IP adrese povezane s imenom domene prije nego što korisnik odabere slijediti ("klikne na") poveznicu na tu domenu. Primjer koda u HTML-u:

<head>
  <!-- ... -->
  <link rel="dns-prefetch" href="https://www.example.com/">
</head>

(Više detalja o dns-prefetchu na MDN-u i njegova primjena u ostvarivanju boljih performansi, specifikacija u Resource Hints na W3C-u.)


Povezivanje unaprijed (preconnect)

Povezivanje unaprijed omogućuje pregledniku da uspostavi vezu s poslužiteljem prije nego će doći do potrebe za slanjem HTTP zahtjeva na taj poslužitelj. Pronalaženje IP adrese za domenu putem DNS-a, TCP rukovanje i dogovor oko šifrarnika u TLS-u mogu se pokrenuti unaprijed, čime se eliminra povratno kašnjenje za te veze i štedi vrijeme iz perspektive korisnika.

<head>
  <!-- ... -->
  <link rel="preconnect" href="https://www.example.com/"
        crossorigin="anonymous">
</head>

(Više detalja o preconnectu na MDN-u, specifikacija u Resource Hints na W3C-u.)


Kompresija

Gzip (Wikipedia) je oblik kompresije koji komprimira HTML, CSS i JavaScript datoteke na poslužitelju prije slanja klijentu. Ovo je jednostavno uključiti u popularnim web poslužiteljima, a može drastično smanjiti količinu podataka koja se prenosi.

Više detalja na MDN-u:


Kompresija (Apache HTTP Server)

Primjer u Apache HTTP Serveru s uključenim mod_deflate:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE font/opentype
    AddOutputFilterByType DEFLATE font/otf
    AddOutputFilterByType DEFLATE font/ttf
    AddOutputFilterByType DEFLATE image/svg+xml
    AddOutputFilterByType DEFLATE image/x-icon
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/xml
</IfModule>

Kompresija (PHP)

<?php

$contents = '...'

if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) &&
    str_contains($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
  header('Content-Encoding: gzip');
  $compressed_contents = gzencode($contents);
  echo $compressed_contents;
}
else {
  echo $contents;
}

Web fontovi

Nedostatak web fontova (npr. Google Fonts i Adobe Fonts) je u tome što uvode dodatne HTTP zahtjeve za vanjskim resursima. Učitavanje web fontova također blokira prikaz sadržaja (stranice koriste "ružne" fontove dok nisu učitani).

Bolje performanse mogu se ostvariti:

  1. Smanjenjem broja stilova (npr. težina 400 (regular) uspravni i zakošeni, težina 700 (bold) samo uspravni)
  2. Smanjenjem skupa korištenih znakova (npr. na latin i latin extended)
  3. Dohvaćanjem fontova unaprijed (npr. prefetch, preconnect)

Prevencija hotlinkanja

Prevencija hotlinkanja odnosi se na ograničavanje skupa prihvatljivih HTTP referrera kako bi se spriječilo da drugi ugrađuju vaše datoteke (npr. slike i snimke) na web stranice osim vaše, što štedi širinu pojasa zabranom prikazivanja datoteka na drugim web lokacijama.

Primjer korištenjem Apache HTTP Servera i modula mod_rewrite:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTP_REFERER} !^http://(.+\.)?example\.com/ [NC]
    RewriteCond %{HTTP_REFERER} !^$
    RewriteRule .*\.(jpe?g|gif|png|mp4)$ http://example.com/nolink.png [L]
</IfModule>

HTTP/2

HTTP/2 značajno poboljšava performanse učitavanja web stranice koja ima mnogo slika (za ilustraciju: Go + HTTP/2 demo poslužitelj, Akamai HTTP/2 poslužitelj).

HTTP/2 works by making a single connection to the server, and then "multiplexing" multiple requests over that connection to receive multiple responses at the same time.

Izvor: HTTP/2: A Fast, Secure Bedrock for the Future of SEO (Moz Blog)


HTTP/2 u Apache HTTP Serveru

Apache HTTP Server podržava HTTP/2 korištenjem mod_http2. Za HTTP/2 preko TLS-a ("HTTPS") konfiguracija je oblika:

Protocols h2 http/1.1

Sve varijante HTTP/2 ("HTTPS" i "HTTP"):

Protocols h2 h2c http/1.1

HTTP/2 demo na example.group.miletic.net

$ curl -I http://example.group.miletic.net/
HTTP/1.1 200 OK
Date: Mon, 31 Jan 2022 20:58:34 GMT
Server: Apache/2.4.52 (Debian)
Upgrade: h2,h2c
Connection: Upgrade
Last-Modified: Wed, 25 Aug 2021 14:52:01 GMT
$ curl -I --http2 http://example.group.miletic.net/
HTTP/1.1 101 Switching Protocols
Upgrade: h2c
Connection: Upgrade

HTTP/2 200
last-modified: Wed, 25 Aug 2021 14:52:01 GMT

Utjecaj HTTP/2 na web

With HTTP2, you no longer pay a large penalty for sending many small files instead of one big file. A single connection can multiplex all the responses you need. No more managing multiple connections, paying for multiple SSL handshakes. This means that bundling all your JavaScript into a single file loses many of its performance benefits (yes, yes, tree-shaking [link added] is still one).

Izvor: Modern web apps without JavaScript bundling or transpiling (DHH, HEY World)


HTTP/3

the naive engineer geek comic bg 95% left:55%

Mazohizam

Izvor: the naive engineer ({turnoff.us})


Dodatne optimizacije

Author: Vedran Miletić