Klassikalised vead koodi kiiruse mõõtmisel

09.09.2010  |  Gunnar

Keeruline juttKlassikalised vead koodi kiiruse mõõtmisel on vist aegumatud. Neid tehti eile, tehakse täna ja tehakse kindlasti ka homme. Et meie siin pisikeses Eestis teistest tublimad progejad saaks olla, siis võtan tagataskust välja mõned õpetussõnad, kuidas oma koodi pädevalt mõõta.

Et see blogi on konstruktiivne infokanal, siis annan muidugi näited ja lahendused ka iga punkti juurde, kuhu vaja. Esimesele ei anna, sest rippnimistust õige elemendi valimine ei tohiks seda blogi lugeval progejal üle jõu käia. :)

Debug konfiguratsiooni kasutamine

Silumisinfot sisaldav kood ei ole nii kiire, kui see, mis seda ei sisalda. Erinevad osad täidetavast koodist sisaldavad silumisinfot erineval määral ja see võib anda mõningatel juhtudel täiesti vale pildi sellest, mis täidetava koodi sisemuses toimub.

Release konfiguratsiooni kasutades saame kompilaatori poolt optimeeritud koodi, mis on kiireim, mida see pakkuda suudab (käesolevas katses oli kiiruste vahe debug ja release konfiguratsioonide vahel orienteeruvalt 4x).

Aega mõõdetakse kella pealt

Paljud mõõtjad ei tea, et kahe DateTime.Now võrdlemisel saadakse tulemuseks aeg, mille sisse läheb ka kõik muu tegevus, mida süsteem teeb.

Stopwatch klassi kasutades saame aga selle aja, mis uuritava koodi täitmiseks tegelikult kulus. See tähendab seda, et kui käesolev thread opsüsteemist tulenevalt vahepeal teiste threadide taga ootab, mille kord on tegutseda, siis sellised viivitused Stopwatchi aegades ei sisaldu.

Vale:

var start = DateTime.Now;

// jooksuta mõõdetavat koodi

var finish = DateTime.Now;

Console.WriteLine("Result: " + (finish - start));

Õige:

var watch = new Stopwatch();

watch.Start();

// jooksuta mõõdetavat koodi

watch.Stop();

Console.WriteLine("Result: " + watch.ElapsedMilliseconds);

Mõõdetakse liiga paljusid tegevusi

Päris palju hakkab silma ka selliseid ämbreid, kus stopper käivitatakse kusagil suvalises kohas, mitte vahetult enne mõõdetavaid koodiridu. Sama kehtib stopperi peatamise kohta. Selle tulemusena võib mõni mõõtmisele tegelikult mittekuuluv koodirida lisada omalt poolt lõplikusse tulemusse päris väärika panuse.

Täpsemate ja puhtamate tulemuste saamiseks soovitab stopperi käima lüüa rida enne mõõdetavat koodi. Ja kinni löö see loomulikult esimese asjana peale mõõdetavat koodi. Siis on kindel (või peaaegu kindel), et mõõtmised ei sisalda liigset müra.

Lülita diagnostika mõõtmise ajaks välja

Igasugune diagnostika näiteks konsoolile või debug aknasse või logidesse kirjutamise näol lülita mõõtmise ajaks välja. Muidu sisaldavad su mõõtmised ka seda aega, mis kulus kirjutamisele. Failide korral võib mängu tulla näiteks kõvaketta koormus ja see omakorda võib tulemusi oluliselt moonutada.

Selline asi on ei-ei-ei-ei-ei!

foreach(var customer in list)
{
    Logger.Write("Processing customer " + customer.Name);

    // tee midagi
}

Mõõda mitu korda

Kui mõõtmiseks mõeldud kood hästi organiseerida, siis pole seda keerukas tsüklis jooksutada. Tihti seda ei tehta ja nii leidub netis teinekord päris veidrad mõõtmistulemusi, kus koostöös eeltoodud vigadega saadakse ebapädevad tulemused.

Mõõda 10 korda või 100 korda või miljon korda ja arvuti ajakulude keskmine. Mõõtmiskordade arv vali selline, et kordi saaks piisav arv antud mõõtmise kohta ja mõõtmise järel ei pea liiga pikalt ootama.

Kokkuvõtteks

Eeltoodud vigade vältimisel saame koodi kiiruse ja jõudluse mõõtmisel oluliselt täpsemad tulemused. Kindlasti soovitan ma mõõtmisi läbi viia hoolikalt, sest iga lohakusviga võib meid viia valede tulemusteni ja sealt valede järeldusteni. Valed järeldused viivad meid omakorda eksiarvamusteni ja mitte just eriti jõudsalt töötava koodini. Hoolikad mõõtmised aga annavad meile väga kasulikku infot ja õpetavad meie käes olevaid vahendeid paremini tundma.

Kommenteeri

sulge
Saada link e-postiga

© DT 2012 | Creative Commons Attribution-Noncommercial 3.0 License | WordPress