面向对象Pascal - Delphi中的内联VS线性字符串处理性能

时间:2011-06-24 12:34:43

标签: performance string delphi

由于我的一个项目的结束,我想要进行一些讨论(如果Rob没有提供非常详细的答案:D),我更关注一些内存和循环优化在一些饥饿的字符串处理区域。在我的情况下,我对一些性能测试感兴趣,如果有人做了类似的事情,对于两种情况的特殊性能差异:

案例1:我以串联的方式使用字符串处理,所以我有一个额外的冗长行,例如,

RichEdit1.SelText := stringfunction1(stringfunction2(stringfunction3(stringfunction4, stringfunction5), stringfunction6, stringfunction7(stringfunction8))))

案例2:

我只是拆分所有这些函数,因此每个函数都在单独的行中执行,因此我必须声明一个缓冲每个函数返回的变量。

P.S。我希望我没有误解案例1中的括号。

那么,你对这个问题的发现/意见/批评是什么?

也许不值得花时间获得一些额外的纳秒?

3 个答案:

答案 0 :(得分:4)

我相信声明变量不会有任何不同。

当你调用这样的函数时,编译器需要生成隐式字符串变量来保存函数的结果。你这样做的主要优点是编译器可以决定在使用temp变量后重用它,但没有什么能阻止编译器对显式变量做同样的事情。

实际上,每次使用字符串结果调用函数时,编译器都需要创建临时变量,因为返回字符串的函数实际上是作为带有附加var参数的过程实现的。

例如:

function GetTempPath : string;

实际上是以这种方式实现的

procedure GetTempPath(var S : string);

所以,按照以下程序:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Text := GetTempPath;
end;

编译器首先分配一个临时字符串变量。使用参数中的所述临时变量调用GetTempPath。一旦它返回,它将获取此变量并将其设置为Memo1.Lines.Text。基本上,它真正做的是:

procedure TForm1.Button1Click(Sender: TObject);
var S : string;
begin
  GetTempPath(S);
  Memo1.Lines.Text := S;
end;

如果你实际上声明了如下所示的函数,那么编译器就足够聪明,不能创建一个额外的变量。

procedure TForm1.Button1Click(Sender: TObject);
var S : string;
begin
  S := GetTempPath;
  Memo1.Lines.Text := S;
end;

答案 1 :(得分:3)

代码

var
  s1, s2: string;
begin
  s1 := 'This is a very long string...';
  s2 := s1;
end;

将字符串s1复制到s2(这可能是紧密循环中的性能问题),但它只是指示s2 < em>指向到内存中与s1相同的位置。也就是说,通常,将字符串分配给变量并不是一件坏事。

事实上,我不确定哪种方法可以产生最有效的汇编代码(如果它们不相同!)。即使在内联案例中,中间结果也必须存储在某个地方......

总而言之,我绝对认为你应该采用最易读的方法(对于人类程序员)。性能差异甚至无法检测到。

答案 2 :(得分:0)

好。

我会尝试将两个句子放在一起。 :)

  • 字符串优化 基本上是过早的优化 因为它是瓶颈 在非常非常非常后方的表现 情况或用例。

  • 内联字符串用法的主要优点是使用允许在进一步的参数函数调用中重用先前的返回(temp)变量的编译器功能。仍然 - 如果我们打算使用线性操作,我们应该在主字符串均衡代码之前添加GetTempPath()过程,以确保我们使用仍可在内存中访问的旧临时变量。