我试图了解这个分配一兆字节的简单代码:
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();
4次轻微gc循环(清除)的结果。如您所见,我们明确将新空间的大小设置为1兆字节。预期的结果是看到一个清除,但我不明白为什么我们看到四个。
➜ ~ d8
V8 version 4.5.103.35 [console: readline]
➜ ~ d8 --trace_gc --trace_gc_verbose --min_semi_space_size=1 --max_semi_space_size=1 --target_semi_space_size=1 --semi_space_growth_factor=0 allocateMB.js
[2853:0x7fa1fa012600] 6 ms: Scavenge 1.7 (36.9) -> 1.2 (36.9) MB, 0.3 / 0 ms [allocation failure].
[2853:0x7fa1fa012600] Memory allocator, used: 37752 KB, available: 1461384 KB
[2853:0x7fa1fa012600] New space, used: 281 KB, available: 726 KB, committed: 2015 KB
[2853:0x7fa1fa012600] Old space, used: 674 KB, available: 0 KB, committed: 794 KB
[2853:0x7fa1fa012600] Code space, used: 194 KB, available: 0 KB, committed: 261 KB
[2853:0x7fa1fa012600] Map space, used: 34 KB, available: 0 KB, committed: 59 KB
[2853:0x7fa1fa012600] Large object space, used: 0 KB, available: 1460343 KB, committed: 0 KB
[2853:0x7fa1fa012600] All spaces, used: 1185 KB, available: 1461069 KB, committed: 3130 KB
[2853:0x7fa1fa012600] External memory reported: 0 KB
[2853:0x7fa1fa012600] Total time spent in GC : 0.3 ms
[2853:0x7fa1fa012600] 7 ms: Scavenge 1.5 (36.9) -> 1.3 (36.9) MB, 0.4 / 0 ms [allocation failure].
[2853:0x7fa1fa012600] Memory allocator, used: 37752 KB, available: 1461384 KB
[2853:0x7fa1fa012600] New space, used: 397 KB, available: 610 KB, committed: 2015 KB
[2853:0x7fa1fa012600] Old space, used: 691 KB, available: 0 KB, committed: 794 KB
[2853:0x7fa1fa012600] Code space, used: 194 KB, available: 0 KB, committed: 261 KB
[2853:0x7fa1fa012600] Map space, used: 34 KB, available: 0 KB, committed: 59 KB
[2853:0x7fa1fa012600] Large object space, used: 0 KB, available: 1460343 KB, committed: 0 KB
[2853:0x7fa1fa012600] All spaces, used: 1317 KB, available: 1460954 KB, committed: 3130 KB
[2853:0x7fa1fa012600] External memory reported: 0 KB
[2853:0x7fa1fa012600] Total time spent in GC : 0.7 ms
[2853:0x7fa1fa012600] 8 ms: Scavenge 1.9 (36.9) -> 1.5 (36.9) MB, 0.2 / 0 ms [allocation failure].
[2853:0x7fa1fa012600] Memory allocator, used: 37752 KB, available: 1461384 KB
[2853:0x7fa1fa012600] New space, used: 596 KB, available: 411 KB, committed: 2015 KB
[2853:0x7fa1fa012600] Old space, used: 691 KB, available: 0 KB, committed: 794 KB
[2853:0x7fa1fa012600] Code space, used: 194 KB, available: 0 KB, committed: 261 KB
[2853:0x7fa1fa012600] Map space, used: 34 KB, available: 0 KB, committed: 59 KB
[2853:0x7fa1fa012600] Large object space, used: 0 KB, available: 1460343 KB, committed: 0 KB
[2853:0x7fa1fa012600] All spaces, used: 1516 KB, available: 1460755 KB, committed: 3130 KB
[2853:0x7fa1fa012600] External memory reported: 0 KB
[2853:0x7fa1fa012600] Total time spent in GC : 0.9 ms
[2853] Limited new space size due to high promotion rate: 1 MB
[2853:0x7fa1fa012600] 8 ms: Scavenge 1.5 (36.9) -> 1.5 (37.9) MB, 0.7 / 0 ms [allocation failure].
[2853:0x7fa1fa012600] Memory allocator, used: 38776 KB, available: 1460360 KB
[2853:0x7fa1fa012600] New space, used: 0 KB, available: 1007 KB, committed: 2015 KB
[2853:0x7fa1fa012600] Old space, used: 1287 KB, available: 102 KB, committed: 1801 KB
[2853:0x7fa1fa012600] Code space, used: 194 KB, available: 0 KB, committed: 261 KB
[2853:0x7fa1fa012600] Map space, used: 34 KB, available: 0 KB, committed: 59 KB
[2853:0x7fa1fa012600] Large object space, used: 0 KB, available: 1459319 KB, committed: 0 KB
[2853:0x7fa1fa012600] All spaces, used: 1516 KB, available: 1460430 KB, committed: 4138 KB
[2853:0x7fa1fa012600] External memory reported: 0 KB
[2853:0x7fa1fa012600] Total time spent in GC : 1.6 ms
答案 0 :(得分:3)
似乎新空间使用的是semi-space allocation strategy(参见“Deep Dive ...”),所以它不一定是1MB的限制。实际上,似乎最多允许填充80%新空间。
还有一种通过更改分配限制来确保快速清除的机制(参见80%链接中的第55行)。所以GC行为并不像看起来那么简单,但阅读V8源代码和注释可以提供很好的提示。
答案 1 :(得分:1)
“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
之前,FixedArray
垃圾值为531778 * 4 + 22 * 2 * 4 =
2127288
字节或64位4254576
字节。此外,177481
的最后一个垃圾数组甚至无法在新空间中分配,因为它在64位中需要1419864个字节。
对于尺寸最大为10万件的小型阵列,您可以通过new Array(size)
跳过浪费的大小调整。
我使用未知数组大小的技巧是给出近似值,然后重置长度:
var myArray = new Array(1024)
myArray.length = 0;
// Can now use .push without having to resize the backing array