常见的 JavaScript 实现是否使用字符串实习?

IT技术 javascript programming-languages webkit v8 string-interning
2021-01-10 23:01:00

常见的 JavaScript 引擎,例如 V8 和 WebKit 的 JavaScriptCore,是否对 JavaScript 字符串使用字符串实习或者他们实际上是否在内存中保留了多个相同字符串的实例?

3个回答

是的。通常,JS 源代码中的任何文字字符串、标识符或其他常量字符串都是 intern。然而,实现细节(例如实习的确切内容)以及实习发生的时间各不相同。

请注意,字符串值与字符串对象不同,但字符串对象不会被实习,因为这从根本上是不正确的行为。

@FelipeSabino 实习的逻辑(至少在 JSC 中)分布在多个领域。基本模型与 Java 类似——常量字符串是自动插入的,字符串连接的结果等不是。在 Java 中,您可以明确强制实习,但在 JS 中不存在。
2021-03-11 23:01:00
当然,我可以查看任何开源代码并自行检查,但 SO 存在的原因之一是为了避免这种麻烦,哈哈。这不是怀疑您的知识的问题,这只是帮助开发人员进行研究的问题。看来你是一个对这个主题了解很多的人,而且还有更多有力的参考资料,可以帮助我更多地了解这个主题。只是举例说明,你说“一般情况下字符串是实习的”,在什么情况下他们不是?等等...
2021-03-12 23:01:00
@FelipeSabino 是否在主要引擎上工作并加入 ecmascript 委员会?;) 更重要的是,您可以在线查看 JavaScriptCore、SpiderMonkey、V8 等的源代码。
2021-03-13 23:01:00
@olliej 请你看看这里 - 有一个激烈的辩论stackoverflow.com/questions/26549715/...也在此处stackoverflow.com/questions/26532550/...谢谢!非常感谢帮助:)
2021-03-18 23:01:00
嗨@olliej,您的声明有任何来源吗?
2021-04-04 23:01:00

http://jsperf.com/strinterning

在 Chrome 中是,在 Aurora 15 和 FF 13 中不是!比较两个字符串比在 Firefox 中比较两个指针慢 85%。然而,它在 Chrome 中的速度相同,这表明它正在比较两个指针。

也许 Mozilla 的 JS 引擎团队应该检查他们的代码......

如果您认为这很糟糕,IE9在将字符串变量与其自身进行比较甚至不会进行指针比较相关的 JSPerfs。)
2021-04-03 23:01:00

简短回答:有时是,有时不是。

我也偶然发现了同样的问题,并仔细研究了一下。似乎实习通常是针对以相同方式生成的字符串文字完成的(例如,始终将相同的字符串分配给同一循环中的变量),但我也能够创建一个示例,该示例导致创建两个相同的字符串有两个不同的参考:

Chrome 开发工具堆快照显示具有不同引用 ID 的相同字符串值对

如您所见,每个字符串存储两次,具有不同的引用。

这是我用来生成重复字符串的代码:

const a = [];
const b = [];

for(let j  =1; j<= 100;++j){
    for(let i = 1; i <= 10000; ++i) a[i] = 'player 1 got 5 points from player 2' + i;
    for(let i = 1; i <= 10000; ++i) b[i] = 'player 1 got 5 points from player 2' + i;
}

似乎字符串实习是针对字符串文字完成的,但不是针对串联字符串值完成的,但是正如您在上面看到的,每个串联字符串只出现两次,而不是 100x2 = 200 次,因此仍然对在 中创建的串联字符串进行了字符串实习外循环。

@towc 这是来自 chrome 开发工具的内存堆快照。
2021-03-15 23:01:00
这是什么控制台?我无法让左侧的箭头出现在字符串上,或者更奇怪的是右侧的灰色参考在 opera/chrome/firefox 上
2021-03-20 23:01:00
@HanSeoul-Oh 所以连接的字符串永远不会被实习?
2021-03-31 23:01:00
@XCS 我不认为这是正确的:“仍然对在外循环中创建的连接字符串进行了字符串实习”。你是不是保持在外环(每次覆盖的每个元素迭代的早期迭代创建的字符串引用ab),但“只有可达对象包括在快照”。如果您维护对较早连接字符串的引用,那么您将获得每个字符串的200 个副本
2021-04-03 23:01:00
@XCS 我不知道,不幸的是,这就是为什么我在谷歌上搜索并遇到了这个问题!:) 我唯一确定的是您的测试用例没有说明连接字符串被实习的情况,而是说明了堆快照不包括无法访问的对象。但是,可能还有其他情况下连接的字符串插入,我不知道如何找到一个或证明它们不存在。
2021-04-04 23:01:00