【问题标题】:Does the compiler optimize string concatenation?编译器是否优化字符串连接?
【发布时间】:2012-11-25 15:09:32
【问题描述】:

在我的代码中有一些情况,我正在构建大量文本字符串,例如复杂的 SQL 语句。我打算将这段文字连续多次放在一起,每次都有一些略有不同的参数。我已经养成使用一个名为 procedure A(const S: String); 的子程序的习惯,它只是将文本 (S) 附加到较大的字符串 Text := Text + S + #10 + #13;

我想知道与使用传统的字符串连接相比,这是否会阻碍性能?我开始认为编译器会优化这样的东西:

Text := 'some' + ' ' + 'text' + ' ' + 'and' + ' ' + 'such';

Text := 'some text and such';

这是真的吗?编译器是否优化了这种情况?如果是这样,我可能会决定将所有内容更改为以下内容:

Text := 'select something from sometable st'+#10+#13+
  'join someothertable sot on sot.id = st.sotid'+#10+#13+
  'where sot.somevalue = 1'+#10+#13+
  'order by sot.sorting';

理论上会比这个更快

Text:= Text + 'select something from sometable st'+#10+#13;
Text:= Text + 'join someothertable sot on sot.id = st.sotid'+#10+#13;
Text:= Text + 'where sot.somevalue = 1'+#10+#13;
Text:= Text + 'order by sot.sorting';

或者我通常是怎么做的:

A('select something from sometable st');
A('join someothertable sot on sot.id = st.sotid');
A('where sot.somevalue = 1');
A('order by sot.sorting');

【问题讨论】:

  • 为什么不在调试器中打开它并查看生成的 ASM?
  • 如果您要将该文本作为 SQL 查询发送,那么 db 查询将花费比创建查询字符串的代码多几个数量级的时间。
  • 只是好奇:你为什么使用#10#13 (LF CR) 而不是#13#10 (CR LF)?
  • 使用 sLineBreak 并且不必记住哪个是第一个..
  • >>“那个 SQL 查询只是真实场景的一个快速示例。”在这种情况下,我想更清楚地说明这里提到的内容。请考虑一下 Knuth:“程序员会浪费大量时间来思考或担心程序中非关键部分的速度,而在考虑调试和维护时,这些效率上的尝试实际上会产生强烈的负面影响。我们应该忘记小的效率低下,大约 97% 的时间说:过早的优化是万恶之源。但我们不应该在关键的 3% 中放弃我们的机会。”

标签: string delphi delphi-xe2 concatenation compiler-optimization


【解决方案1】:

类似的表达式

'a' + 'b'

在编译时进行评估。这意味着一个任务

str := 'a' + 'b';

产生与

相同的编译代码
str := 'ab';

另一方面,对于

str := 'a';
str := str + 'b';

连接是在运行时执行的。

【讨论】:

  • 这正是我所希望和期待的,只需要从更有知识的人那里听到,谢谢!
  • 这是一种名为“恒定折叠”的“窥孔优化”。请参阅en.wikipedia.org/wiki/Constant_folding Delphi 编译器并没有实现所有这些优化,而是最常见和最有用的一种。好消息是我从未见过 Delphi 优化使代码逻辑失败,而一些激进的编译器有时在优化设置的情况下没有一致的行为。
  • 非常好。它使一个很长的内联字符串编写为一系列连接,与 Perl 和 Python 等语言中可能出现的“此处文档”或“多行字符串文字”一样有效。
【解决方案2】:

请注意,当使用非常量表达式时,将所有连接放在一个表达式中仍然更有效。 考虑这段代码:

  A := '*';
  B := 'person';
  C := 'first_name=''Jerry''';

  Q := 'select ';
  Q := Q + A;
  Q := Q + ' from ';
  Q := Q + B;
  Q := Q + ' where ';
  Q := Q + C;

上面的六个语句将执行 5 个单独的连接。 鉴于:

  Q := 'select ' + A + ' from ' + B + ' where ' + C;

将执行单个连接。 Delphi 将为结果分配必要的空间并将六个值中的每一个复制到该空间中。

【讨论】:

    猜你喜欢
    • 2011-05-16
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    • 2010-09-22
    相关资源
    最近更新 更多