自己写的一个测试函数执行效率的单元(test on Delphi 7)

运用了一点技巧来实现对函数进行效率测试

使用方法:
uses
  Profile;
.......

function TForm1.Func1():string;
begin
    TFunctionTimeProfiler.ExecuteTest(ClassName, 'Func1'); //这里会创建一个接口实例,并开始测试; 此实例会自动释放并结束测试
    ....
end;

程序最后退出会自动生成一详细的报告, 根据报告, 就可以有针对性的优化代码, 提高程序的执行效率

希望大家看后能有一点收获



unit
  Profile ;

interface

uses
   SysUtils ,  Classes ,  Windows ,  Controls ,  Forms ;

{$IFNDEF TIMEPROFILE}
   {$DEFINE TIMEPROFILE}  { 需要测试时去掉"."即可 }
{$ENDIF}

type
   { 性能测试对象 }
   TTimeProfiler  =  class ( TObject )
   private
     {$IFDEF TIMEPROFILE}
     FItemList ,  FHistoryList :  TStringList ;
     FLogStream :  TFileStream ;
     FLevel :  Integer ;
     FTimeID :  Integer ;
     function  RecordToString ( ClassName ,  Method :  string ;  Tick :  Cardinal ):  string ;
     procedure  StringToRecord ( Str :  string ;  var  ClassName ,  Method :  string ;  var  Tick :  Cardinal );
     function  Ident :  string ;
     procedure  AddString ( s :  string ;  WithBreak :  Boolean  =  True );
     procedure  AddHR ( CH :  Char  =  '-' ;  Width :  Integer  =  80 );
     procedure  AddBR ;
     function  GetItem ( TestID :  Integer ):  string ;
     {$ENDIF}
   public
     constructor  Create ( LogName :  string );
     destructor  Destroy ;  override ;
     { 开始测试 }
     function  BeginTest ( ClassName :  string ;  Method :  string ):  Integer ;
     { 结束测试 }
     function  EndTest ( TestID :  Integer ):  Cardinal ;
   end ;

   { 性能测试接口,利用接口技术实现自动释放 }
   ITimeProfiler  =  interface
     [ '{4F54512F-728C-438E-9CAE-A10257A58439}' ]
   end ;

   { 函数性能测试对象 }
   TFunctionTimeProfiler  =  class ( TInterfacedObject ,  ITimeProfiler )
   private
     FTimeID :  Integer ;
   public
     constructor  Create ( TimeID :  Integer );
     destructor  Destroy ;  override ;
     class  function  ExecuteTest ( ClassName :  string ;  Method :  string ):  ITimeProfiler ;
   end ;

var
   TimeProfiler :  TTimeProfiler ;

implementation

function  iif ( const  Condition :  Boolean ;  const  IfTrue :  string ;  const  IfFalse :  string ):  string ;
begin
   if  Condition  then
     Result  :=  IfTrue
   else
     Result  :=  IfFalse ;
end ;

{ TTimeProfiler }

constructor  TTimeProfiler . Create ( LogName :  string );
begin
   {$IFDEF TIMEPROFILE}
   FTimeID  :=  0 ;
   FLevel  :=  0 ;
   FItemList  :=  TStringList . Create ;
   FHistoryList  :=  TStringList . Create ;
   LogName  :=  Trim ( LogName );
   if  FileExists ( LogName )  then
   begin
     FLogStream  :=  TFileStream . Create ( LogName ,  fmOpenWrite );
     FLogStream . Seek ( 0 ,  soFromEnd );
   end
   else
     FLogStream  :=  TFileStream . Create ( LogName ,  fmCreate );
   AddBR ;
   AddHR ;
   AddString ( Format ( ' 软件性能测试 - 测试时间:%s ' ,  [ DateTimeToStr ( Now )]));
   AddHR ;
   {$ENDIF}
end ;

destructor  TTimeProfiler . Destroy ;
{$IFDEF TIMEPROFILE}
var
   i :  Integer ;
   ClassName ,  Method :  string ;
   Tick :  Cardinal ;
{$ENDIF}
begin
   {$IFDEF TIMEPROFILE}
   { 保存综合测试结果 }
   if  FHistoryList . Count  >  0  then
   begin
     AddBR ;
     AddHR ( '*' );
     AddString ( ' 所有函数测试结果(按所花费时间排序) ' );
     AddHR ( '*' );
     FHistoryList . Sort ;
     for  i  :=  FHistoryList . Count  -  1  downto  0  do
     begin
       StringToRecord ( FHistoryList [ i ],  ClassName ,  Method ,  Tick );
       AddString ( ClassName  +  iif ( ClassName  <>  '' ,  '.' ,  '' )  +  Method  +  ' - Used Time: '  +  Format ( '%.3f' ,  [ Tick  /  1000 ])  +  ' sec.' );
     end ;
   end ;
   AddBR ;
   AddHR ;
   AddString ( Format ( ' 软件性能测试 - 测试结束,时间:%s ' ,  [ DateTimeToStr ( Now )]));
   AddHR ;
   if  Assigned ( FItemList )  then
     FreeAndNil ( FItemList );
   if  Assigned ( FHistoryList )  then
     FreeAndNil ( FHistoryList );
   if  Assigned ( FLogStream )  then
     FreeAndNil ( FLogStream );
   {$ENDIF}
   inherited  Destroy ;
end ;

function  TTimeProfiler . BeginTest ( ClassName ,  Method :  string ):  Integer ;
begin
   {$IFDEF TIMEPROFILE}
   Inc ( FTimeID );
   FItemList . AddObject ( RecordToString ( ClassName ,  Method ,  GetTickCount ),  Pointer ( FTimeID ));
   AddString ( Ident  +  ClassName  +  iif ( ClassName  <>  '' ,  '.' ,  '' )  +  Method  +  ' - Begin' );
   Inc ( FLevel );
   Result  :=  FTimeID ;
   {$ELSE}
   Result  :=  0 ;
   {$ENDIF}
end ;

function  TTimeProfiler . EndTest ( TestID :  Integer ):  Cardinal ;
{$IFDEF TIMEPROFILE}
var
   ClassName ,  Method ,  s :  string ;
   Tick :  Cardinal ;
{$ENDIF}
begin
   {$IFDEF TIMEPROFILE}
   s  :=  GetItem ( TestID );
   if  s  =  ''  then
     Exception . Create ( 'Cannot end the test '  +  IntToStr ( TestID )  +  '!' );
   StringToRecord ( s ,  ClassName ,  Method ,  Tick );
   Result  :=  GetTickCount  -  Tick ;
   FItemList . Delete ( FItemList . Count  -  1 );
   Dec ( FLevel );
   AddString ( Ident  +  ClassName  +  iif ( ClassName  <>  '' ,  '.' ,  '' )  +  Method  +  ' - End (Used Time: '  +  Format ( '%.3f' ,  [ Result  /  1000 ])  +  ' sec.)' );
   //if FLevel = 0 then //只保存第一级测试结果
     FHistoryList . Add ( RecordToString ( ClassName ,  Method ,  Result ));
   {$ELSE}
   Result  :=  0 ;
   {$ENDIF}
end ;

{$IFDEF TIMEPROFILE}
function  TTimeProfiler . RecordToString ( ClassName ,  Method :  string ;
   Tick :  Cardinal ):  string ;
begin
   Result  :=  Format ( '%-.8d|%s.%s' ,  [ Tick ,  ClassName ,  Method ]);
end ;

procedure  TTimeProfiler . StringToRecord ( Str :  string ;  var  ClassName ,
   Method :  string ;  var  Tick :  Cardinal );
begin
   Tick  :=  StrToIntDef ( GetShortHint ( Str ),  0 );
   Str  :=  StringReplace ( GetLongHint ( Str ),  '.' ,  '|' ,  [ rfReplaceAll ]);
   ClassName  :=  GetShortHint ( Str );
   Method  :=  GetLongHint ( Str );
end ;

procedure  TTimeProfiler . AddString ( s :  string ;  WithBreak :  Boolean );
begin
   if  Assigned ( FLogStream )  then
   begin
     if  WithBreak  then
       s  :=  s  +  #13#10 ;
     FLogStream . WriteBuffer ( Pointer ( s )^,  Length ( s ));
   end ;
end ;

function  TTimeProfiler . Ident :  string ;
begin
   Result  :=  StringOfChar ( ' ' ,  FLevel  *  4 );
end ;

procedure  TTimeProfiler . AddHR ;
begin
   AddString ( StringOfChar ( CH ,  Width ));
end ;

procedure  TTimeProfiler . AddBR ;
begin
   AddString ( #13#10 ,  False );
end ;

function  TTimeProfiler . GetItem ( TestID :  Integer ):  string ;
var
   i :  Integer ;
begin
   Result  :=  '' ;
   if  FItemList . Count  >  0  then
   begin
     {
    if TestID = -1 then
    begin
      Result := FItemList[FItemList.Count - 1];
      Exit;
    end;
    }
     for  i  :=  FItemList . Count  -  1  downto  0  do
       if  Integer ( FItemList . Objects [ i ])  =  TestID  then
       begin
         Result  :=  FItemList [ i ];
         Break ;
       end ;
   end ;
end ;
{$ENDIF}

{ TFunctionTimeProfiler }

constructor  TFunctionTimeProfiler . Create ( TimeID :  Integer );
begin
   FTimeID  :=  TimeID ;
end ;

destructor  TFunctionTimeProfiler . Destroy ;
begin
   TimeProfiler . EndTest ( FTimeID );
   inherited  Destroy ;
end ;

class  function  TFunctionTimeProfiler . ExecuteTest ( ClassName :  string ;
   Method :  string ):  ITimeProfiler ;
begin
   {$IFDEF TIMEPROFILE}
   Result  :=  TFunctionTimeProfiler . Create ( TimeProfiler . BeginTest ( ClassName ,  Method ));
   {$ELSE}
   Result  :=  nil ;
   {$ENDIF}
end ;

initialization
   if  not  Assigned ( TimeProfiler )  then
     TimeProfiler  :=  TTimeProfiler . Create ( ChangeFileExt ( Application . ExeName ,  '.Time.txt' ));

finalization
   if  Assigned ( TimeProfiler )  then
     FreeAndNil ( TimeProfiler );

end .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值