为什么Javascript === / ==字符串相等有时具有恒定的时间复杂度,有时具有线性时间复杂度?

时间:2014-10-24 14:14:35

标签: javascript string performance time-complexity string-interning

在我发现常见/最新的Javascript实现使用String Interning进行性能提升(Do common JavaScript implementations use string interning?)之后,我认为===对于字符串将获得恒定的O(1)时间。所以我对这个问题给出了错误的答案:

JavaScript string equality performance comparison

由于根据该问题的OP,它是O(N),将字符串输入加倍,等于需要的时间。他没有提供任何jsPerf,因此需要进行更多调查,

所以我使用字符串实习的方案是:

var str1 = "stringwithmillionchars"; //stored in address 51242

var str2 = "stringwithmillionchars"; //stored in address 12313

“stringwithmillionchars”将被存储一次,比如说地址201012的内存 并且str1和str2都将“指向”此地址201012.然后可以通过某种散列来确定该地址,以映射到内存中的特定位置。

所以在做的时候

"stringwithmillionchars" === "stringwithmillionchars"

看起来像

getContentOfAddress(51242)===getContentOfAddress(12313)

201012 === 201012

需要O(1)/恒定时间

JSPerfs / Performance updates:

JSPerf似乎显示常量时间,即使字符串长16倍?请看一下:

http://jsperf.com/eqaulity-is-constant-time

上面的字符串可能太小了: 这可能显示线性时间(感谢sergioFC)字符串是用循环构建的。我试过没有功能 - 仍然是线性时间/我稍微改了一下 http://jsfiddle.net/f8yf3c7d/3/

根据https://www.dropbox.com/s/8ty3hev1b109qjj/compare.html?dl=0(sergioFC制作的12MB文件),当你有一个字符串并且你已经用引号分配了值,无论t1和t2有多大(例如5930496个字符),它就是它0-1ms /即时。

似乎在使用for循环或函数构建字符串时,字符串不会被实现。因此,仅当您直接为带有var str = "test";

等引号的字符串分配时,才会发生实习

3 个答案:

答案 0 :(得分:5)

基于字符串a和b的所有性能测试(参见原始帖子),操作a === b需要:

  • 常量时间O(1)如果字符串被中断。从示例中可以看出,仅使用var str = "test";等直接分配的字符串就会发生 实习,如果使用for循环或函数进行连接,则不会。

  • 线性时间O(N),因为在所有其他情况下,首先比较两个字符串的长度。如果它是相等的,那么我们逐字符比较。当然,他们并不平等。 N是字符串的长度。

答案 1 :(得分:2)

根据ECMAScript 5.1 Specification's Strict Equal Comparison algorithm,即使被比较的对象类型是String,也会检查所有字符是否相等。

  
      
  1. 如果Type(x)是字符串,则返回true ,如果xy完全相同的字符序列(相应位置的长度和字符相同) ); 否则,返回false
  2.   

Interning严格来说是一种实现方式,以提高性能。语言标准没有在这方面强加任何规则。因此,它取决于规范的实施者是否为实习生字符串。

答案 2 :(得分:1)

首先,很高兴看到一个JSPerf测试,该测试演示了将字符串大小加倍的声明,使执行时间加倍。

接下来,让我们认为这是理所当然的。这是我的(未经证实,未经检查,可能与现实无关)理论。

无论引用多少数据,对两个内存地址的比较都很快。但是你必须首先使用INTERN这个字符串。如果你的代码中有

var a = "1234";
var b = "1234";

然后引擎首先必须理解这两个字符串是相同的并且可以指向相同的地址。所以至少一次这些字符串必须完全比较。所以基本上这里有以下选项:

  • 引擎在解析代码时直接比较和实习字符串。在这种情况下,等于字符串应该获得相同的地址。
  • 引擎可能会说“这些字符串是两个大字,我不想实习它们”并且有两个副本。
  • 引擎可能会在以后实习这些字符串。

在后两种情况下,字符串比较会影响测试结果。在最后一种情况下 - 即使字符串最终被实现。

但正如我所写的,一个狂野的理论,为理论的圣人。我首先想看一些JSPerf。