动态创建全局范围的变量

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

在 Node.js 中(如果您想知道:v16.15.0):

我想一遍又一遍地创建全局变量,直到我的计算机的堆栈/堆没有更多空间,并且出现错误。我认为以下代码可以做到这一点:

for (let i = 0; true; i++) {
    eval('var a' + i + ' = "I will break you."')
}

但是当我运行代码时,我等了几分钟,它继续运行,显然没有破坏我的记忆。为什么它不会导致我的内存溢出,我该如何修改它来实现这一点?

附言- 我知道在循环中用

let
声明变量会使变量作用域限定在该块内,但我认为
var
在这种情况下是全局作用域。显然不是?

javascript node.js memory eval
1个回答
0
投票

我认为你有一个特殊的测试,强调 v8 分配器/垃圾收集器,导致它在耗尽内存堆之前卡住。

稍微修改您的循环,并使用

--trace-gc
运行节点突出显示进度停止的地方。

for (let i = 1; true; i++) {
  if (i%10000 === 0) console.log(i)
  eval(`var a${i} = "I will break you."`)
}

在我的本地节点上,在 8388608 个变量之后,循环不会进行太多,因为每次分配(即迭代)都会触发 GC。

8388601
8388602
8388603
8388604
8388605
8388606
8388607
8388608
8388609
[97743:0x7f9c58078000]    97804 ms: Scavenge 2062.5 (2831.9) -> 1995.0 (2767.9) MB, 5.4 / 0.0 ms  (average mu = 0.896, current mu = 0.827) allocation failure; 
8388610
[97743:0x7f9c58078000]   100681 ms: Scavenge 2059.0 (2831.9) -> 1994.9 (2767.9) MB, 2.5 / 0.0 ms  (average mu = 0.896, current mu = 0.827) allocation failure; 
8388611
[97743:0x7f9c58078000]   103477 ms: Scavenge 2058.9 (2831.9) -> 1994.9 (2736.9) MB, 1.5 / 0.0 ms  (average mu = 0.896, current mu = 0.827) allocation failure; 
8388612
[97743:0x7f9c58078000]   106332 ms: Scavenge 2058.9 (2800.9) -> 1994.9 (2736.9) MB, 1.9 / 0.0 ms  (average mu = 0.896, current mu = 0.827) allocation failure; 
8388613
[97743:0x7f9c58078000]   109183 ms: Scavenge 2058.9 (2800.9) -> 1994.9 (2736.9) MB, 1.4 / 0.0 ms  (average mu = 0.896, current mu = 0.827) allocation failure; 

耗尽堆的更快方法是避免

eval
并将引用存储到更长、不同的字符串。

let a = {}
for (let i = 0; true; i++) {
  a[i] = "I will break you."+i+i+i+i
}
% node --trace-gc break.js
[97778:0x7faec0078000]       30 ms: Scavenge 6.0 (6.3) -> 5.8 (7.3) MB, 1.2 / 0.0 ms  (average mu = 1.000, current mu = 1.000) allocation failure; 
[97778:0x7faec0078000]       31 ms: Scavenge 6.0 (7.3) -> 5.9 (8.1) MB, 0.8 / 0.0 ms  (average mu = 1.000, current mu = 1.000) allocation failure; 
[97778:0x7faec0078000]       32 ms: Scavenge 6.7 (8.1) -> 6.8 (10.6) MB, 0.6 / 0.0 ms  (average mu = 1.000, current mu = 1.000) allocation failure; 
[97778:0x7faec0078000]       36 ms: Scavenge 8.0 (10.8) -> 7.8 (11.5) MB, 1.6 / 0.0 ms  (average mu = 1.000, current mu = 1.000) allocation failure; 
[97778:0x7faec0078000]       38 ms: Scavenge 8.7 (11.5) -> 8.8 (16.5) MB, 0.9 / 0.0 ms  (average mu = 1.000, current mu = 1.000) allocation failure; 
<snip>
[97778:0x7faec0078000]    29994 ms: Scavenge 3990.3 (4071.6) -> 3991.9 (4073.1) MB, 10.7 / 0.0 ms  (average mu = 0.222, current mu = 0.199) allocation failure; 
[97778:0x7faec0078000]    30019 ms: Scavenge 3992.0 (4073.1) -> 3990.3 (4087.6) MB, 24.2 / 0.0 ms  (average mu = 0.222, current mu = 0.199) allocation failure; 
[97778:0x7faec0078000]    30037 ms: Scavenge 4006.0 (4087.6) -> 4007.7 (4089.1) MB, 10.0 / 0.0 ms  (average mu = 0.222, current mu = 0.199) allocation failure; 
[97778:0x7faec0078000]    30058 ms: Scavenge 4007.7 (4089.1) -> 4006.0 (4103.1) MB, 21.6 / 0.0 ms  (average mu = 0.222, current mu = 0.199) allocation failure; 

<--- Last few GCs --->

[97778:0x7faec0078000]    30019 ms: Scavenge 3992.0 (4073.1) -> 3990.3 (4087.6) MB, 24.2 / 0.0 ms  (average mu = 0.222, current mu = 0.199) allocation failure; 
[97778:0x7faec0078000]    30037 ms: Scavenge 4006.0 (4087.6) -> 4007.7 (4089.1) MB, 10.0 / 0.0 ms  (average mu = 0.222, current mu = 0.199) allocation failure; 
[97778:0x7faec0078000]    30058 ms: Scavenge 4007.7 (4089.1) -> 4006.0 (4103.1) MB, 21.6 / 0.0 ms  (average mu = 0.222, current mu = 0.199) allocation failure; 


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x101705fb5 node::Abort() (.cold.1) [/node-18.15.0/bin/node]
 2: 0x100186a29 node::Abort() [/node-18.15.0/bin/node]
 3: 0x100186c0e node::OOMErrorHandler(char const*, bool) [/node-18.15.0/bin/node]
 4: 0x100315cc3 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/node-18.15.0/bin/node]
 5: 0x1004de975 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/node-18.15.0/bin/node]
 6: 0x1004e2e40 v8::internal::Heap::CollectSharedGarbage(v8::internal::GarbageCollectionReason) [/node-18.15.0/bin/node]
 7: 0x1004df68f v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*, v8::GCCallbackFlags) [/node-18.15.0/bin/node]
 8: 0x1004dc768 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/node-18.15.0/bin/node]
 9: 0x1004db762 v8::internal::Heap::HandleGCRequest() [/node-18.15.0/bin/node]
10: 0x10047c681 v8::internal::StackGuard::HandleInterrupts() [/node-18.15.0/bin/node]
11: 0x1008e7bf8 v8::internal::Runtime_StackGuard(int, unsigned long*, v8::internal::Isolate*) [/node-18.15.0/bin/node]
12: 0x100cdddb9 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/node-18.15.0/bin/node]
13: 0x105a8cc08 
© www.soinside.com 2019 - 2024. All rights reserved.