【发布时间】:2014-12-20 09:32:34
【问题描述】:
在我发现常见/最新的 Javascript 实现使用字符串实习来提高性能 (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/性能更新:
即使字符串长 16 倍,JSPerf 似乎也显示恒定时间?请看:
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 个字符)都已经在引号中分配了值(例如 5930496 个字符)时,它会将其设为 0- 1ms/瞬间。
似乎当您使用 for 循环或函数构建字符串时,该字符串不会被保留。因此,只有当您直接分配带有 var str = "test"; 之类的引号的字符串时才会发生实习
【问题讨论】:
-
我认为是因为 === 运算符仅在比较对象时才比较内存地址(类似于 Java)。但是“某物”不是对象,它的类型是内置字符串。和比较数字一样,var a=2; var b=2;,如果你这样做 a===b 你不是在比较对象也不是内存地址。
-
我知道你可以做 var
str = new String("test");但我也不知道那里的含义.. -
即使这样做 typeof str 也会是“字符串”,而不是对象。
-
我已经删除了小提琴,以免压垮更多的浏览器。我认为它们太小了。重要提示:我刚刚测试了两个等于字符串与使用 var s1='...';var s2='...'; 构造的 5930496chars 的比较需要 0ms,而比较char 构造的相同字符串需要 20 毫秒。
-
不知道,我对实习不熟悉。字符串太长以至于文件为 12MB。我要把它上传到 Dropbox 并用链接更新这条评论。
标签: javascript string performance time-complexity string-interning