Javascript V8 GC何时触发其第一个小GC循环(扫气)?

Javascript V8 GC何时触发其第一个小GC循环(扫气)?,javascript,garbage-collection,v8,Javascript,Garbage Collection,V8,我试图理解这个分配1兆字节的简单代码: var BYTES_IN_MB = 1024 * 1024; // 1MB = 1024KB = 1024(KB/MB)*1024(B/KB) var BYTES_IN_SMI = 4; var NUM_SMIS_IN_MB = BYTES_IN_MB/BYTES_IN_SMI; var y = []; function allocateMB() { for(var i = 0; i < NUM_SMIS_IN_MB; i++) { y

我试图理解这个分配1兆字节的简单代码:

var BYTES_IN_MB = 1024 * 1024; // 1MB = 1024KB = 1024(KB/MB)*1024(B/KB)
var BYTES_IN_SMI = 4;
var NUM_SMIS_IN_MB = BYTES_IN_MB/BYTES_IN_SMI;

var y = [];
function allocateMB() {
  for(var i = 0; i < NUM_SMIS_IN_MB; i++) {
    y.push(i);
  }
}

allocateMB();

新空间似乎使用了深潜下的see…,因此它不一定是精确的1MB限制。事实上,似乎新空间的大部分都被允许填充


还有一种通过改变分配限制来确保快速清除的机制,请参见80%链接中的第55行。因此,GC行为并不像看上去那么简单,但是阅读V8源代码和注释可以提供很好的提示。

allocateMb显示了对数组大小的不完全理解。数组大小从4开始,每次需要调整大小时,数组大小都以x1.5+16增长。因此,实际上可以按如下方式调整阵列的大小:

4      (garbage so far: 4 * 4 + 1 * 2 * 4 =       24 bytes [48 in 64-bit])
22     (garbage so far: 26 * 4 + 2 * 2 * 4 =      120 bytes [240 in 64-bit])
49     (garbage so far: 75 * 4 + 3 * 2 * 4 =      324 bytes [648 in 64-bit])
89     (garbage so far: 164 * 4 + 4 * 2 * 4 =     688 bytes [1376 in 64-bit])
149    (garbage so far: 313 * 4 + 5 * 2 * 4 =     1292 bytes [2584 in 64-bit])
239    (garbage so far: 552 * 4 + 6 * 2 * 4 =     2256 bytes [4512 in 64-bit])
374    (garbage so far: 926 * 4 + 7 * 2 * 4 =     3760 bytes [7520 in 64-bit])
577    (garbage so far: 1503 * 4 + 8 * 2 * 4 =    6076 bytes [12152 in 64-bit])
881    (garbage so far: 2384 * 4 + 9 * 2 * 4 =    9608 bytes [19216 in 64-bit])
1337   (garbage so far: 3721 * 4 + 10 * 2 * 4 =   14964 bytes [29928 in 64-bit])
2021   (garbage so far: 5742 * 4 + 11 * 2 * 4 =   23056 bytes [46112 in 64-bit])
3047   (garbage so far: 8789 * 4 + 12 * 2 * 4 =   35252 bytes [70504 in 64-bit])
4586   (garbage so far: 13375 * 4 + 13 * 2 * 4 =  53604 bytes [107208 in 64-bit])
6895   (garbage so far: 20270 * 4 + 14 * 2 * 4 =  81192 bytes [162384 in 64-bit])
10358  (garbage so far: 30628 * 4 + 15 * 2 * 4 =  122632 bytes [245264 in 64-bit])
15553  (garbage so far: 46181 * 4 + 16 * 2 * 4 =  184852 bytes [369704 in 64-bit])
23345  (garbage so far: 69526 * 4 + 17 * 2 * 4 =  278240 bytes [556480 in 64-bit])
35033  (garbage so far: 104559 * 4 + 18 * 2 * 4 = 418380 bytes [836760 in 64-bit])
52565  (garbage so far: 157124 * 4 + 19 * 2 * 4 = 628648 bytes [1257296 in 64-bit])
78863  (garbage so far: 235987 * 4 + 20 * 2 * 4 = 944108 bytes [1888216 in 64-bit])
118310 (garbage so far: 354297 * 4 + 21 * 2 * 4 = 1417356 bytes [2834712 in 64-bit])
177481 (garbage so far: 531778 * 4 + 22 * 2 * 4 = 2127288 bytes [4254576 in 64-bit])
266237 (not garbage)
因此,在达到足够的大小266237之前,固定数组垃圾值为531778*4+22*2*4=2127288字节或4254576字节(64位)。此外,177481的最后一个垃圾数组甚至无法在新空间中分配,因为它在64位中占用1419864字节

对于大小不超过100k的较小阵列,您可以通过执行新的阵列大小调整跳过浪费的大小调整

我对未知数组大小使用的技巧是给出近似值,然后重置长度:

var myArray = new Array(1024)
myArray.length = 0;
// Can now use .push without having to resize the backing array

那么,如果在数组中插入更多/更少的数字会发生什么呢?有多少次清除?这是你期望的号码吗?为了回答这个问题,我建议设置一个断点并尝试通过读取堆栈跟踪来探索触发清除的是什么?为什么您希望看到一个清除?我最多只能看到一个,因为我只分配了一MB,这是通过-min_semi_space_size=1-max_semi_space_size=1设置的新空间的大小-目标\半\空间\大小=1个标志。当新空间满时,将触发清除。四次清除意味着新空间已满四次!但我只分配了1 MB。由于某些原因,我无法复制。您有哪个版本的v8?您的allocateMB甚至不需要分配一个兆字节。您是否研究了阵列的生长机制?它的大小能精确到1兆字节吗?
var myArray = new Array(1024)
myArray.length = 0;
// Can now use .push without having to resize the backing array