奇怪的 Node.js 性能问题

4
我是一名有用的助手,可以翻译文本。
我编写了一个大型算法来解析一个字符串(测试时长达5MB)。在进行了一些更改后,我注意到性能显著下降了约30%-35%,因此我开始使用各种性能测量工具进行调试,并发现了一些奇怪的东西。
事实证明,在算法开头删除了以下仅调用一次的行之后,我的算法大幅减慢了:
text.match(/\n/g);

如果我只是将该行放在算法的顶部,而从未使用其结果,性能提高了30-35%,算法中的其他更改似乎根本没有任何区别。似乎执行这样的行在某种程度上会在进一步的字符串处理中为Node.js提供帮助,我无法进一步解释或分析。然后我开始在不同版本的Node.js上进行测试,并发现这发生在当前的10.15.3中,但未发生在v4.x或v12.x中。这种巨大的不一致性和对性能的完全神秘影响,我不知道如何解释。有人可以解释为什么像这样运行额外的RegEx搜索会突然为Node.js提供帮助吗?还是它在我的情况下具有特殊性质? 我已经记录了一个问题反对Node.js
1个回答

3
根据V8中字符串的创建方式,它被存储为一个连续的数组或者是“切片”(一棵二叉树)。二叉树不太友好于缓存,并且遍历多次会因为缓存未命中而导致管道停顿从而产生显著的性能损失。
在V8中ReGex的match()的副作用是调用String::Flatten。那将导致字符串在内存中成为连续的。该副作用很不幸在之后的V8版本中被移除了。
Node 10暴露了一个新函数%FlattenString,可以用于显式地使字符串成为连续的。
作为一个版本无关的解决方案,您可以使用flatstr模块。根据V8版本,它要么调用%FlattenString(s),要么调用Number(s)(依赖于副作用)。

值得一提的是,我尝试使用 flatstr 模块,但其效果几乎为零,而仅仅执行 text.match(/\n/g); 就能大大提高性能。 - vitaly-t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接