delphi – 是使用“const”教条还是理性?
发布时间:2020-12-15 10:18:30 所属栏目:大数据 来源:网络整理
导读:在Delphi中,您可以通过将参数传递为const来加快您的代码,例如 function A(const AStr: string): integer;//orfunction B(AStr: string): integer; 假设两个函数内部都有相同的代码,它们之间的速度差可以忽略不计,我怀疑它甚至可以用一个循环计数器来测量
在Delphi中,您可以通过将参数传递为const来加快您的代码,例如
function A(const AStr: string): integer; //or function B(AStr: string): integer; 假设两个函数内部都有相同的代码,它们之间的速度差可以忽略不计,我怀疑它甚至可以用一个循环计数器来测量,如: function RDTSC: comp; var TimeStamp: record case byte of 1: (Whole: comp); 2: (Lo,Hi: Longint); end; begin asm db $0F; db $31; mov [TimeStamp.Lo],eax mov [TimeStamp.Hi],edx end; Result := TimeStamp.Whole; end; 这样做的原因是功能A中的所有const都是为了防止AStr的引用计数增加。 为什么要打扰const? 解决方法
如果函数没有其他原因包含一个隐含的try / finally,并且函数本身没有太多的工作,使用const可能会导致显着的加速(我曾经有一个使用> 10%的总运行时间,只需在正确的位置添加一个const即可在剖析运行中低于<2%)。 此外,引用计数需要比一个循环多得多,因为它必须用于锁定前缀来执行线程安全的原因,所以我们说的更像是50-100个循环。更多如果同一个高速缓存行中的某些内容被另一个内核修改。 至于无法衡量它:
program Project; {$APPTYPE CONSOLE} uses Windows,SysUtils,Math; function GetThreadTime: Int64; var CreationTime,ExitTime,KernelTime,UserTime: TFileTime; begin GetThreadTimes(GetCurrentThread,CreationTime,UserTime); Result := PInt64(@UserTime)^; end; function ConstLength(const s: string): Integer; begin Result := Length(s); end; function NoConstLength(s: string): Integer; begin Result := Length(s); end; var s : string; i : Integer; j : Integer; ConstTime,NoConstTime: Int64; begin try // make sure we got an heap allocated string; s := 'abc'; s := s + '123'; //make sure we minimize thread context switches during the timing SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL); j := 0; ConstTime := GetThreadTime; for i := 0 to 100000000 do Inc(j,ConstLength(s)); ConstTime := GetThreadTime - ConstTime; j := 0; NoConstTime := GetThreadTime; for i := 0 to 100000000 do Inc(j,NoConstLength(s)); NoConstTime := GetThreadTime - NoConstTime; SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_NORMAL); WriteLn('Const: ',ConstTime); WriteLn('NoConst: ',NoConstTime); WriteLn('Const is ',(NoConstTime/ConstTime):2:2,' times faster.'); except on E: Exception do Writeln(E.ClassName,': ',E.Message); end; if DebugHook <> 0 then ReadLn; end. 在我的系统上生成此输出: Const: 6084039 NoConst: 36192232 Const is 5.95 times faster. 编辑:如果我们添加一些线程争用,它会变得有趣: program Project; {$APPTYPE CONSOLE} uses Windows,Classes,UserTime); Result := PInt64(@UserTime)^; end; function ConstLength(const s: string): Integer; begin Result := Length(s); end; function NoConstLength(s: string): Integer; begin Result := Length(s); end; function LockedAdd(var Target: Integer; Value: Integer): Integer; register; asm mov ecx,eax mov eax,edx lock xadd [ecx],eax add eax,edx end; var x : Integer; s : string; ConstTime,NoConstTime: Integer; StartEvent: THandle; ActiveCount: Integer; begin try // make sure we got an heap allocated string; s := 'abc'; s := s + '123'; ConstTime := 0; NoConstTime := 0; StartEvent := CreateEvent(nil,True,False,''); ActiveCount := 0; for x := 0 to 2 do TThread.CreateAnonymousThread(procedure var i : Integer; j : Integer; ThreadConstTime: Int64; begin //make sure we minimize thread context switches during the timing SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_HIGHEST); InterlockedIncrement(ActiveCount); WaitForSingleObject(StartEvent,INFINITE); j := 0; ThreadConstTime := GetThreadTime; for i := 0 to 100000000 do Inc(j,ConstLength(s)); ThreadConstTime := GetThreadTime - ThreadConstTime; SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_NORMAL); LockedAdd(ConstTime,ThreadConstTime); InterlockedDecrement(ActiveCount); end).Start; while ActiveCount < 3 do Sleep(100); SetEvent(StartEvent); while ActiveCount > 0 do Sleep(100); WriteLn('Const: ',ConstTime); ResetEvent(StartEvent); for x := 0 to 2 do TThread.CreateAnonymousThread(procedure var i : Integer; j : Integer; ThreadNoConstTime: Int64; begin //make sure we minimize thread context switches during the timing SetThreadPriority(GetCurrentThread,INFINITE); j := 0; ThreadNoConstTime := GetThreadTime; for i := 0 to 100000000 do Inc(j,NoConstLength(s)); ThreadNoConstTime := GetThreadTime - ThreadNoConstTime; SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_NORMAL); LockedAdd(NoConstTime,ThreadNoConstTime); InterlockedDecrement(ActiveCount); end).Start; while ActiveCount < 3 do Sleep(100); SetEvent(StartEvent); while ActiveCount > 0 do Sleep(100); WriteLn('NoConst: ',E.Message); end; if DebugHook <> 0 then ReadLn; end. 在6核心机器上,这给我: Const: 19968128 NoConst: 1313528420 Const is 65.78 times faster. EDIT2:通过调用Pos替换对Length的调用(我选择了最坏的情况,搜索字符串中不包含的东西): function ConstLength(const s: string): Integer; begin Result := Pos('x',s); end; function NoConstLength(s: string): Integer; begin Result := Pos('x',s); end; 结果是: Const: 51792332 NoConst: 1377644831 Const is 26.60 times faster. 对于螺纹外壳,以及: Const: 15912102 NoConst: 44616286 Const is 2.80 times faster. 对于非螺纹的情况。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |