什么是释放大型数组内存的正确方法?

3

我正在使用canvas进行图像处理。

用户每次会选择10张照片(通常是高分辨率照片),然后脚本会在上传到服务器之前对这些照片进行处理。

这个过程将创建大型数组并消耗大量内存。因此,我想知道以下选项中哪一种是释放内存的正确方法。

选项1: 不做任何操作,让GC处理内存使用情况。

for(int i=0;i<10;i++) {
    var bigArray = new Array(20000000);
    //do something with bigArray
}

选项2:设置为null

for(int i=0;i<10;i++) {
    var bigArray = new Array(20000000);
    //do something with bigArray

    bigArray=null;  
}

选项3:在释放数组内容后将其设置为null

for(int i=0;i<10;i++) {
    var bigArray=new Array(20000000);

    //do something with bigArray

    bigArray=[];
    bigArray=null;  
}

选项4:在将数组长度设置为零后设置为空。

for(int i=0;i<10;i++) {
    var bigArray=new Array(20000000);
    //do something with bigArray
    bigArray.length=0;
    bigArray=null;  
}

将其设置为null就足够了。其他选项(如分配空数组等)没有任何好处,因为堆将在下一次GC时被清除。 - Randy Casburn
谢谢您的回答。我刚刚测试了bigArray = []; bigArray = null; 和 bigArray.length = 0; 这三种方法都可以很好地释放大数组。根据您的回答,您是不是意味着bigArray = null 是以上三种方法中最可取的一种? - xw uwo
3个回答

2
将其设置为 null 或设置为空数组、未定义的空字符串或其他选项都可以使数据有资格进行垃圾回收,以使内容更易理解。保留 html 标签,请注意:在您的第一个示例(使用 var)中,由于您将全局范围的引用存储到 var 中,因此它不会成为垃圾回收的对象。

for(i=0;i<10; i++){
   var pippo = "TEST";
}
console.log(pippo);


1
感谢您的提醒。是的,在示例中,“var”语句确实会占用内存,除非您在控制台中手动调用GC。应该使用“let”。 - xw uwo

2

bigArray如果失去所有引用,将会被完全垃圾回收。例如:

// 代码片段

 bigArray = [];

最初的回答丢失后,数组被垃圾回收,bigArray 指向一个新的空数组。代码如下:

bigArray = null;

最初的回答中引用也会丢失。使用时需注意。
bigArray.length = 0;

数组将失去对其存储值的引用,只有数组本身留在内存中。

现在您应该这样做(而不是创建一个泄漏循环外的变量并手动管理其取消引用):

只需正确定义范围,它就会自动取消引用:

最初的回答:

for(let i = 0; i < 10; i++) {
  let bigArray = new Array(20000000);

   //do something with bigArray
   //...
   // array gets recycled here
}

附带说明:

Array(20000000)只是一个数组声明,并不会占用太多空间,真正占用空间的是数组中存储的实际值。


1
旁注是错误的,请在控制台设置之前和之后尝试打开Chrome的内存配置文件:var p = new Array(1000000) 这将占用约8MB的内存。 - Mosè Raguzzini
@mosè,你肯定误解了控制台。 - Jonas Wilms
1
也许你也错过了什么:http://www.mattzeunert.com/2016/07/24/javascript-array-object-sizes.html - Mosè Raguzzini
谢谢@Mosè Raguzzini。我刚测试了,bigArray = []; bigArray = null; 和 bigArray.length = 0; 都可以很好地释放大数组。我有一个额外的问题,做完一些操作后,我们不再需要bigArray,只想释放它的内存,在这种情况下,上述哪种方法(bigArray = []; bigArray = null; 和 bigArray.length = 0;)是推荐的?还是它们之间没有显着的区别?由于兼容性原因,我现在不能使用let语句。 - xw uwo
1
关于Sidenote的讨论,我也进行了测试。看起来它取决于浏览器。在Firefox中,new Array(20000000)不会消耗内存,而Chrome将占用约8MB。 - xw uwo
@xwuwo 它们几乎做相同的事情(请看我的回答)。也许 null 或空数组是更语义化的选项,因为真正的区别在于另一个开发人员将如何阅读您的代码以理解它。关于旁注:是的,不同的浏览器引擎行为不同。 - Mosè Raguzzini

1

你好,

bigArray = null;

如果您想要将变量用于其他类型,请重新使用该变量。
bigArray = [];

如果您想将其作为数组重复使用。
delete bigArray;

如果你已经完成了这个变量。

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