Katoni.dk – ModPagespeed til Apache/NGINX Hastighedsoptimering

I vores arbejde med at optimere Katoni har vi udført en række ændringerne både i frontend og backend, som har resulteret i, at forsiden nu indlæses på blot 500 millisekunder, mens vores lidt tungere produktsider med 100 produkter indlæses på omkring 700 ms. Dette resultat er alene opnået med ændringer og omstrukturering af kildekoden samt brugen af PageSpeed modulet fra Google, som nemt og gratis kan installeres oven på Apache eller NGINX servere.
katoni webside screendump

Artikel skrevet af: Katoni.dk

I denne artikel vil jeg forklare, hvad vi konkret har gjort for at opnå vores resultater, og hvor lidt du som hjemmesideejer skal gøre for at få en hurtigere hjemmeside, som måske gør den lille forskel, at dine besøgende vælger din forretning frem for konkurrenternes!

Tiltag 1 – SQL sætninger og indeks

Vi startede med at kigge på vores SQL sætninger, da vores kategorisider loadede alt for langsomt, især når der skulle vises farver og størrelser sammen. Når man har store datamængder i en database, kan man med fordel lave et indeks på en eller flere tabelkolonner. Et indeks bruges til at forbedre performance på SELECT sætninger og dem har vi mange af på vores kategorisider. Når man opretter et indeks, laver databasen en ny blok af information og denne blok skal opdateres hver gang der laves ændringer i de tilhørende tabeller. Så laver du et indeks på en tabel, der tit bliver opdateret, kan det have en negativ effekt.

I vores tilfælde bliver tabellerne kun opdateret, når vi opretter nye produkter og det gør vi cirka 1 gang om dagen. Det giver derfor god mening at oprette indeks på vores tabeller. Du kan læse mere om, hvordan det gøres her.

Efter vi havde lavet indeks på vores tabeller, fandt vi ud af, at vores SQL sætninger lavede alt for mange Temporary tables og samtidig benyttede sig af Filesort.  Når en SQL sætning laver Temporary tables betyder det, at den skriver på serverens harddisk og det er selvfølgelig ikke godt for performance. Derudover lavede de også Filesort, som betød at vores SQL sætninger ikke kunne gøre brug af de indeks, vi havde oprettet i vores database, og derfor måtte løbe igennem alle rækker for at udføre en sammenligning.

Ved at bruge kommandoen EXPLAIN foran vores SQL sætninger kunne vi se, hvor synderne var og kunne dermed optimere dem til ikke at skrive på harddisken og gøre brug af de indeks, vi havde oprettet i vores database. Disse ændringer forbedrede vores loadtid på kategorisiderne med cirka 1 sekund og farve / størrelse kombinationen, som var det største problem, med cirka 3 sekunder.

Tiltag 2 – Caching af hjemmesiden

Vi har lavet vores eget caching modul, der bliver brugt til at cache alle de sider, der har mange daglige besøgende og de sider vi kan se tager for lang tid at loade.

Det fungerer på den måde, at jeg har en tekstfil med de valgte sider som så automatisk bliver kørt igennem hver gang vores database er blevet opdateret med nye produkter. Det tager cirka 5 minutter og så skal de sider ikke i kontakt med vores database og er dermed også med til at reducere antallet af forespørgsler til den. Derudover kan vi sætte det op til automatisk at cache sider, der loader langsommere end 1 sekund så den næste bruger, der besøger denne side, får den genereret meget hurtigere. Du kan læse mere om caching her.

Tiltag 3 – Sammenfletning og reducering af CSS og Javascript

En browser kan cirka indlæse omkring 6 filer på samme tid, det svinger lidt alt efter browser og version. Så jo færre http forespørgsler du har jo bedre. For at få et overblik over, hvor mange filer din hjemmeside indlæser, kan du indtaste webadressen for din hjemmeside på tools.pingdom.com.

Vi havde i forvejen lavet vores CSS og Javascipt i eksterne filer og samelede derfor alt CSS i én fil, som blev placeret så højt som muligt i <head>, da denne fil så indlæses først. Derved undgår man det blink (Flash of Unstyled Content, som det hedder), man ofte ser, når man navigerer rundt på hjemmesider.

Det samme gjorde vi for det meste af vores JavaScript, som gik igen på alle sider. Vær dog opmærksom på at nogle kodestumper kan afhænge af andre – sørg for at bevare indlæsningsrækkefølgen. Det er knap så vigtigt, at du med JavaScript koden ender med én fil, da det er muligt at indlæse JavaScript asynkront.

Herudover gik vi både CSS og Javacript filer igennem og reducerede koden så meget som muligt.

Til sidst flyttede vi næsten alt Javascript til bunden af vores HTML kode. Det gjorde vi ,fordi en browser skal bygge et DOM træ for at parse HTML koden og hver gang den møder et script, skal den stoppe op og eksekvere det og derefter forsætte med at parse HTML’en.

Tiltag 4 – Reducering af HTML og aktivering af Gzip

Ved at reducere den mængde data (trafik) brugeren skal hente for at kunne se side, vil siden indlæses hurtigere. I tiltag 3 sammenflettede og reducerede vi CSS og JavaScript, i dette tiltag er turen kommet til selve HTML koden. Det lykkedes os at reducere kildekoden med op til 50%, hvilket ikke blot har en væsentlig positiv påvirkning på indlæsningstid, men reducerer også browseren hukommelsesbrug, da DOM-træet reduceres.

Vi startede med at fjerne de få steder vi havde brugt inline HTML style, og flyttede det til generelle regler i CSS. Dernæst begrænsede vi brugen af classes eller længden af disse, og brugte CSS som erstatning for classes, f.eks. ved at bevare en class på et ydre HTML element, kan man nemt style specifikke elementer derunder ved brug af forskellige selectors såsom: tagname, >, +, :nth-child, :first-child og :last-child, som i dag understøttes af 97% af anvendte browsere, og må derfor anses som tilgængelige.

Hvis du ikke har Gzip aktiveret, så gør det med det samme. Det reducerer drastisk den mængde data (trafik), brugeren skal hente. Eksempelvis skal brugeren kun hente en kildekode på 30 kb fremfor 140 kb uden du skal gøre noget aktivt – det sker helt automatisk, når først det er aktiveret. Serveren sørger for at komprimere og pakke dataene, så de fylder mindre, mens de sendes, og pakkes derefter ud igen i browseren.

Tiltag 5 – Google PageSpeed Module

Vi installerede Google PageSpeed Module på vores server. Det er faktisk ret nemt at installere og det kommer med en allerede opsat konfiguration, der ud af boksen reducerer dine loadtider væsentligt. Det retter automatisk mange af de fejl, du måske får, når du kører en test med Google’s PageSpeed Insights. Jeg vil ikke beskrive modulet i detaljer, da det er gjort ret godt i denne artikel fra Moz.com og du kan se en video fra Google her.

Efter installationen kunne vi hurtigt se en markant forbedring af vores loadtider og efter lidt konfigurationsarbejde blev det faktisk rigtig godt. Jeg kan kun anbefale at få det, installeret det skal dog lige nævnes, at det lige nu kun fungerer på Apache og NGINX servere. Hvis du har brug for hjælp til at sætte modulet op, er jeg sikker på, at Kim kan hjælpe.

Tiltag 6 – Hent eksterne filer fra eksternt domæne

Som sagt så kan en browser kun indlæse omkring 6 filer på samme tid fra samme domæne. Derfor har vi oprettet et subdomæne static.katoni.dk, der indeholder vores billeder, CSS og JavaScript filer.

Vi henter filerne via tre subdomæner dk1.k-static.dk, dk2.k-static.dk og dk3.k-static.dk. Derfor kan browserne nu hente op til 18 billeder på samme tid og det gør jo en ret væsentlig forskel. Der er selvfølgelig en begrænsning for hvor mange samtidige forespørgsler en browser kan modetage. IE 11 kan hente 17, hvor Chrome 32 kan hente 10, så der er altså ret stor forskel.  Derudover kan man også sætte sine eksterne domæner til at være Cookieless og man sparer dermed nogle bytes på hver enkelt forespørgsel.

Tiltag 7 – Overvågning

Efter vi har lavet alle ændringerne, er det rart at kunne se, hvordan de virker og om alting kører stabilt. Derfor har vi installeret Sealion, der kan fortælle os hvor meget CPU kraft, ram osv. vores server bruger. Desuden har vi installeret MONyog, der overvåger vores database. Monyog kan rigtig mange ting og kan blandt andet fortælle os, hvor hurtigt vores SQL sætninger eksekverer og give os råd til, hvordan vi kan forbedre dem.

Resultatet

Indtil videre er resultatet af overstående ændringer, at vores kategorisider ifølge tools.pingdom.com som regel loader på omkring 700 til 900 ms. Før lå de mellem 2,5 og 5 sekunder.

katoni.dk-loadtid-pingdom-tools

Vi er tilfredse med hastigheden, da vi har mange billeder, der skal loades og en del SQL sætninger, der skal køres. Men vi forventer selvfølgelig, at vores sider bliver endnu hurtigere, efter vi får implementeret nogle af vores fremtidige tiltag.

De næste tiltag

Vi har forsøgt at finde en god CDN leverandør, der kan levere vores statiske indhold hurtigere, da vi af og til oplever, at vores løsning er lidt bagefter her.

Vi har afprøvet nogle stykker, men har ikke fundet en udbyder, der kunne gøre det bedre end det vi har nu til en overkommelig pris. Vi kunne selvfølgelig bare bruge 5.000 til 10.000 kr. pr. måned og tage nogle af de bedste i branchen, men det synes vi er lige i overkanten med den trafik, vi har lige nu.

Så næste test er en NGINX server med PageSpeed Modulet installeret, der kun indeholder vores statiske filer og er bygget til at levere dem hurtigt. Denne løsning er ikke aktiv endnu, men skulle gerne være tilgængelig inden måneden er omme.

Vores SQL Sætninger skal igen ses efter og vi vil prøve om vi kan undgå at bruge sorteringer, da det vil gøre dem endnu hurtigere. I øjeblikket eksperimenter vi med en omskrivning af vores primære SQL-sætning, den som trækker produkterne ud på baggrund af brugeres filtrering – dette eksperiment har indtil videre vist sig at være 3 gange hurtigere, så det bliver spændende at få den i produktion.

Udover at vi øger MySQL konfigurationen til at kunne bruge 4 GB RAM, og derved reducerer rigtig mange databaseopslag, har vi i sinde at implementere Medcached eller Redis, som skulle være endnu hurtigere i selve serverkoden, så vi helt kan undgå at sende forespørgsler til databasen. Det foregår ved, at man udtrækker et dataset fra databasen én gang, som herefter caches i serverens RAM med f.eks. en MD5 af SQL-sætningen. Derved kan man, inden man kører samme SQL-sætning igen, tjekke om et dataset allerede ligger i hukommelsen. Det er selvfølgelig kun muligt, hvis ens data ikke ændrer sig undervejs, hvilket ikke er tilfældet ved os – vi har fuld kontrol over, hvornår databasen opdateres og kan derved tømme hukommelsen for disse dataset.

Og så skal vi have testet Googles SPDY Protocol, der skulle være noget hurtigere end den gamle http protocol.

En kommentar til “Katoni.dk – ModPagespeed til Apache/NGINX hastighedsoptimering”

  1. Mega fed og dejlig nørdet artikel om PageSpeed. Tak for den!

    Når du finder den rette CDN, så må du endelig lave et indlæg om dit valg.

    Men jeg vil se videre på dit setup med subdomæner mv. til min ShopOrama shop

    Svar

Skriv en kommentar

Måske du også vil læse disse indlæg

Ja, jeg har også skrevet andre indlæg som måske kunne have din interesse