+ 运算符的性能是不是低于 StringBuffer.append()

Posted

技术标签:

【中文标题】+ 运算符的性能是不是低于 StringBuffer.append()【英文标题】:is the + operator less performant than StringBuffer.append()+ 运算符的性能是否低于 StringBuffer.append() 【发布时间】:2010-09-11 20:20:14 【问题描述】:

在我的团队中,我们通常这样进行字符串连接:

var url = // some dynamically generated URL
var sb = new StringBuffer();
sb.append("<a href='").append(url).append("'>click here</a>");

显然以下内容更具可读性:

var url = // some dynamically generated URL
var sb = "<a href='" + url + "'>click here</a>";

但是 JS 专家声称 + 运算符的性能不如 StringBuffer.append()。这是真的吗?

【问题讨论】:

javascript中没有StringBuffer 唐,你指的是 Java 吗? 我的经验是[].join('') 已经表现出一些非常有线的行为,所以我觉得回到 + :-/ 我知道这里的基本问题是关于字符串连接,但是在创建这样的 html 元素时应该小心。如果url 包含'\n,您的示例可能会中断。 我想知道为什么这个问题因为不够清晰而没有结束。相反,它有 91 个赞成票。 JS 中没有 StringBuffer,这怎么可能是一个有效的问题? 【参考方案1】:

您的示例不是一个好示例,因为性能不太可能有显着差异。在您的示例中,可读性应该胜过性能,因为一个与另一个的性能增益可以忽略不计。数组 (StringBuffer) 的好处只有在您进行许多连接时才会显现出来。即使这样,您的里程也可能非常取决于您的浏览器。

这是一个详细的性能分析,显示了在许多不同浏览器中使用所有不同 JavaScript 连接方法的性能; String Performance an Analysis

更多:Ajaxian >> String Performance in IE: Array.join vs += continued

【讨论】:

关于图表,以防不明显;越低越好。 "首先是 IE7 的性能改进,在进行大规模字符串操作时,我们不再需要考虑使用备用路径;在迭代情况下使用 Array.join 没有比在相同的情况下使用 +=。此外,与 IE6 的差异很小,让您不必为那个特定版本分叉。" @Chris,这不是真的。比较 IE7 中的这两个小提琴:jsfiddle.net/9uS4n/5(快)与jsfiddle.net/9uS4n/2(慢)。使用join() 技术,性能似乎至少提高了 1000 倍。 很好的解释。另请查看:iliadraznin.com/2012/03/…【参考方案2】:

Internet Explorer 是当今世界上唯一真正受此困扰的浏览器。 (版本 5、6 和 7 非常慢。8 没有表现出同样的退化。)更重要的是,IE 变得越来越慢,字符串越长。

如果你有很长的字符串要连接,那么一定要使用 array.join 技术。 (或一些 StringBuffer 包装器,以提高可读性。)但如果你的字符串很短,请不要打扰。

【讨论】:

【参考方案3】:

是的,这是真的,但你不应该在意。选择更容易阅读的那个。如果您必须对您的应用程序进行基准测试,那么请关注瓶颈。

我猜字符串连接不会成为你的瓶颈。

【讨论】:

【参考方案4】:

同意Michael Haren。

如果性能确实是个问题,还要考虑使用数组和连接。

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));

【讨论】:

我知道选择了一个正确的答案,但是这个答案有一个更有用的例子。 哇,哇。比较 IE7 中的这两个小提琴:jsfiddle.net/9uS4n/5(快)vs.jsfiddle.net/9uS4n/2(慢)。使用这种技术,性能似乎至少提高了 1000 倍。 @KirkWoll:将来可能想使用jsPerf,以便我们轻松比较结果。 我最近也在这样做,代码风格类似于 .NET StringBuilder,var sb = []; sb.push("第 1 节"); sb.push("第 2 节"); return sb.join(''); 这个 jsPerf jsperf.com/join-concat/2 在:***.com/questions/16696632/… 中提到似乎表明+= 更快。【参考方案5】:

试试这个:

var s = ["<a href='", url, "'>click here</a>"].join("");

【讨论】:

好吧,您在答案中链接到的帖子专门试图反驳我的回答所暗示的 Array.join 的“神话”。所以也许不是。我只是发布了我认为在实践中更快的内容。 喜欢这种字符串连接方法。【参考方案6】:

正如一些用户已经指出的那样:这与小字符串无关。

Firefox、Safari 或 Google Chrome 中的新 JavaScript 引擎进行了优化

"<a href='" + url + "'>click here</a>";

速度一样快

["<a href='", url, "'>click here</a>"].join("");

【讨论】:

【参考方案7】:

JavaScript 没有本机 StringBuffer 对象,所以我假设这是来自您正在使用的库,或者是不寻常的主机环境(即不是浏览器)的功能。

我怀疑库(用 JS 编写)会更快地生成任何东西,尽管本机 StringBuffer 对象可能会。可以通过分析器找到明确的答案(如果您在浏览器中运行,那么 Firebug 将为您提供 Firefox 中的 JS 引擎的分析器)。

【讨论】:

【参考方案8】:

用 Knuth 的话来说,“过早的优化是万恶之源!”无论哪种方式的小差异最终很可能不会产生太大影响。我会选择更易读的。

【讨论】:

传统上 StringBuffer 用于串联,因为前者的时间复杂度为 O(N),而后者的时间复杂度为 O(N^2),因此对于大 N(但对于小 N)来说差异很大.在任何情况下,O(N^2) 的情况在 JavaScript 中可能不是这种情况,具体取决于使用的环境。【参考方案9】:

更易于阅读的方法在查看代码时为人们节省了可察觉的时间,而“更快”的方法仅在人们浏览页面时浪费了难以察觉且可能可忽略不计的时间。

我知道这个帖子很烂,但我不小心发布了一些完全不同的东西,以为这是一个不同的帖子,我不知道如何删除帖子。我的坏...

【讨论】:

【参考方案10】:

使用jspref.com 设置快速基准测试并检查 Javascript 性能变化非常容易。当这个问题被问到时,它可能并不存在。但是对于遇到这个问题的人来说,他们应该看看这个网站。

我在http://jsperf.com/string-concat-methods-test 对各种连接方法进行了快速测试。

【讨论】:

从现在看来,与 + 运算符连接肯定是要走的路。除非我读错了。这是完全合理的。【参考方案11】:

我喜欢用函数式风格,比如:

function href(url,txt) 
  return "<a href='" +url+ "'>" +txt+ "</a>"


function li(txt) 
  return "<li>" +txt+ "</li>"


function ul(arr) 
  return "<ul>" + arr.map(li).join("") + "</ul>"


document.write(
  ul(
    [
      href("http://url1","link1"),
      href("http://url2","link2"),
      href("http://url3","link3")
    ]
  )
)

这种样式看起来可读且透明。它导致了实用程序的创建,从而减少了代码的重复。

这也倾向于自动使用中间字符串。

【讨论】:

【参考方案12】:

据我所知,每个连接都意味着内存重新分配。所以问题不在于操作者习惯做的事情,解决方法是减少连接的数量。例如,尽可能在迭代结构之外进行连接。

【讨论】:

这实际上不是一个坏建议,我不知道为什么它被如此多地否决。我知道它没有回答具体问题,但它应该被认为是一般的好建议。【参考方案13】:

是的,根据通常的基准。例如:http://mckoss.com/jscript/SpeedTrial.htm.

但对于小字符串,这无关紧要。您将只关心非常大的琴弦上的演奏。更重要的是,在大多数 JS 脚本中,瓶颈很少出现在字符串操作上,因为它还不够。

你最好看看 DOM 操作。

【讨论】:

链接已失效。https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm 指向网络存档版本。

以上是关于+ 运算符的性能是不是低于 StringBuffer.append()的主要内容,如果未能解决你的问题,请参考以下文章

一个双向 Doctrine2 关系的性能是不是低于两个单向关系?

整数运算性能 32 与 64 位

关于StringBuffe()长度和初始化长度的问题归纳

优化专题

WKWebView WebGL 性能低于 Safari

查询 Mongoid/rails 3 中的嵌入对象(“低于”、Min 运算符和排序)