经常重写大字符串时如何防止浏览器内存溢出?

问题描述 投票:0回答:1

背景: 我需要分析和比较由不太完美的部署过程生成的几个大型 css. 文件。 在清理整个 CSS 混乱之前,我需要组织部署过程。 但是,仅使用一种一致的方法,仅将相同的文件包含在推荐的语法中,而不是混合使用过时的语法,生成的文件就会有很大差异。 我(需要)在 Javascript/Typescript 中执行此操作,因为团队经常使用这样的网络工具。 该工具的保质期不会很长,也不必满足最高的质量标准。 加壳器会生成带有所包含文件的源位置的注释,这对我们的故障排除很有帮助。

问题: 我正在使用的文件大小为 1.2 MB,有 34500 行,有 4331 条评论。我解析出所有注释并将它们存储在一个数组中,包括它们的原始起始行。 我想删除注释,因为它们的内容可能会混淆以下解析过程(例如杂散括号),但我也想将所有内容保留在其原始行位置。因此,我循环文件内容,一次存储一条注释,然后用一个或多个空行替换注释,具体取决于注释的行数。

所有这些都没有问题,但对于这一行:

this._source = this._source.replace(content, replacer);

this._source 显然是大字符串,并且是注释内容,替换空行。

根据开发工具,该字符串使用了 2.5 MB 内存(并且内部是 unicode,这似乎符合预期)。发生的情况是:每次运行该行时,字符串的副本都会存储在内存中,并且不会被垃圾收集。在大约 1200 次运行时,(显然)达到了 4GB 的内存限制,并且在 Chrome 中调试器开始启动。 Firefox 在我的机器上没有抱怨,但最终内存使用量为 6.5 GB。

我有信心,我会找到一个更优雅的解决方案,并且不会出现内存问题,但我对这种情况发生感到困惑。我什至尝试在 1000 条评论后停止解析,并等待 10 秒让垃圾收集器有时间释放内存,但这并没有帮助。

我做错了什么,和/或我不明白什么?

提前谢谢您。

javascript typescript string replace memory-leaks
1个回答
1
投票

在循环内重复使用

this._source = this._source.replace(content, replacer);
会在内存中创建新字符串,并且之前的字符串不会立即被垃圾回收,从而导致内存使用量增加。

您可以考虑使用数组来累积修改的行,然后将它们连接回字符串。这样,您就可以避免在内存中创建字符串的多个副本:

const lines = this._source.split('\n');

for (const { startLine, content, replacer } of commentsArray) {
  lines[startLine - 1] = replacer;
}

const modifiedSource = lines.join('\n');

如果您的注释遍布整个文件,并且您需要替换多次出现的同一注释,您可以考虑将带有全局标志 (

/g
) 的正则表达式与循环结合使用。这使您可以一次性替换所有出现的位置,而不需要循环。

for (const { content, replacer } of commentsArray) {
  const commentRegExp = new RegExp(content, 'g');
  this._source = this._source.replace(commentRegExp, replacer);
}
© www.soinside.com 2019 - 2024. All rights reserved.