Pomiar czasu trwania procedury
fatalbomb
To już w zasadzie było opisane w artykule "Efektywne programowanie w Turbo Pascalu", ale warto to wyciągnąć do osobnego artykułu, bo nie każdemu chce się wczytywać w głąb tamtego.
Czas wykonywania procedury można określić mierząc go w ten sposób
var t: Longint absolute $0040:$006C;
tb, te:Longint;
...
tb := t;
Procedura_której_czas_mierzymy;
te := t;
writeln ('Procedura wykonywała się ',(te-tb)/100:0:2,' s');
Zmienna t jest przypisana do adresu 0040:006C, pod którym siedzi licznik zegara czasu rzeczywistego. Potem wykorzystujemy tą zmienną jak funkcję. Jest to dużo bardziej efektywne od konstrukcji w stylu:
uses Dos;
function t:Longint;
var H,M,S,St:Word;
GetTime (H,M,S,St);
t := H*360000 + M*6000 + S*100+ St;
end;
Ale wróćmy do pomiarów czasu. Licznik czasu rzeczywistego jest aktualizowany 18.2 raza na sekundę, co daje dokładność plus/minus 55 milisekund. O wiele za dużo jak na nasze potrzeby: naprawdę długa procedura wywołuje się tyle czasu (chyba że dobieramy się do dyskietki czy duuużego pliku). Rozwiązaniem jest wywołać taką procedurę kilka(set) razy i podzielić czas przez liczbę wywołań:
var t: Longint absolute $0040:$006C;
tb, te:Longint;
N:Word;
...
tb := t;
for N := 1 to 1000 do
Procedura_której_czas_mierzymy;
te := t;
{ Można zostawić wynik w sekundach... }
writeln ('Procedura wykonywała się ',((te-tb)/100)/1000:0:6,' s');
{ ...albo zamienić od razu na mikrosekundy }
writeln ('Procedura wykonywała się ',((te-tb)*10000)/1000,' us');
Ostateczna dokładność pomiaru to plus/minus 55/x milisekund, gdzie x to liczba wywołań procedury. W naszym przykładzie jest to 55 mikrosekund
jak już coś to +- 27,5sek... A poza tym zawsze można przerwanko przyspieszyć i będzie większa dokłąność
Ale to jakby średnią wtedy wyciągasz - chyba, że przyjmujesz identyczny czas wykonania kodu za każdym razem - wtedy się zgodzę.
Jeżeli z błędem 55 ms obliczamy czas 1000x większy, to dzieląc 55ms przez 1000 powtórzeń otrzymujemy dokładność do 55us. Jakbym wywołał milion razy, to błąd by wyniósł 55 nanosekund. Stosuję tą metodę i się sprawdza, faktycznie jest bardzo dokładna.
Korzystając z WinAPI można jeszcze skorzystać z funkcji GetTickCount o ile pamiętam