我需要在程序中经常读取字符串s
的长度。我将s
字符串设置为一次,以便我可以在变量(NoOfChars
)中记住它的大小,如下所示:
type
MyClass= class
Public
s: string;
NoOfchars: integer;
end;
procedure MyClass.SetS(const MyString: String);
begin
s:= MyString;
NoOfchars := Length(s); // <-- store it once, read it often
end;
我想我读到Length(s)
与读取常量一样快的地方,因为它只访问存储在字符串前面的“hidden”字段中的字符串的长度。这很有意义,但由于我们没有源代码,我们只能猜测。也许还有其他涉及的计算?
那么,我应该使用Length(s)
还是应该记住变量中的长度?
答案 0 :(得分:8)
你有源代码。它位于System
单位。
function _UStrLen(const S: UnicodeString): Integer;
begin
Result := Longint(S);
if Result <> 0 then // PStrRec should be used here, but
Result := PLongint(Result - 4)^; // a private symbol can't be inlined
end;
这个辅助函数被标记为内联,实际上编译器会内联它。这个计划:
{$APPTYPE CONSOLE}
var
i: Integer;
s: string;
begin
i := Length(s);
Writeln(i);
end.
编译为以下内容:
.... Project1.dpr.10: i := Length(s); 004060E3 A19CAB4000 mov eax,[$0040ab9c] // $0040ab9c holds the variable s 004060E8 85C0 test eax,eax // test for nil 004060EA 7405 jz $004060f1 004060EC 83E804 sub eax,$04 // offset to length 004060EF 8B00 mov eax,[eax] // read length into eax 004060F1 8BD8 mov ebx,eax // compiler optimises i into ebx ....
代码非常简单。检查字符串变量是否为nil
。如果是这样,答案就是零。否则,从字符串的适当偏移量读取长度。
这当然是一个非常快速的功能。但是,调用Length
,即使按内联方式调用它也不会那么快,因为它是从局部变量读取的。实际上,编译器可以很好地将局部变量优化为寄存器。
因此,如果性能很重要,读入局部变量可以提高性能。但是你必须计算现实世界的代码,以了解性能差异是否真正重要。
我个人倾向于将字符串长度存储在局部变量中,因为我需要不止一次地引用长度。如果我每次调用函数时都知道值相同,则可以通过将值存储在本地来表达。
答案 1 :(得分:7)
FWIW通过简单的测试,您可以轻松地了解变量的使用速度。当然,这并不会测试您的生产代码中的所有情况和可能性,但您会得到一个粗略的估计。
program Project1;
{$APPTYPE CONSOLE}
uses
Diagnostics;
var
sw: TStopwatch;
s: string;
len, i, x: Integer;
begin
s := 'somestring';
len := Length(s);
sw := TStopwatch.StartNew;
for i := 0 to MaxInt do
begin
x := len;
if x = 0 then
end;
Writeln('using variable: ', sw.ElapsedMilliseconds);
sw := TStopwatch.StartNew;
for i := 0 to MaxInt do
begin
x := Length(s);
if x = 0 then
end;
Writeln('using Length(s): ', sw.ElapsedMilliseconds);
Readln;
end.
在VM中,我得到这样的数字(发布配置):
using variable: 587
using Length(s): 1255
答案 2 :(得分:0)
当读取字符串的长度时,Delphi会读取字符串的隐藏长度字段。但是读取隐藏字段需要比读取整数更多的cpu指令。所以Length()很快,但没有读取NoOfChars字段那么快。
理论上,编译器可能能够根据上下文进一步优化读取长度。因此,我建议您在真正的单词应用程序中进行一些速度测量。