Guide:
Optimering av websider
Når man lager nettsider, ender man av og til opp med sider som tar lang tid å laste. Her er noen tips for hvordan du kan unngå slike ting.
Finn flaskehalsen
I de aller fleste tilfeller når man blir nødt til å optimere, er det en enkel del av skriptet som forårsaker problemene. Det er ikke alltid det er like lett å finne ut nøyaktig hvilken del av skriptet dette er, siden problemet gjerne kan være kamuflert i kode. En av prosessene hvor man prøver å finne flaskehalser kalles profilering.
Profilering går ut på å måle hvilken del av koden programmet tilbringer mest tid i. Programmeringsspråk har svært ofte innebygde profileringsverktøy, men det er ingen slike som blir levert sammen med PHP. Du kan derimot installere noen, slik som Xdebug. Mange foretrekker likevel å lage sitt eget system, og den enkleste måten å gjøre dette på i PHP er ved hjelp av microtime-funksjonen.
<?php
$start = ((float) array_sum(explode(" ",microtime())));
for ($i = 0; $i < 100000; $i++)
{
$sum += $i;
}
$end = ((float) array_sum(explode(" ",microtime())));
echo ($end-$start);
?>
Dette er den helt klart enkleste måten å gjøre det på selv.
Mer avanserte skript
Et annet alternativ er å bruke en større tidtakingsklasse, som det finnes mange forskjellige utgaver av. Det som følger er en kort beskrivelse av hvordan man bruker en klasse som undertegnede har skrevet selv. Ved å bruke dette objektet, kan du samle opp kjøretider fra flere gjennomkjøringer. Du kan også markere deler av koden din du vil ta tiden på, og objektet genererer statistikk til deg på slutten.
Vi har lagt ut kildekoden til denne måleklassen, og vil gi deg et enkelt eksempel på hvordan den brukes. Koden gjør en enkel addisjonsoperasjon en million ganger, i steg på hundretusen operasjoner. For hver hundretusende operasjon setter den et tidsmerke, som indikerer at en ny tidsperiode begynner.
<?php
require_once('timer.php');
$t = new Timer(true, true);
$z = 0;
for ($i = 0; $i < 10; $i++)
{
$t->mark($i+1);
for ($j = 0; $j < 100000; $j++)
{
$z++;
}
}
$t->stopClock();
$t->printStats();
?>
Etterhvert som du kjører dette skriptet flere ganger, vil statistikken inneholde mer og mer data, siden dataene blir mellomlagret i en cookie mellom hver kjøring. Når vi hadde kjørt dette skriptet 3 ganger, satt vi igjen med følgende tabell:
Simulation took a total of 0.9681 seconds.
| Set 1 | Set 2 | Set 3 | Average | |||||
|---|---|---|---|---|---|---|---|---|
| Mark | Start | Runtime | Start | Runtime | Start | Runtime | Start | Runtime |
| 1 | 0.0001 s | 0.0001 s | 0.0001 s | 0.0001 s | 0.0001 s | 0.0001 s | 0.0001 s | 0.0001 s |
| 2 | 0.0968 s | 0.0968 s | 0.0979 s | 0.0978 s | 0.0978 s | 0.0977 s | 0.0975 s | 0.0974 s |
| 3 | 0.1930 s | 0.0961 s | 0.1936 s | 0.0957 s | 0.1945 s | 0.0966 s | 0.1937 s | 0.0962 s |
| 4 | 0.2898 s | 0.0969 s | 0.2904 s | 0.0969 s | 0.2900 s | 0.0956 s | 0.2901 s | 0.0964 s |
| 5 | 0.3873 s | 0.0975 s | 0.3871 s | 0.0967 s | 0.3885 s | 0.0985 s | 0.3876 s | 0.0975 s |
| 6 | 0.4847 s | 0.0974 s | 0.4837 s | 0.0967 s | 0.4941 s | 0.1056 s | 0.4875 s | 0.0999 s |
| 7 | 0.5830 s | 0.0983 s | 0.5795 s | 0.0957 s | 0.5872 s | 0.0931 s | 0.5832 s | 0.0957 s |
| 8 | 0.6812 s | 0.0982 s | 0.6763 s | 0.0968 s | 0.6815 s | 0.0943 s | 0.6797 s | 0.0964 s |
| 9 | 0.7785 s | 0.0973 s | 0.7742 s | 0.0979 s | 0.7782 s | 0.0967 s | 0.7769 s | 0.0973 s |
| 10 | 0.8732 s | 0.0947 s | 0.8703 s | 0.0962 s | 0.8729 s | 0.0947 s | 0.8721 s | 0.0952 s |
| End | 0.9689 s | 0.0957 s | 0.9656 s | 0.0953 s | 0.9681 s | 0.0952 s | 0.9675 s | 0.0954 s |
Kolonnene Set 1, Set 2, Set 3 angir de tre forskjellige gangene vi kjørte skriptet. Start-kolonnen inneholder tidspunktet det gitte tidsmerket ble nådd, og Runtime angir når det ble forlatt. Det første tidsmerket vårt var fra vi startet klokken, til vi var inne i den ytterste loopen. Om vi studerer resultatene, ser vi at på denne serveren brukes det omtrent 100ms å legge sammen hundretusen tall, mens det brukes omtrent et sekund å gjøre en million tall. En relativt ubrukelig statistikk, synes du ikke?
NB: Siden vi har svært observante brukere på forumet, så vil noen helt sikkert oppdage at vi ikke ikke tar tiden på en million addisjonsoperasjoner i skriptet over, men faktisk minimum 2.000.020 addisjonsoperasjoner. Ser du hvorfor?
Rask oversikt over metoder
Det er gjerne kjekt å ha en rask oversikt over metodene du kan kalle på tidtakingsobjektet. Om du ser på kildekoden har klassen andre metoder i tillegg, men disse er laget kun for internt bruk.
-
Timer($fStartNow, $fUseCookies)
Timer($fStartNow)
Timer()
Oppretter objektet. Ved å sette$fStartNow = true, starter tidtakingen med en gang.$fUseCookiesangir om objektet skal ta vare på innsamlede data mellom kjøringer (objektet tar kun vare på 4 tidligere kjøringer). Begge variablene er satt tilfalsesom standard.
Merk at dersom du benytter deg av$fUseCookies, må denne kalles før skriptet har skrevet ut noe som helst. -
startClock()
Starter klokken med en gang, dersom den ikke allerede er startet. -
stopClock($fPrintStats)
stopClock()
Stopper klokken. Om du setter$fPrintStatstiltrueskrives statistikken ut med en gang, standard erfalse -
mark($sName)
mark()
Lager et tidsmerke.$sNameangir navnet på merket. Uten parameter brukes nummeret på tidsmerket som blir satt. -
printStats()
Skriver ut statistikk fra denne (og evt. tidligere) kjøringer. -
clearStatistics()
Fjerner eventuell statistikk som er lagret i cookies. Legg merke til at denne må kalles før skriptet har skrevet ut noe som helst.