Buenas
Seguro que en alguna ocasión hemos tenido que controlar el tiempo que tarda en realizarse algún trozo de código o proceso, y seguro que para ello se ha recurrido a la función Now (definida en la unidad SysUtils) o a la función del API de Windows GetTickCount. Otra opción es crearnos una unit que contenga la clase expuesta por Zarko en uno de sus artículos de delphi.about.com (ver How to Accurately Measure Elapsed Time Using High-Resolution Performance Counter).
Lo que quizás no sepamos es que, a partir de Delphi 2010, disponemos de la unit Diagnostics (System.Diagnostics para XE2 o superior por lo que será compatible para los dos frameworks, VCL y FMX). Esta unit básicamente contiene un record que describe la clase escrita por Zarko en su artículo anteriormente mencionado, incluso han conservado el mismo nombre de la clase (TStopwatch) y de varios de sus métodos. El funcionamiento también es casi igual, aquí un ejemplo:
uses System.Diagnostics; procedure TForm1.Button1Click(Sender: TObject); var sw: TStopWatch; i: Integer; begin sw := TStopwatch.StartNew; // inicializa, reset y start, toto en uno for i := 0 to 100000 do Application.ProcessMessages; sw.Stop; Caption := IntToStr(sw.ElapsedMilliseconds); end;
Este record (al igual que la clase de Zarko) se basa en el uso de las funciones del API de Windows QueryPerformanceFrequency la cual inicializará la propiedad Frequency (para plataforma MAC se establece una frecuencia de 100 nanosegundos) y QueryPerformanceCounter (para plataforma MAC se usa la función AbsoluteToNanoseconds).
Una vez parado el contador podemos acceder a varias de sus propiedades para obtener el tiempo transcurrido. Si queremos saber los milisegundos bastará con consultar la propiedad ElapsedMilliseconds la cual nos dará el resultado de los milisegundos transcurridos.
Otra propiedad que podemos consultar es Elapsed. Ésta es un TTimeSpan (definido en la unit TimeSpan o System.TimeSpan para XE2 o superior). Esta estructura tiene algunas propiedades que nos darán algo más de precisión que ElapsedMilliseconds llegando a los microsegundos. Para ello accederemos a su propiedad TotalMilliseconds que, al ser un Double, podremos obtener fielmente esos microsegundos.
Pero si lo que queremos es más precisión, gracias a la frecuencia (Frequency) y a la propiedad ElapsedTicks podremos llegar a nanosegundos con una sencilla división (ElapsedTicks / Frequency nos daría los segundos, sólo es cuestión de ir dividiendo por 1000 hasta llegar a la unidad deseada – segundo -> milisegundo -> microsegundo -> nanosegundo -).
Pues nada, ya conocemos una unidad más de Delphi 😉
Hasta la próxima
Nos leemos
I’d also mention that if someone want just to writeln elapsed time (TTimeSpan) he/she don’t even need to bother with milliseconds stuff. The easy way is explicit conversion to string, just
var
w: TStopWatch;
…
writeln(‘Elapsed: ‘, string(w.Elapsed));
That’s it. w.Elapsed will call Value.ToString and you get text.
Thanks DDev for this tip