The sample

while (true) {
  console.log("Hello, World!");
}
Copy the code

Output shortly after

. Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! <-- Last few GCs --> 710976 MS: Mark-sweep 698.3 (737.7) --> 698.3 (737.7) MB, 15343.7/0 ms [allocation Failure] [GCin726188 MS: Mark-sweep 698.3 (737.7) -> 698.3 (737.7) MB, 15212.6/0 MS [Allocation failure] [GC]inold space requested]. 741831 ms: Mark-sweep 698.3 (737.7) -> 698.3 (737.7) MB, 15642.7/0 MS [Last Resort GC]. 757723 MS: Mark-sweep 698.3 (737.7) -> 698.3 (737.7) MB, 15892.2/0 [ms last resort mixes gc]. < -- - JS stacktrace - > = = = = JS stack trace = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Security context: 0x37c258b9 <JS Object> 1: nextTick [node.js:~465] [pc=0x341fac9c] (this=0x37c7f939 <a process with map 0x563136b1>,callback=0x3e7bf5e1 <JS Function afterWrite (SharedFunctionInfo 0x3e777679)>) 2: arguments adaptor frame: 5->1 3: onwrite(aka onwrite) [_stream_writable.js:~314] [pc=0x341f3f50] (this=0x37c08099 <undefined>,stream=0x3e7bf6b1 <a WriteStream with map 0x56322bc9>,er=0x37c08099 <undefined>) 4: _w... FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory AbortedCopy the code

In a Node environment, just output a string. Why is it out of memory? This is a known “problem” because writing to STdout is asynchronous in the case of tty/console. Therefore, if tty/Console can’t keep up, recording a lot of data very quickly is likely to result in a lot of write buffers in memory.

The key code for console is as follows

// internal/console/constructor.js
Console.prototype[kBindStreamsLazy] = function(object) {
  let stdout;
  let stderr;
  Object.defineProperties(this, {
    '_stdout': {
      enumerable: false,
      configurable: true.get() {
        if(! stdout) stdout = object.stdout;return stdout;
      },
      set(value) { stdout = value; }},'_stderr': {
      enumerable: false,
      configurable: true.get() {
        if(! stderr) { stderr = object.stderr; }return stderr;
      },
      set(value) { stderr = value; }}}); };Copy the code

Take a closer look at the _stdout object. When we run the JS code and execute console.log, the _stdout object is called. So where is the content cached when it is output? Continue with the code below

// _http_common.js
const parsers = new FreeList('parsers', 1000, function parsersCb() {
  const parser = new HTTPParser();

  cleanParser(parser);

  parser.onIncoming = null;
  parser[kOnHeaders] = parserOnHeaders;
  parser[kOnHeadersComplete] = parserOnHeadersComplete;
  parser[kOnBody] = parserOnBody;
  parser[kOnMessageComplete] = parserOnMessageComplete;

  return parser;
});
Copy the code

So when the request comes in, the new FreeList above is going to apply for a buffer of size 1000, so what does the FreeList do

// freelist.js constructor(name, max, ctor) { this.name = name; this.ctor = ctor; this.max = max; this.list = []; }... free(obj) {if (this.list.length < this.max) {
      this.list.push(obj);
      return true;
    }
    return false;
  }
Copy the code

When free is called, obj is pressed into the list. When the program is running, if console.log output is frequent, the memory footprint will be high before GC.

Conclusion: Production environments are better off without console.log. Output to a file can solve the memory footprint of console.log.