javascript - 如何强制 JavaScript 深度复制字符串?

标签 javascript google-chrome memory-management garbage-collection

我有一些 javascript 代码,如下所示:

var myClass = {
  ids: {}
  myFunc: function(huge_string) {
     var id = huge_string.substr(0,2);
     ids[id] = true;
  }
}

稍后会使用一些大字符串 (100 MB+) 调用该函数。我只想保存一个在每个字符串中找到的短 ID。但是,Google Chrome 的子字符串函数(在我的代码中实际上是正则表达式)只返回一个引用原始字符串的“切片字符串”对象。因此,在对 myFunc 进行一系列调用之后,我的 chrome 选项卡内存不足,因为临时 huge_string 对象无法被垃圾回收。

如何复制字符串 id 以便不维护对 huge_string 的引用,而 huge_string 可以收集垃圾?

enter image description here

最佳答案

JavaScript 的 ECMAScript 实现因浏览器而异,但对于 Chrome,许多字符串操作(substr、slice、regex 等)只是保留对原始字符串的引用,而不是复制字符串。这是 Chrome 中的一个已知问题 (Bug #2869)。要强制复制字符串,可以使用以下代码:

var string_copy = (' ' + original_string).slice(1);

此代码通过在字符串前面附加一个空格来工作。这种连接会在 Chrome 的实现中产生一个字符串副本。然后可以引用空格后面的子串。

解决方案的这个问题已在此处重新创建:http://jsfiddle.net/ouvv4kbs/1/

警告:加载时间较长,打开 Chrome 调试控制台以查看进度打印输出。

// We would expect this program to use ~1 MB of memory, however taking
// a Heap Snapshot will show that this program uses ~100 MB of memory.
// If the processed data size is increased to ~1 GB, the Chrome tab
// will crash due to running out of memory.

function randomString(length) {
  var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  var result = '';
  for (var i = 0; i < length; i++) {
    result +=
        alphabet[Math.round(Math.random() * (alphabet.length - 1))];
  }
  return result;
};

var substrings = [];
var extractSubstring = function(huge_string) {
  var substring = huge_string.substr(0, 100 * 1000 /* 100 KB */);
  // Uncommenting this line will force a copy of the string and allow
  // the unused memory to be garbage collected
  // substring = (' ' + substring).slice(1);
  substrings.push(substring);
};

// Process 100 MB of data, but only keep 1 MB.
for (var i =  0; i < 10; i++) {
  console.log(10 * (i + 1) + 'MB processed');
  var huge_string = randomString(10 * 1000 * 1000 /* 10 MB */);
  extractSubstring(huge_string);
}

// Do something which will keep a reference to substrings around and
// prevent it from being garbage collected.
setInterval(function() {
  var i = Math.round(Math.random() * (substrings.length - 1));
  document.body.innerHTML = substrings[i].substr(0, 10);
}, 2000);

enter image description here

关于javascript - 如何强制 JavaScript 深度复制字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31712808/

相关文章:

iOS - 在静态单例类中保留对主 UIViewController 的引用

javascript - 如何从 aspx 文件中提取表格数据?

google-chrome - Selenium 不启动可移植 chrome 而是本地安装

javascript - 从内容脚本访问选项页面 localStorage

javascript - Chrome 扩展程序可从外部连接所有网址

c++ - 两个数组的内存地址重叠

java - Matlab内存管理; java堆不足

javascript - 用户登录身份验证如何与 React Native 一起工作?

javascript - 错误 - 权限被拒绝 - jQuery 打印预览?

javascript - 使用 gulp-watch 和 gulp-develop-server 重新加载 cucumber.js 步骤