这段代码
const file = require("fs").createWriteStream("./test.dat");
for(var i = 0; i < 1e7; i++){
file.write("a");
}
运行约30秒后会显示此错误消息
<--- Last few GCs --->
[47234:0x103001400] 27539 ms: Mark-sweep 1406.1 (1458.4) -> 1406.1 (1458.4) MB, 2641.4 / 0.0 ms allocation failure GC in old space requested
[47234:0x103001400] 29526 ms: Mark-sweep 1406.1 (1458.4) -> 1406.1 (1438.9) MB, 1986.8 / 0.0 ms last resort GC in old spacerequested
[47234:0x103001400] 32154 ms: Mark-sweep 1406.1 (1438.9) -> 1406.1 (1438.9) MB, 2628.3 / 0.0 ms last resort GC in old spacerequested
<--- JS stacktrace --->
==== JS stack trace =========================================
Security context: 0x30f4a8e25ee1 <JSObject>
1: /* anonymous */ [/Users/matthewschupack/dev/streamTests/1/write.js:~1] [pc=0x270efe213894](this=0x30f4e07ed2f1 <Object map = 0x30f4ede823b9>,exports=0x30f4e07ed2f1 <Object map = 0x30f4ede823b9>,require=0x30f4e07ed2a9 <JSFunction require (sfi = 0x30f493b410f1)>,module=0x30f4e07ed221 <Module map = 0x30f4edec1601>,__filename=0x30f493b47221 <String[49]: /Users/matthewschupack/dev/streamTests/...
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
1: node::Abort() [/usr/local/bin/node]
2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/bin/node]
3: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/local/bin/node]
4: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/bin/node]
5: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
6: 0x270efe08463d
7: 0x270efe213894
8: 0x270efe174048
[1] 47234 abort node write.js
尽管这段代码
const file = require("fs").createWriteStream("./test.dat");
for(var i = 0; i < 1e6; i++){
file.write("aaaaaaaaaa");//ten a's
}
完美运行几乎瞬间并生成一个10MB的文件。据我所知,流的重点是两个版本应该在大约相同的时间内运行,因为数据是相同的。即使将a
的数量增加到每个迭代的100或1000个,也几乎不会增加运行时间,并且可以写入1GB的文件而没有任何问题。每次迭代以1e6的速度写入单个字符也能正常工作。
这里发生了什么?
1e7
会导致内存溢出,但是您应该能够通过使用drain
事件来避免OOM并尊重反压。如果需要在下一次写入之前等待,则file.write(...)
返回false
。文档中有一个示例:https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback - Robbie