//
{{Copyright(c)2016 Advanced Delphi Systems Richard Maley Advanced Delphi Systems 12613 Maidens Bower Drive Potomac, MD 20854 USA phone 301-840-1554 dickmaley@advdelphisys.com The code herein can be used or modified by anyone. Please retain references to Richard Maley at Advanced Delphi Systems. If you make improvements to the code please send your improvements to dickmaley@advdelphisys.com so that the entire Delphi community can benefit. All comments are welcome. } unit ads_TimingTester; (*UnitIndex Master Index Implementation Section Download Units
Description: ads_TimingTester.pas This unit contains the following routines.
Register TTimeTest_ads.GetStartTime TTimeTest_ads.Init TTimeTest_ads.Next TTimeTest_ads.SaveToFile TTimeTest_ads.SetActive TTimeTest_ads.SetDeltaTime TTimeTest_ads.SetEndTime TTimeTest_ads.SetFileName TTimeTest_ads.SetMaxLines TTimeTest_ads.SetOverWrite TTimeTest_ads.SetStartTime TTimeTest_ads.Start TTimeTest_ads.Stop_1 TTimeTest_ads.Stop_2 TTimeTest_ads.TimeDeltaInMSeconds TTimeTest_ads.TrimExcess TTimeTest_ads.UserName
*) interface Uses WinProcs, SysUtils, Classes; {Copyright(c)2016 Advanced Delphi Systems Richard Maley Advanced Delphi Systems 12613 Maidens Bower Drive Potomac, MD 20854 USA phone 301-840-1554 dickmaley@advdelphisys.com The code herein can be used or modified by anyone. Please retain references to Richard Maley at Advanced Delphi Systems. If you make improvements to the code please send your improvements to dickmaley@advdelphisys.com so that the entire Delphi community can benefit. All comments are welcome. } (* TTimeTest_ads Description: TTimeTest_ads will record timing segments in delphi code and rank longest to shortest. Log File: The timing results are saved in a log file called UserName.log (where UserName is the person's Windows Network Login ID). By default the file is put in the same directory where the executable is. The location and name of the log file can be changed by changing the filename property. Installation: This tester can be used in any delphi unit including a projects *.dpr file. Put the name of this unit in the uses clause of any unit you want to test times in. How to Use: Put TimeTest_ads.Start('Caption'); before the first block of code to be tested. Caption should be a unique identifer for a chunk of code. Put TimeTest_ads.Next('Caption'); before code that ends one timing event and immediately starts a new one. Put TimeTest_ads.Stop; anyplace that ends a timing event and a new one is not to be started. Disabling: If you wish to leave the lines of code mentioned above in your source code without degrading application performance at times when timing tests are not needed turn the component off by setting active to false. TimeTest_ads.Active := False; The following example shows how the tester can be used. Example Code: program MasterControl; uses ads_TimingTester, Forms, MasterControl_dm in 'MasterControl_dm.pas' {dtm_MasterControl: TDataModule}, MasterControl_g in 'MasterControl_g.pas', MasterControl_p in 'MasterControl_p.pas' {frm_MasterControl_Main}, Cmp_sec in '..\..\dcmp\4\ads\Cmp_Sec.pas'; {$R *.RES} begin TimeTest_ads.Start('BeforeInitialize'); Application.Initialize; TimeTest_ads.Next('BeforeDM'); Application.CreateForm(Tdtm_MasterControl, dtm_MasterControl); TimeTest_ads.Next('BeforeMain'); Application.CreateForm(Tfrm_MasterControl_Main, frm_MasterControl_Main); TimeTest_ads.Next('BeforeRun'); Application.Run; TimeTest_ads.Stop; end. Example Output: ads_TimingTester Results The left column ranks times from longest to shortest. Time are in milliseconds. DELTA ms START TIME END TIME CAPTION 00002360 980929031507p 980929031510p BeforeRun 00000500 980929031507p 980929031507p BeforeMain 00000050 980929031507p 980929031507p BeforeInitialize 00000000 980929031507p 980929031507p BeforeDM *) Type TTimeTest_ads = class(TComponent) Protected FActive : Boolean; FCaption : String; FDeltaTime : Double; FEndTime : TDateTime; FFileName : TFileName; FMaxLines : Integer; FOverWrite : Boolean; FStartTime : TDateTime; lstLog : TStringList; lstTemp : TStringList; StartNames : TStringList; StartTimes : TStringList; tmpFileName: String; Function UserName: string; Function GetStartTime(Caption : String): TDateTime; procedure SetActive(const Value: Boolean); procedure SetDeltaTime(const Value: Double); procedure SetEndTime(const Value: TDateTime); procedure SetFileName(const Value: TFileName); procedure SetMaxLines(const Value: Integer); procedure SetOverWrite(const Value: Boolean); procedure SetStartTime(const Value: TDateTime); procedure TrimExcess; Public constructor Create(AOwner: TComponent); Override; Destructor Destroy; Override; Function TimeDeltaInMSeconds(StartDate : TDateTime;EndDate : TDateTime): Double; Procedure Init; Procedure Next(Caption : String); Procedure SaveToFile; Procedure Start(Caption : String); Procedure Stop; Overload; Procedure Stop(Caption : String); Overload; property OverWrite : Boolean read FOverWrite write SetOverWrite; property Active : Boolean read FActive write SetActive; property StartTime : TDateTime read FStartTime write SetStartTime; property EndTime : TDateTime read FEndTime write SetEndTime; property DeltaTime : Double read FDeltaTime write SetDeltaTime; property MaxLines : Integer read FMaxLines write SetMaxLines; Published property FileName : TFileName read FFileName write SetFileName; End; Procedure Register; Var TimeTest_ads : TTimeTest_ads; implementation Constructor TTimeTest_ads.Create(AOwner: TComponent); Begin inherited Create(AOwner); OverWrite := False; tmpFileName := ExtractFilePath(ParamStr(0))+UserName+'.tmp'; If FileExists(tmpFileName) Then Deletefile(tmpFileName); FileName := ExtractFilePath(ParamStr(0))+UserName+'.tim'; Active := True; FMaxLines := 10000; FCaption := ''; StartTime := 0; EndTime := 0; DeltaTime := 0.00; lstLog := TStringList.Create(); lstTemp := TStringList.Create(); StartNames := TStringList.Create(); StartTimes := TStringList.Create(); lstLog .Clear; lstTemp .Clear; StartNames .Clear; StartTimes .Clear; End; Destructor TTimeTest_ads.Destroy; Begin SaveToFile; lstLog .Free; lstTemp .Free; StartNames .Free; StartTimes .Free; inherited destroy; End; //Unit Description UnitIndex Master Index
Function TTimeTest_ads.UserName: string; Var sgUserName : String; iwUserNameLen : DWord; Begin iwUserNameLen := 255; SetLength(sgUserName, iwUserNameLen); If GetUserName(PChar(sgUserName), iwUserNameLen) Then Result := Copy(sgUserName,1,iwUserNameLen - 1) Else Result := 'Unknown'; End; //Unit Description UnitIndex Master Index
Function TTimeTest_ads.TimeDeltaInMSeconds(StartDate, EndDate: TDateTime): Double; Var Hour, Min, Sec, MSec: Word; Delta: TDateTime; Begin Try Delta := EndDate - StartDate; DecodeTime(Delta, Hour, Min, Sec, MSec); Result := (((((Hour*60)+Min)*60)+Sec)*1000)+MSec; Except Result := 0; End; End; //Unit Description UnitIndex Master Index
Procedure TTimeTest_ads.SaveToFile; Var lstPrior : TStringlist; lstFinal : TStringlist; inCounter : Integer; Begin If Not Active Then Exit; lstPrior := TStringlist.Create(); lstFinal := TStringlist.Create(); Try If Not OverWrite Then Begin lstPrior.clear; If FileExists(FileName) Then Begin Try lstPrior.LoadFromFile(FileName); Except lstPrior.clear; End; End; End; If FileExists(tmpFileName) Then Begin lstTemp.LoadFromFile(tmpFileName); lstLog.SetText(PChar(lstTemp.Text+lstLog.Text)); lstTemp.Clear; DeleteFile(tmpFileName); End; lstLog.Sorted := True; lstFinal.Clear; lstFinal.Add('ads_TimingTester Results '+FormatDateTime('mm/dd/yy hh:nn:ss a/p',now())); lstFinal.Add(''); lstFinal.Add('The left column ranks times from longest to shortest.'); lstFinal.Add('Time are in milliseconds.'); lstFinal.Add(''); lstFinal.Add('DELTA ms START TIME END TIME CAPTION'); For inCounter := (lstLog.Count -1) DownTo 0 Do Begin lstFinal.Add(lstLog[inCounter]); End; If Not OverWrite Then Begin lstFinal.Append('____________________________________________'); lstFinal.Append(lstPrior.Text); End; Try If lstFinal.Count > MaxLines Then Begin For inCounter := (lstFinal.Count - 1) DownTo (MaxLines - 1) Do Begin lstFinal.Delete(inCounter); End; For inCounter := (lstFinal.Count - 1) DownTo 0 Do Begin If Not (lstFinal[inCounter] = '____________________________________________') Then Begin lstFinal.Delete(inCounter); End Else Begin Break; End; End; End; lstFinal.SaveToFile(FileName); Except End; Finally lstPrior.Free; lstFinal.Free; End; End; //Unit Description UnitIndex Master Index
Procedure TTimeTest_ads.Stop; Var sgTempFile : String; sgDelta : String; Begin If Not Active Then Exit; EndTime := now(); DeltaTime := TimeDeltaInMSeconds(StartTime, EndTime); sgDelta := FormatFloat('00000000',DeltaTime); If sgDelta <> '00000000' Then Begin If Not (Trim(FCaption) = '') Then Begin lstLog.Add( FormatFloat('00000000',DeltaTime) + ' ' + FormatDateTime('yymmddhhnnssa/p', StartTime)+ ' ' + FormatDateTime('yymmddhhnnssa/p', EndTime) + ' ' + FCaption); End; If lstLog.Count > 2 Then Begin sgTempFile := ''; If FileExists(tmpFileName) Then Begin lstTemp.LoadFromFile(tmpFileName); sgTempFile := lstTemp.Text; End; lstTemp.SetText(PChar(sgTempFile+lstLog.Text)); lstTemp.SaveToFile(tmpFileName); lstTemp.Clear; lstLog .Clear; End; End; Init; End; //Unit Description UnitIndex Master Index
Procedure TTimeTest_ads.Init; Begin FCaption := ''; StartTime := 0; EndTime := 0; DeltaTime := 0.00; End; //Unit Description UnitIndex Master Index
Procedure TTimeTest_ads.Start(Caption : String); Begin If Not Active Then Exit; FCaption := Caption; StartTime := now(); StartNames.Add(UpperCase(Caption)); StartTimes.Add(FormatFloat('#0.000000',StartTime)); If StartNames.Count > 1000 Then TrimExcess; End; //Unit Description UnitIndex Master Index
Procedure TTimeTest_ads.Next(Caption : String); Begin If Not Active Then Exit; Stop; Start(Caption); End; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.SetDeltaTime(const Value: Double); begin FDeltaTime := Value; end; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.SetEndTime(const Value: TDateTime); begin FEndTime := Value; end; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.SetFileName(const Value: TFileName); Var sgOldTemp : String; begin FFileName := Value; sgOldTemp := tmpFileName; tmpFileName:= Copy(FFileName,1,Length(FFileName)-3)+'tmp'; If Not (sgOldTemp = tmpFileName) Then Begin If FileExists(tmpFileName) Then Deletefile(tmpFileName); If FileExists(sgOldTemp) Then CopyFile(PChar(sgOldTemp),PChar(tmpFileName),False); If FileExists(sgOldTemp) Then Deletefile(sgOldTemp); End; end; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.SetStartTime(const Value: TDateTime); begin FStartTime := Value; end; //Unit Description UnitIndex Master Index
Procedure Register; Begin RegisterComponents('ads', [TTimeTest_ads]); End; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.SetActive(const Value: Boolean); begin FActive := Value; end; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.SetOverWrite(const Value: Boolean); begin FOverWrite := Value; end; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.SetMaxLines(const Value: Integer); begin FMaxLines := Value; end; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.Stop(Caption: String); Var dtStart : TDateTime; Begin If Not Active Then Exit; dtStart := GetStartTime(Caption); If dtStart <> 0 Then Begin StartTime := dtStart; FCaption := Caption; End; Stop; End; //Unit Description UnitIndex Master Index
function TTimeTest_ads.GetStartTime(Caption: String): TDateTime; Var inCounter : Integer; sgDt : String; inMax : Integer; inIndex : Integer; begin Result := 0; Try If Not Active Then Exit; Caption := UpperCase(Caption); inMax := StartNames.Count -1; inIndex := -1; For inCounter := inMax DownTo 0 Do Begin If StartNames[inCounter] <> Caption Then Continue; inIndex := inCounter; Break; End; If inIndex = -1 Then Exit; sgDt := StartTimes[inIndex]; StartNames.Delete(inIndex); StartTimes.Delete(inIndex); Result := StrToFloat(sgDt); Except Result := 0; End; End; //Unit Description UnitIndex Master Index
procedure TTimeTest_ads.TrimExcess; Var inCounter : Integer; inToTrim : Integer; begin If Not Active Then Exit; inToTrim := StartNames.Count - 1000; If inToTrim < 0 Then Exit; For inCounter := 1 To inToTrim Do Begin StartNames.Delete(0); StartTimes.Delete(0); End; end; Initialization TimeTest_ads := TTimeTest_ads.Create(nil); Finalization TimeTest_ads.Free; end. //