EpikTimer: Difference between revisions
m (Fixed syntax highlighting) |
|||
(23 intermediate revisions by 8 users not shown) | |||
Line 1: | Line 1: | ||
{{EpikTimer}} | |||
=== About === | === About === | ||
EpikTimer is a programmer's stopwatch that is capable of measuring very short events with traceably high precision over long periods of time. It's simple to use, consumes virtually no CPU and requires only 25 bytes of ram to implement a timer instance. The component provides a single internal timer... but unlimited numbers can be declared externally and linked to a single EpikTimer component on the form. | EpikTimer is a programmer's stopwatch that is capable of measuring very short events with traceably high precision over long periods of time. It's simple to use, consumes virtually no CPU and requires only 25 bytes of ram to implement a timer instance. The component provides a single internal timer... but unlimited numbers can be declared externally and linked to a single EpikTimer component on the form. | ||
Line 8: | Line 10: | ||
=== Author === | === Author === | ||
[[User:VlxAdmin|Tom Lisjac]] | [[User:VlxAdmin|Tom Lisjac]] | ||
=== License === | === License === | ||
Line 17: | Line 15: | ||
=== Download === | === Download === | ||
The | The '''source code''' can be downloaded from the Git repository as follows: | ||
git clone https://github.com/graemeg/epiktimer.git | |||
If you don't want to install a Git client, Github also allows you to download the latest code as a ZIP archive. Simply go to the [https://github.com/graemeg/epiktimer Github EpikTimer] url and click the "Download ZIP" button on the right. | |||
Status | All '''tagged releases''' can be downloaded in .zip or .tar.gz format by going to this [https://github.com/graemeg/epiktimer/releases Github Releases] url and select the zip or tar.gz link for whichever release you want to download. | ||
===Project Status=== | |||
* Production/Stable | |||
=== Change Log === | === Change Log === | ||
Line 45: | Line 50: | ||
# Some changes in timeval | # Some changes in timeval | ||
# Tested on AMD64 (linux) | # Tested on AMD64 (linux) | ||
For any later changes, please see the Git commit log. | |||
=== Dependencies / System Requirements === | === Dependencies / System Requirements === | ||
Line 52: | Line 59: | ||
Tested on: | Tested on: | ||
* Pentium IV 3, | * Pentium IV 3,2Ghz on Windows and Linux with great precision (~ 3,220,000,000 ticks per second) | ||
* Pentium 233Mhz with Damn Small Linux. Works great with hardware clock. | * Pentium 233Mhz with Damn Small Linux. Works great with hardware clock. | ||
* Mobile AMD 64 Athlon 3200+ on Windows XP Home (32 bit), Lazarus 9.13 | * Mobile AMD 64 Athlon 3200+ on Windows XP Home (32 bit), Lazarus 9.13 | ||
* AMD 64 CPU, running 64 bit version of Ubuntu Linux, Lazarus 9.18. | * AMD 64 CPU, running 64 bit version of Ubuntu Linux, Lazarus 9.18. | ||
* Intel i7-3770K, running 64-bit version of FreeBSD 9.1, using FPC 2.6.2 | |||
* ARM CPU using Raspberry Pi and FPC 2.6.2 | |||
=== Installation in Lazarus IDE === | |||
* In Components/Open Package File, open etpackage.lpk | |||
=== Installation === | * Compile the package and close the package dialog | ||
* In Components/Open Package File, open etpackage.lpk. | * In Components -> Open Package File, open the etpackage_dsgn.lpk | ||
* Compile the | * Compile the package. | ||
* Install and let Lazarus rebuild | * Click the Install button and let Lazarus rebuild | ||
* Component will be in the System Palette (stopwatch-ruler icon) | * Component will be in the System Palette (stopwatch-ruler icon) | ||
Line 69: | Line 78: | ||
'''If the timer is named ET''' | '''If the timer is named ET''' | ||
<syntaxhighlight lang="pascal"> | |||
uses epiktimer; | |||
var | |||
ET: TEpikTimer; | |||
procedure InitTimer; | |||
begin | |||
ET := TEpikTimer.Create(Application); | |||
end; | |||
procedure InstrumentedCall; | |||
Begin | |||
ET.Clear; // optional... timer is cleared at creation | |||
ET.Start; | |||
ExecuteFirstTimedSection; | |||
ET.Stop; // the timer is actually paused and can be restarted later | |||
TimedSection1:=ET.Elapsed; // store the elapsed in a global | |||
MakeAnUntimedOverheadCall; // not counted in the timer | |||
ET.Start; //resume the timer... continue accumulating ticks | |||
CallTimedSection2; | |||
TimedSection2:=ET.Elapsed; //timer keeps running... we've just sample it. | |||
CallTimedSection3; | |||
CallSomethingElse; | |||
TimedSection3:=ET.Elapsed; //keep counting... tap the elapsed | |||
CallTimedSection4; | |||
TimedSection4:=ET.Elapsed; //keep counting... tap the elapsed | |||
ET.clear // done... timer is stopped and zeroed | |||
end;</syntaxhighlight> | |||
You can also create any number of timers from a single component on the form by declaring a TimerData record and passing it as a parameter to start, stop, elapsed and clear using the overloaded methods in the component. An example would be: | You can also create any number of timers from a single component on the form by declaring a TimerData record and passing it as a parameter to start, stop, elapsed and clear using the overloaded methods in the component. An example would be: | ||
<syntaxhighlight lang="pascal"> | |||
Function TimedExecution: Extended; | |||
Var | |||
DiskAccessTime:TimerData; | |||
Begin | |||
ET.Clear(DiskAccessTimer); // Declared timers *must* be cleared before use. | |||
ET.Start(DiskAccessTimer); | |||
ExecuteTheTimedSection; | |||
Result:=ET.Elapsed(DiskAccessTimer); // the timer keeps running... | |||
etc...</syntaxhighlight> | |||
One particular use for EpikTimer is checking | One particular use for EpikTimer is checking if a given amount of time has elapsed before continuing with a task or to another iteration of the same task. | ||
< | <syntaxhighlight lang="pascal"> | ||
DelayInSeconds := 8.5; // or any value | |||
OldTime := ET.Elapsed; | |||
while ((ET.Elapsed - OldTime) < DelayInSeconds) do | |||
begin | |||
ET.SystemSleep(10); | |||
end; | |||
// DelayInSeconds has elapsed and now you can continue executing the code</syntaxhighlight> | |||
</ | |||
See etdemo.pas for additional examples of component usage | See etdemo.pas for additional examples of component usage | ||
==== EpikTimer as a profiler ==== | |||
EpikTimer can be used to profile the speed of procedures: | |||
<syntaxhighlight lang="pascal"> | |||
uses | |||
{$ifdef PROFILING}epiktimer,{$endif} | |||
... | |||
type | |||
TMyClass = class | |||
private | |||
{$ifdef PROFILING} | |||
profiler: Tepiktimer; | |||
{$endif} | |||
... | |||
end; | |||
implementation | |||
constructor TMyClass.Create(AOwner: TComponent); | |||
begin | |||
inherited Create(AOwner); | |||
... | |||
{$ifdef CARDROOM_PROFILING} | |||
profiler := TEpikTimer.Create(Self) | |||
{$endif} | |||
end; | |||
procedure TMyClass.MethodToBeProfiled; | |||
begin | |||
{$ifdef PROFILING} | |||
profiler.Clear; | |||
profiler.Start; | |||
{$endif} | |||
// do stuff | |||
{$ifdef PROFILING} | |||
OPDebugLn('TMyClass.MethodToBeProfiled ' + FloatToStr(profiler.Elapsed)); | |||
{$endif} | |||
end; | |||
</syntaxhighlight> | |||
=== The ETDemo Application === | === The ETDemo Application === | ||
Line 126: | Line 190: | ||
* run | * run | ||
=== | === Console application === | ||
If you don't have an "Application" object instance as above, simply create the EpikTimer instance as follows. It must be manually freed when you are all done with it: | |||
ET := TEpikTimer.Create(nil) | |||
... your code here ... | |||
ET.Free; | |||
=== See also === | |||
* [[doc:fcl/fptimer/index.html|FPTimer included with FPC/Lazarus]] | |||
* [[Yet another Running Timer]] | |||
[[Category:Components]] |
Latest revision as of 12:55, 9 August 2019
│
Deutsch (de) │
English (en) │
français (fr) │
русский (ru) │
About
EpikTimer is a programmer's stopwatch that is capable of measuring very short events with traceably high precision over long periods of time. It's simple to use, consumes virtually no CPU and requires only 25 bytes of ram to implement a timer instance. The component provides a single internal timer... but unlimited numbers can be declared externally and linked to a single EpikTimer component on the form.
The download contains the component, an installation package and a demo application, that illustrates the features of the component along with some instrumentation for evaluating the clock sources on a given system.
This component was designed for cross-platform applications and was written specifically for the Lazarus IDE and Free Pascal Compiler and includes a demo application.
Author
License
LGPL (please contact the author if the LGPL doesn't work with your project licensing)
Download
The source code can be downloaded from the Git repository as follows:
git clone https://github.com/graemeg/epiktimer.git
If you don't want to install a Git client, Github also allows you to download the latest code as a ZIP archive. Simply go to the Github EpikTimer url and click the "Download ZIP" button on the right.
All tagged releases can be downloaded in .zip or .tar.gz format by going to this Github Releases url and select the zip or tar.gz link for whichever release you want to download.
Project Status
- Production/Stable
Change Log
- Initially written on 24-06-2003 TL
- Pre-release 30-06-2003 TL - Needs testing on the BSD's and Win32
- Version 0.1 1-7-2003 TL
- initial beta release
- Version 0.2 3-7-2003 TL
- Revised logic around hardware detection to prevent executing extended instructions if the HasCapabilityData call returns false.
- Removed exposed low level diagnositic functions from unit interface.
- Revised demo.
- Version 0.3 15-11-2005
- Updated 0.2 version to make it compile on the latest Lazarus (0.9.10).
- Added LCL to the required packages.
- Changed mode to Delphi in order to compile.
- Changed windows timebase to use QueryPerformanceCounter, because has a much greater precision then GetSystemTime.
- Added changes to ensure the component compiles on Delphi 7.0
- Made tests on Windows and Linux
- Small changes to the demo to make it compile
- Version 1.0 06-10-2006
- Changes for 64 bits operation
- Added units BaseUnix, Unix and UnixUtil, removed oldlinux (obsolete)
- Gettimeofday -> fpGettimeofday
- Changed systemsleep for 64 bits systems
- Some changes in timeval
- Tested on AMD64 (linux)
For any later changes, please see the Git commit log.
Dependencies / System Requirements
- Nanosecond resolution is supported on Intel Pentium versions with a Timestamp Counter.
- Microsecond system clock is the default timebase.
Tested on:
- Pentium IV 3,2Ghz on Windows and Linux with great precision (~ 3,220,000,000 ticks per second)
- Pentium 233Mhz with Damn Small Linux. Works great with hardware clock.
- Mobile AMD 64 Athlon 3200+ on Windows XP Home (32 bit), Lazarus 9.13
- AMD 64 CPU, running 64 bit version of Ubuntu Linux, Lazarus 9.18.
- Intel i7-3770K, running 64-bit version of FreeBSD 9.1, using FPC 2.6.2
- ARM CPU using Raspberry Pi and FPC 2.6.2
Installation in Lazarus IDE
- In Components/Open Package File, open etpackage.lpk
- Compile the package and close the package dialog
- In Components -> Open Package File, open the etpackage_dsgn.lpk
- Compile the package.
- Click the Install button and let Lazarus rebuild
- Component will be in the System Palette (stopwatch-ruler icon)
Usage
Drop the component on a form. The component contains a single timer instance and parameterless calls to start, stop, elapsed and clear will implicitly reference it.
If the timer is named ET
uses epiktimer;
var
ET: TEpikTimer;
procedure InitTimer;
begin
ET := TEpikTimer.Create(Application);
end;
procedure InstrumentedCall;
Begin
ET.Clear; // optional... timer is cleared at creation
ET.Start;
ExecuteFirstTimedSection;
ET.Stop; // the timer is actually paused and can be restarted later
TimedSection1:=ET.Elapsed; // store the elapsed in a global
MakeAnUntimedOverheadCall; // not counted in the timer
ET.Start; //resume the timer... continue accumulating ticks
CallTimedSection2;
TimedSection2:=ET.Elapsed; //timer keeps running... we've just sample it.
CallTimedSection3;
CallSomethingElse;
TimedSection3:=ET.Elapsed; //keep counting... tap the elapsed
CallTimedSection4;
TimedSection4:=ET.Elapsed; //keep counting... tap the elapsed
ET.clear // done... timer is stopped and zeroed
end;
You can also create any number of timers from a single component on the form by declaring a TimerData record and passing it as a parameter to start, stop, elapsed and clear using the overloaded methods in the component. An example would be:
Function TimedExecution: Extended;
Var
DiskAccessTime:TimerData;
Begin
ET.Clear(DiskAccessTimer); // Declared timers *must* be cleared before use.
ET.Start(DiskAccessTimer);
ExecuteTheTimedSection;
Result:=ET.Elapsed(DiskAccessTimer); // the timer keeps running...
etc...
One particular use for EpikTimer is checking if a given amount of time has elapsed before continuing with a task or to another iteration of the same task.
DelayInSeconds := 8.5; // or any value
OldTime := ET.Elapsed;
while ((ET.Elapsed - OldTime) < DelayInSeconds) do
begin
ET.SystemSleep(10);
end;
// DelayInSeconds has elapsed and now you can continue executing the code
See etdemo.pas for additional examples of component usage
EpikTimer as a profiler
EpikTimer can be used to profile the speed of procedures:
uses
{$ifdef PROFILING}epiktimer,{$endif}
...
type
TMyClass = class
private
{$ifdef PROFILING}
profiler: Tepiktimer;
{$endif}
...
end;
implementation
constructor TMyClass.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
...
{$ifdef CARDROOM_PROFILING}
profiler := TEpikTimer.Create(Self)
{$endif}
end;
procedure TMyClass.MethodToBeProfiled;
begin
{$ifdef PROFILING}
profiler.Clear;
profiler.Start;
{$endif}
// do stuff
{$ifdef PROFILING}
OPDebugLn('TMyClass.MethodToBeProfiled ' + FloatToStr(profiler.Elapsed));
{$endif}
end;
The ETDemo Application
The ETDemo application does not require EpikTimer to be installed in order to compile and operate. I never liked having to install a palette full of components only to find out that I didn't like any of them! :)
Installation
- Open etdemo.lpi
- compile
- run
Console application
If you don't have an "Application" object instance as above, simply create the EpikTimer instance as follows. It must be manually freed when you are all done with it:
ET := TEpikTimer.Create(nil) ... your code here ... ET.Free;