function A(const AStr: string): integer;//orfunction B(AStr: string): integer;
假设两个函数内部都有相同的代码,它们之间的速度差可以忽略不计,我怀疑它甚至可以用一个循环计数器来测量,如:
function RDTSC: comp;var TimeStamp: record case byte of 1: (Whole: comp); 2: (Lo,Hi: Longint); end;begin asm dbprogram 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.F; db ; mov [TimeStamp.Lo],eax mov [TimeStamp.Hi],edx end; Result := TimeStamp.Whole;end;
这样做的原因是功能A中的所有const都是为了防止AStr的引用计数增加。
但增量只需要我的多核cpu的一个核心的一个周期,所以…
为什么要打扰const?
解决方法 如果函数没有其他原因包含一个隐含的try / finally,并且函数本身没有太多的工作,使用const可能会导致显着的加速(我曾经有一个使用> 10%的总运行时间,只需在正确的位置添加一个const即可在剖析运行中低于<2%)。 此外,引用计数需要比一个循环多得多,因为它必须用于锁定前缀来执行线程安全的原因,所以我们说的更像是50-100个循环。更多如果同一个高速缓存行中的某些内容被另一个内核修改。 至于无法衡量它:Const: 6084039NoConst: 36192232Const 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,edxend;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.
编辑:如果我们添加一些线程争用,它会变得有趣:
Const: 19968128NoConst: 1313528420Const is 65.78 times faster.
在6核心机器上,这给我:
function ConstLength(const s: string): Integer;begin Result := Pos('x',s);end;function NoConstLength(s: string): Integer;begin Result := Pos('x',s);end;
EDIT2:通过调用Pos替换对Length的调用(我选择了最坏的情况,搜索字符串中不包含的东西):
Const: 51792332NoConst: 1377644831Const is 26.60 times faster.
结果是:
Const: 15912102NoConst: 44616286Const is 2.80 times faster.
对于螺纹外壳,以及:
对于非螺纹的情况。
总结以上是内存溢出为你收集整理的delphi – 是使用“const”教条还是理性?全部内容,希望文章能够帮你解决delphi – 是使用“const”教条还是理性?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)