Çarşamba, Eylül 20, 2006

İki işlem arasında geçen süre

İki işlem arasında geçen yaklaşık süre için bu sayfadaki örnek kullanılabilir.
Ancak burada milisaniyeler(saliseler) bazında da olsa hata olabilir.
Sürenin doğruluğu sizin için çok önemli ise örneğin saliseler bazında, o zaman başka yönteme bakmanızı öneririm.
Bu güncede anlatacağım sanırım sizi ilgilendiriyor.

İki işlem arasında geçen süre genellikle GetTickCount ya da timeGetTime adlarıyla bilinen Windows API fonksiyonları tarafından ölçülür, ancak bu fonksiyonlar bir kaç milisaniyelik (salise) de olsa hata yapabilirler.
Onun yerine daha kesin sonuç veren QueryPerformansCounter Windows API fonksiyonunu kullanma taraftarıyım.
Ancak QueryPerformansCounter Windows API fonksiyonu QueryPerformansFrequency Windows API fonksiyonu ile birlikte kullanılır.
QueryPerformansFrequency : Her bir saniyede, bilgisayarın donanımındaki timer’ın artan değeridir yani frekansı da diyebiliriz. Bu fonksiyondan dönen değeri, baz olarak alacağız. (Her donanım desteklemeyebilir.)
QueryPerformansCounter : Sistem (Windows) başladığından beri geçen sürenin milisaniye cinsinden değerini de verir.
Yapılması gereken şey öncelikler, bilgisayarın donanımının frekansının bulunması, dönen değer 64-bit yani Int64 değerindedir.

var
  tmpFreq : Int64Rec;
  Freq : Cardinal;
....
....
  Freq := 0;
  if not QueryPerformanceFrequency(TLargeInteger(tmpFreq)) then
  begin
    ShowMessage('Donanım desteklemiyor');
    Exit;
  end;
  if tmpFreq.Lo = 0 then Exit;
  Freq := tmpFreq.Lo div 1000;

Burada frekansın ilk 32-bitlik değerin 0 olması işimize yaramaz, çünkü bu değeri 1000 sayısına böleceğiz. Yukardaki işlemi 1 kere kullanmak yeterlidir, çünkü bu donanımsal bir değerdir, hiçbir zaman değişmez.
Daha sonra işimizi asıl QueryPerformansCounter fonksiyonu çözecektir.
var
  counter : TLargeInteger;
  donen_ms : Cardinal;
....
....
  if Freq <> 0 then
  begin
    QueryPerformanceCounter(counter);
    donen_ms := counter div Freq;
  end;

Şimdi yukarıda anlattıklarımızı kod’a dökelim.

unit UntUtilities;

interface

function MSecEllapsed():Cardinal;

implementation

uses
  SysUtils, Windows;

var
  Freq : Cardinal;
  tmpFreq : Int64Rec;

function MSecEllapsed():Cardinal;
var
  counter : TLargeInteger;
begin
  if Freq <> 0 then
  begin
    QueryPerformanceCounter(counter);
    Result := counter div Freq;
  end
  else

    Result := GetTickCount;
end;

initialization
  Freq := 0;
  if not QueryPerformanceFrequency(TLargeInteger(tmpFreq)) then Exit;
  if tmpFreq.Lo = 0 then Exit;
  Freq := tmpFreq.Lo div 1000;
end.

Örnek kullanım:
....
....
uses
  Windows, //GetTickCount için
  UntUtilities, //MSecEllapsed
  MMSystem, //timeGetTime
  Dialogs; //ShowMessage
....
....
const
  SLP = 1024; //salise
var
  st, en : Cardinal;
begin
  st := timeGetTime();
  Sleep(SLP); //1024 salise bekleyelim
  en := timeGetTime();
  ShowMessage(Format('timeGetTime:%d', [en-st]));

  st := GetTickCount();
  Sleep(SLP); //1024 salise bekleyelim
  en := GetTickCount();
  ShowMessage(Format('GetTickCount:%d', [en-st]));

  st := MSecEllapsed();
  Sleep(SLP); //1024 salise bekleyelim
  en := MSecEllapsed();
  ShowMessage(Format('MSecEllapsed():%d', [en-st]));
end;


Kolay gelsin...
Yusuf ÇELİK

Hiç yorum yok: