Efectuar un cronometraje preciso

2762 vistas

Para realizar un cronometraje preciso, tendremos que usar las funciones de contador de altas prestaciones (CAP) del API Win32.
Entre otras tenemos las funciones QueryPerformanceFrequency y QueryPerformanceCounter de la unidad Windows
La primera devuelve la frecuencia (en hercios) el contador HP de la máquina y la segunda devuelve el valor corriente de un contador libre. La resolución suele ser del orden de 1 nanosegundo.

Declaramos estas variables:



delphi
  1. Var
  2.   FFrequency    : Int64    ;    // frecuencia del contador de altas prestaciones.
  3.   FStart, FStop : Int64    ;    // valor del contador al inicio y fin del cronometraje.
  4.   FElapsed      : Extended ; 



Veamos cómo hacer el cronometraje:



delphi
  1. // inicialización del contador de altas prestaciones y inicio del cronometraje
  2. if not QueryPerformanceFrequency(FFrequency) then
  3.   raise Exception.Create('no hay contador de altas prestaciones.');
  4. QueryPerformanceCounter(FStart);
  5.  
  6. // Aquà va la operación a cronometrar o una llamada a la función a cronometrar.
  7.  
  8. // fin del cronometraje, conversión del tiempo en segundos.
  9. QueryPerformanceCounter(FStop);
  10. FElapsed := (FStop - FStart) / FFrequency;



La resolución de este contador es en general muy elevada: no es de extrañar que sea la frecuencia del ordenador la que sirva de base. Sobre un sistema dado, ésta no cambia nunca, pero ésta puede cambiar de un sistema a otro: por esto es imprescindible recuperar siempre la frecuencia para una llamada al sistema. Esta llamada sólo puede realizarse una vez en el programa. No obstante, hay algunos ordenadores que no tienen contador: por ésto es necesario verificar la devolición de la función QueryPerformanceFrequency.

Si la versión de Delphi que usamos no tiene declaradas estas funciones, tendremos que hacerlo nosotros mismos:



delphi
  1. Uses Windows ;
  2.  
  3. // requiere Delphi 4 o superior
  4. function QueryPerformanceCounter(var lpPerformanceCount: TLargeInteger):
  5. BOOL; stdcall; external kernel32 name 'QueryPerformanceCounter';
  6. function QueryPerformanceFrequency(var lpFrequency: TLargeInteger): BOOL;
  7. stdcall; external kernel32 name 'QueryPerformanceFrequency';