当前位置: 首页 > 编程日记 > 正文

自己写的一个测试函数执行效率的单元(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.

转载于:https://www.cnblogs.com/Icebird/archive/2004/11/04/TimeProfiler.html

相关文章:

datatable自动增加序号

{"targets": [0],"visible": true,"render": function (data, type, full, meta) {var id full.id;if (id) {return meta.row 1 meta.settings._iDisplayStart;} else {return ;}} },此方法有点小bug,推荐用下面的方法。 var table $(#myTabl…

CSS之布局(轮廓和圆角)

轮廓和圆角&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>轮廓和圆角</title><style>.box1{width: 200px;height: 200px;background-color: #BBFFAA;/*box-shadow用来设置元素的的阴影效果&…

Idea项目遇到的错误整理

解决方案 1.Maven 加入新的子模块module, 重新编译报错&#xff1a;找不到类/符号/程序包 需要清空Idea缓存&#xff0c;重新编译 File -> Invalidate Cahes... 转载于:https://www.cnblogs.com/atongmumu/p/7027050.html

对不起,我爱你

在学校上传了一部“对不起&#xff0c;我爱你”&#xff0c;据说很多人都喜欢看&#xff0c;对我 而言没有时间去看了&#xff0c;不过原声大碟倒是常常放到我的“Beep-media-player”里边&#xff0c;大四了&#xff0c;也常常觉得时间的珍贵&#xff0c;许多事情仿佛也懂了许…

流水账,从我开始接触计算机时写起

我第一次接触计算机是在读初二的时候&#xff0c;每周有一节微机课&#xff0c;记得那时大家都挺喜欢上这门课的&#xff0c;一到上课时间就往机房冲&#xff0c;生怕自己去晚了占不了机子&#xff0c;我也是懵懵懂懂的在老师的指导下&#xff0c;在一台黑白屏的电脑上学会了打…

装饰模式(Decorator)

1、概念 装饰模式动态地给一个对象添加一些额外的职责。就扩展功能而言&#xff0c;它比生成子类方式更为灵活&#xff0c;属于结构性模式一种。 2、模式结构 抽象组件角色(Component)&#xff1a;定义一个对象接口&#xff0c;以规范准备接受附加责任的对象&#xff0c;即可以…

css 背景样式学习

背景样式主要有5个属性&#xff1a; 1. background-color 背景颜色 2.background-img 背景图像 3.background-repeat 背景图像如何重复(no-repeat repeat repeat-x repeat-y inherit) 4.background-position 定位背景图像位置(top right bottom left center) 5.background-at…

CSS之定位(定位/相对定位)

定位/相对定位&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>定位/相对定位</title><style>body{font-size: 60px;}.box1{width: 200px;height: 200px;background-color: #bfa;}.box2{width:…

GARFIELD@01-24-2005

the kickoff of not being bored 转载于:https://www.cnblogs.com/rexhost/archive/2005/01/24/96477.html

(To Me Just)c#中的WebBrowser类的使用注意事项!

Visual C# 打造 “浏览器” try { if(tabControl.SelectedIndex 0) { axWebBrowser1.ExecWB(SHDocVw.OLECMDID.OLECMDID_SAVEAS, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT); } else if(tabControl.SelectedIndex 1) { …

CSS之定位(绝对定位)

绝对定位&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>绝对定位</title><style>body{font-size: 60px;position: relative;}.box1{width: 200px;height: 200px;background-color: #bfa;}.bo…

python pexpect包的一些用法

转自&#xff1a;https://www.jianshu.com/p/cfd163200d12 mark一下&#xff0c;原文中写的挺详细 转载于:https://www.cnblogs.com/renxchen/p/9935888.html

编译工具 之 ant

一、概述需要设置的环境变量&#xff1a;JAVA_HOME"D:\JDK",ANT_HOME"D:\ant",PATH".,%JAVA_HOME%\bin,%ANT_HOME%bin"运行&#xff1a;ant -buildfile test.xml -Dbuildbuild/classes dist&#xff08;含义为&#xff1a;执行test.xml的编译脚本…

微酷WeiKuCMS现赠送高速开发系统软件。公司、程序猿的福音呀!

我国电子商务面临的问题。淘宝退出百度无疑是一个遗憾。当在网上购物时。用户面临的一个非常大的问题就是怎样在众多的站点找到自己想要的物品。并以最低的价格买到。自从淘宝退出百度。建立自己的搜索引擎后。广大消费者再也不能再百度里面直接搜索有关淘宝的商品了&#xff0…

网友为对百合所唱的最后的挽歌!(节选)

dudu&#xff0c;不要删好吗&#xff0c;太郁闷了&#xff0c;太郁闷了&#xff0c;太郁闷了 sigh, 如果真的3.20日是末期的话&#xff0c;我所承诺的开源&#xff0c;只不过是一个玩笑罢了 参见&#xff1a;http://bbs.nju.edu.cn/blogall 网友为对百合所唱的最后的挽歌&#…

人工智能入门(二):语音识别基本模型

spectral analysis和formants&#xff0c;倒频谱&#xff0c;mel谱等feature有关&#xff1b; training和recognition涉及到&#xff1a;基础的&#xff08;DWT&#xff0c;HMM&#xff0c;Viterbi等&#xff09;&#xff1b;高阶的&#xff08;deep learning等&#xff09;。…

也谈文件夹同步

前言 1 同步分为文件级别&#xff0c;和块级别。rsync是块级别。 2 如果是基于微软文件共享或samba协议&#xff0c;用robocopy.exe即可文件级别的同步。 3 通过任务计划&#xff0c;实现自动&#xff0c;定时同步。 4 如果是ftp&#xff0c;sftp&#xff0c;用powershellwinsc…

几则与西门子相关的消息

西门子称手机部门前途未定 力推WiMAX系统 http://www.sina.com.cn 2005年02月15日 12:11 新浪科技 新浪科技讯 美国当地时间2月14日(北京时间2月15日)消息&#xff0c;在日前于法国戛那举行的“3GSM世界大会”上&#xff0c;西门子手机部门将何去何从再次被业界所关注。但西门…

CSS之定位(固定定位)

固定定位&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>固定定位</title><style>body{font-size: 60px;height: 2000px;}.box1{width: 200px;height: 200px;background-color: #bfa;}.box2{w…

在页面中控制媒体流的起播点和播放长度

近来在一个web项目中&#xff0c;客户提出需要在试听的音频文件中&#xff0c;输入开始时间和结束时间&#xff0c;然后从开始时间播放&#xff0c;到结束时间停止。在google中搜索了几次&#xff0c;都找不到相关的文档&#xff0c;只有自己进行研究了。刚开始的时候&#xff…

CSS之定位(粘滞定位)

粘滞定位&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>粘滞定位</title><style>body{height: 3000px;}/*粘滞定位-当元素的position属性值设置为sticky时开启元素的粘滞定位-粘滞定位和相对定…

链表的经常使用操作

链表的经常使用操作 posted on 2017-06-18 10:38 mthoutai 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/mthoutai/p/7043708.html

从零打造在线网盘系统之Hibernate框架起步

欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2SpringHibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重地阐述SSH三个框架的基础知识,第四部分将会进入项目实战,如果您已经对SSH框架有所掌握,那么可以直接浏览…

Mr Big [To be with you]

很惊喜&#xff0c;在musictea上看到了Mr Big的专辑Lean Into It&#xff0c;里面则是包含了他最出名的To be with you 赶忙去听&#xff0c;果然是原汁原味的To be with you&#xff0c;相比而言&#xff0c;westlife的翻唱版则是夹杂了popmusic的那种浮华。还是很喜欢这种摇滚…

2018.11.12

1、CSS3新增选择器&#xff0c;新增伪类选择器 3、动画规则&#xff1a; keyframes创建动画&#xff0c;规定动画属性&#xff1a; animation 所有动画属性的简写4、其他待看样式多列、用户界面、图片、按钮、分页、框大小、弹性盒子、多媒体查询 2、样式属性…

使用Singleton需要考虑内存释放

GoF[p84]所说的Singleton没有考虑到内存的释放解决方法&#xff1a;1、加入一个成员函数DestroyInstance&#xff08;&#xff09;来释放内存&#xff0c;在整个工程中需且仅需调用DestroyInstance&#xff08;&#xff09;一次。2、ME中说用智能指针 转载于:https://www.cnblo…

搭建基于Spring Cloud的微服务应用

原文链接 在2017云栖大会-上海峰会上阿里云技术专家李斌做了题为《搭建基于spring Cloud的微服务应用》的分享。随着时代的发展&#xff0c;用户对于应用服务的要求越来越高&#xff0c;单体应用已经无法满足用户。这就使得微服务应用顺势而生&#xff0c;利用Spring Cloud为用…

CSS之定位(绝对定位元素的布局)

绝对定位元素的布局&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>绝对定位元素的布局</title><style>.box1{width: 500px;height: 500px;background-color: #7FFFD4;position: relative;}.box…

【转】学习汇编前你应该知道的知识

转载地址&#xff1a;http://www.zxbc.cn/html/20070611/22772.html 1、汇编需要什么工具和程序&#xff0c;到哪里下载&#xff1f;目前阶段&#xff0c;汇编程序仅需要两个程序就够了。masm.exe,link.exe。 前者是编译程序&#xff0c;后者是链接程序。另外&#xff0c;为了验…

Visual C#弹出窗口杀手

2002-11-19 ASPCool.com 弹出窗口杀手是一个可以自动关闭IE弹出窗口的程序&#xff0c;它工作在系统的托盘中&#xff0c;按照一定的间隔来检测IE窗口&#xff0c;然后关闭弹出窗体。最后&#xff0c;还提供了用热键来杀掉弹出窗口的功能。   虽然已经有类似的用C写的程序&am…