Joh*_*ica 23 delphi parameters const
在Delphi中,您可以通过传递参数来加速代码const,例如
function A(const AStr: string): integer;
//or
function B(AStr: string): integer;
Run Code Online (Sandbox Code Playgroud)
假设两个函数内部具有相同的代码,它们之间的速度差异可以忽略不计,我怀疑它甚至可以用循环计数器测量,如:
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;
Run Code Online (Sandbox Code Playgroud)
其原因是const函数A 中的所有操作都是为了防止引用计数AStr增加.
但是增量只需要我的多核CPU的一个核心的一个周期,所以......
我为什么要打扰const?
Tho*_*ler 33
如果函数没有其他原因包含隐式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, ExitTime, KernelTime, 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.
Run Code Online (Sandbox Code Playgroud)
在我的系统上生成此输出:
Const: 6084039
NoConst: 36192232
Const is 5.95 times faster.
Run Code Online (Sandbox Code Playgroud)
编辑:如果我们添加一些线程争用,它会变得更有趣:
program Project;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils,
Classes,
Math;
function GetThreadTime: Int64;
var
CreationTime, ExitTime, KernelTime, UserTime: TFileTime;
begin
GetThreadTimes(GetCurrentThread, CreationTime, ExitTime, KernelTime, 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, THREAD_PRIORITY_HIGHEST);
InterlockedIncrement(ActiveCount);
WaitForSingleObject(StartEvent, 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: ', 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.
Run Code Online (Sandbox Code Playgroud)
在6核机器上,这给了我:
Const: 19968128
NoConst: 1313528420
Const is 65.78 times faster.
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
结果是:
Const: 51792332
NoConst: 1377644831
Const is 26.60 times faster.
Run Code Online (Sandbox Code Playgroud)
对于螺纹外壳,和:
Const: 15912102
NoConst: 44616286
Const is 2.80 times faster.
Run Code Online (Sandbox Code Playgroud)
对于非线程情况.
Luk*_*keH 26
不要忘记,const不仅仅是提供那些微小的性能改进.
使用const解释给任何读取或维护代码的人不应该更新值,并允许编译器捕获任何意外尝试.
因此,使代码更具可读性和可维护性也可以使其更快.有什么好的理由不使用const?
Dav*_*nan 10
使用const可以防止x86上的隐式try/finally块比引用计数更昂贵.对于const的语义来说,这确实是一个单独的问题.令人遗憾的是,性能和语义以这种方式混杂在一起.
String类型是一种特殊情况,因为它由Delphi管理(按需复制),因此不适合回答您的问题.
如果使用比指针,记录或数组大的其他类型测试函数,则应该看到更大的时间差,因为const只传递一个指针,而const不会在传递给函数之前复制记录.
使用关键字const,您可以将优化决策留给编译器.