CnPack Forum


 
Subject: 建议修改一处代码.
niaoge
灌水司司长
Rank: 6Rank: 6



UID 9910
Digest Posts 0
Credits 438
Posts 143
点点分 438
Reading Access 10
Registered 2007-4-8
Status Offline
Post at 2007-6-13 14:29  Profile | Blog | P.M. 
建议修改一处代码.

1、CnWizUtils.pas内有放多取得OTA 接口的函数,这些函数在短短的10分钟内总共调用有上百万次,经检测存在以下“问题”,
举一个例子:原函数:
function CnOtaGetEditBuffer: IOTAEditBuffer;
var
  iEditorServices: IOTAEditorServices;
begin  
  Result := nil; //:=nil放在上面要占用该函数10-40%的时间,可能是接口取空值与实列取空值处理机制不一样,
  QuerySvcs(BorlandIDEServices, IOTAEditorServices, iEditorServices);
  if iEditorServices <> nil then
    Result := iEditorServices.GetTopBuffer;
end;

建议改成如下表达:
function CnOtaGetEditBuffer: IOTAEditBuffer;
var
  iEditorServices: IOTAEditorServices;
begin  
  QuerySvcs(BorlandIDEServices, IOTAEditorServices, iEditorServices);
  if iEditorServices <> nil then
  begin
    Result := iEditorServices.GetTopBuffer;
    Exit;//取得后直接退出,
  end;
  Result := nil;//没取得时再用:=nil,放在这里,不占用时间
end;
附件是我改好的CnWizUtils.pas
修改后测不出这些函数调用时间

2、还有一处建议,论坛灌水很不方便,刚才加附件(.pas)时,提示不支持该格式,退回来时原来打的字全没了,又得重新输,中招了好多次了,建议改改

3、还有一处 增加应用程序空闲通知,AddApplicationIdleNotifier,参数应为 TIdleEvent而不是TNotifyEvent,
TIdleEvent原型为TIdleEvent = procedure (Sender: TObject; var Done: Boolean) of object; 其中Done默认为True,
现在cw内的几个空闲过程如TCnEditControlWrapper.OnIdle调用很频繁,能否在Done上想想办法,空闲时只调用一次?

[ 本帖最后由 niaoge 于 2007-6-13 15:04 编辑 ]


Attachment: CnWizUtils.rar (2007-6-13 14:30, 22.96 K)
Download count 385
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6812
Posts 3579
点点分 6812
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2007-6-13 16:37  Profile | Blog | P.M. 
nil放在上面要占用该函数10-40%的时间
这是怎么测出来的?

另外这个赋值为nil的语句的汇编代码能否贴出来看看为啥会消耗这么多的时间,难道用了IntfClear这种内部函数?
(上班没装Delphi故此这么一问)
Top
niaoge
灌水司司长
Rank: 6Rank: 6



UID 9910
Digest Posts 0
Credits 438
Posts 143
点点分 438
Reading Access 10
Registered 2007-4-8
Status Offline
Post at 2007-6-13 17:33  Profile | Blog | P.M. 


QUOTE:
原帖由 Passion 于 2007-6-13 16:37 发表
nil放在上面要占用该函数10-40%的时间
这是怎么测出来的?

另外这个赋值为nil的语句的汇编代码能否贴出来看看为啥会消耗这么多的时间,难道用了IntfClear这种内部函数?
(上班没装Delphi故此这么一问) ...

用AQTime测的,
我不会用汇编代码

[ 本帖最后由 niaoge 于 2007-6-13 17:36 编辑 ]
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6812
Posts 3579
点点分 6812
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2007-6-13 22:44  Profile | Blog | P.M. 
一句 Result := nil; 确实调用了IntfClear
见汇编代码:

Unit1.pas.37: Result := nil;
0044C880 8BC3             mov eax,ebx
0044C882 E8C58BFBFF       call @IntfClear
0044C887 33C0             xor eax,eax
0044C889 5A               pop edx
0044C88A 59               pop ecx
0044C88B 59               pop ecx
0044C88C 648910           mov fs:[eax],edx
0044C88F 689CC84400       push $0044c89c
0044C894 C3               ret
0044C895 E97A6FFBFF       jmp @HandleFinally
0044C89A EBF8             jmp -$08
Unit1.pas.38: end;
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6812
Posts 3579
点点分 6812
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2007-6-13 23:13  Profile | Blog | P.M. 
我们参考您的代码改动,对此单元的部分函数进行了一些优化。
不过您有几个优化影响了函数原有的功能,我们没改动。

详情可在CVS上下载过来比较一下。
Top
niaoge
灌水司司长
Rank: 6Rank: 6



UID 9910
Digest Posts 0
Credits 438
Posts 143
点点分 438
Reading Access 10
Registered 2007-4-8
Status Offline
Post at 2007-6-14 09:43  Profile | Blog | P.M. 
第3个问题有没有办法解决?我试了将AddApplicationIdleNotifier参数类型改成TIdleEvent,
原型为:TIdleEvent = procedure (Sender: TObject; var Done: Boolean) of object;
delphi可能取出Done值为True,如果能在Done做做文章就好了,
下面是简单的调试方法,类似于cndebug,不过比cndebug方便,
安装codesite 4,
将下例单元加到delphi路径下
unit csos;
interface
  uses
    SysUtils,CodeSiteLogging;
  function rc4:TCodeSiteObject;
  var
    Frc4:TCodeSiteObject;
implementation
  function rc4:TCodeSiteObject;
  begin
    if not Assigned(Frc4) then
     Frc4:=TCodeSiteObject.Create(nil);
    Result:=Frc4;
  end;
initialization
finalization
  if Assigned(Frc4) then
    FreeAndNil(Frc4);
end.
在CnEditControlWrapper.pas引用csos
在TCnEditControlWrapper.OnIdle内加一行rc4.sendvariant('Done',Done);你会发现,当delphi空闲时,OnIdle一直重复计算,D2007比D2006更快,不过D2006每秒钟也有好几次,而且每算一次都会调用Result.LineCount := Editor.EditView.Buffer.GetLinesInBuffer,这句话很占用时间;,如果能想到办法,让OnIdle只计算一次就好了,
Top
niaoge
灌水司司长
Rank: 6Rank: 6



UID 9910
Digest Posts 0
Credits 438
Posts 143
点点分 438
Reading Access 10
Registered 2007-4-8
Status Offline
Post at 2007-6-14 11:14  Profile | Blog | P.M. 
to:Passion (LiuXiao)
我从Cvs上下载了与我修改的比较后,发现确实有一处功能与原功能有出入,我改好了,由于上次采用类似于记事本的工具修改的,没有认真审查,这次全部在delphi内审查,其它修改的代码的功能与原功能一样,建议全部采用最后把result:=nil;以提高性能
原来代码内有一处Bug,我也修改好了,参见附件


Attachment: CnWizUtils.rar (2007-6-14 11:14, 23.02 K)
Download count 403
Top
niaoge
灌水司司长
Rank: 6Rank: 6



UID 9910
Digest Posts 0
Credits 438
Posts 143
点点分 438
Reading Access 10
Registered 2007-4-8
Status Offline
Post at 2007-6-14 14:26  Profile | Blog | P.M. 
ExecuteOnApplicationIdle 这个过程实际等同于 AddApplicationIdleNotifier
但是在启用后,不知为什么,结束时却没有RemoveApplicationIdleNotifier,
别外ExecuteOnApplicationIdle随着程序的运行应是一直不断地加,故当相应的空闲过程执行结束后应执行,RemoveApplicationIdleNotifier
我自己试着全部加上去的,结果发现在Delphi2006运行和退出速度很快,不知道对不对?
附件是全部修改的代码,供参考,不对之处请指证(文件超过2M,发不出去,我发到周总邮箱)

[ 本帖最后由 niaoge 于 2007-6-14 14:44 编辑 ]
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6812
Posts 3579
点点分 6812
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2007-6-29 23:12  Profile | Blog | P.M. 
如果用TIdleEvent = procedure (Sender: TObject; var Done: Boolean) of object;用done来控制idle是否要继续调用的话,不同的过程之间可能就因此互相影响了。

ExecuteOnApplicationIdle 这个过程实际等同于 AddApplicationIdleNotifier
——这句不对吧。后者加到FApplicationIdleNotifiers中保存,前者是放FIdleMethods中,FIdleMethods里头的东西被执行时,是删一个执行一个的。所以ExecuteOnApplicationIdle应该只会把参数中传入的Method执行一次,而无需再手工Delete。
Top
 




All times are GMT++8, the time now is 2024-9-20 00:19

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.016286 second(s), 8 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP