Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Memory leak using http's request/get/clientRequest and closures #3179

@vvo

Description

@vvo

Using nodejs 0.6.15 on Linux 64bits Debian Wheezy.

I made a small test file that is leaking memory when using http.get.
It seems that callback functions are retained.

The test just use http.get on a lot of google domains.

https://gist.github.com/2488897

var
  http = require('http'),
  extensions = ['com', 'ac', 'ad', 'ae', 'com.af', 'com.ag', 'com.ai', 'am', 'it.ao', 'com.ar', 'as', 'at', 'com.au', 'az', 'ba', 'com.bd', 'be', 'bf', 'bg', 'com.bh', 'bi', 'bj', 'com.bn', 'com.bo', 'com.br', 'bs', 'co.bw', 'com.by', 'com.bz', 'ca', 'com.kh', 'cc', 'cd', 'cf', 'cat', 'cg', 'ch', 'ci', 'co.ck', 'cl', 'cm', 'cn', 'com.co', 'co.cr', 'com.cu', 'cv', 'cz', 'de', 'dj', 'dk', 'dm', 'com.do', 'dz', 'com.ec', 'ee', 'com.eg', 'es', 'com.et', 'fi', 'com.fj', 'fm', 'fr', 'ga', 'gd', 'ge', 'gf', 'gg', 'com.gh', 'com.gi', 'gl', 'gm', 'gp', 'gr', 'com.gt', 'gy', 'com.hk', 'hn', 'hr', 'ht', 'hu', 'co.id', 'iq', 'ie', 'co.il', 'im', 'co.in', 'io', 'is', 'it', 'je', 'com.jm', 'jo', 'co.jp', 'co.ke', 'com.kh', 'ki', 'kg', 'co.kr', 'com.kw', 'kz', 'la', 'com.lb', 'com.lc', 'li', 'lk', 'co.ls', 'lt', 'lu', 'lv', 'com.ly', 'co.ma', 'md', 'me', 'mg', 'mk', 'ml', 'mn', 'ms', 'com.mt', 'mu', 'mv', 'mw', 'com.mx', 'com.my', 'co.mz', 'com.na', 'ne', 'com.nf', 'com.ng', 'com.ni', 'nl', 'no', 'com.np', 'nr', 'nu', 'co.nz', 'com.om', 'com.pa', 'com.pe', 'com.ph', 'com.pk', 'pl', 'pn', 'com.pr', 'ps', 'pt', 'com.py', 'com.qa', 'ro', 'rs', 'ru', 'rw', 'com.sa', 'com.sb', 'sc', 'se', 'com.sg', 'sh', 'si', 'sk', 'com.sl', 'sn', 'sm', 'so', 'st', 'com.sv', 'td', 'tg', 'co.th', 'com.tj', 'tk', 'tl', 'tm', 'to', 'com.tn', 'com.tr', 'tt', 'com.tw', 'co.tz', 'com.ua', 'co.ug', 'co.uk', 'us', 'com.uy', 'co.uz', 'com.vc', 'co.ve', 'vg', 'co.vi', 'com.vn', 'vu', 'ws', 'co.za', 'co.zm', 'co.zw'],
  nbloop = 9, nblaunch = 2, done = 0, todo = nblaunch*nbloop*extensions.length;

console.log('We should do '+ todo +' requests');

// show memused and progress while running
setInterval(status, 5000);status();

// 2 launch
loop();setTimeout(loop, 10000);

function loop() {
  console.log('Starting a new request loop');
  for(var i = 0; i < nbloop; i++) {
    getall();
  }
}

function getall() {
  // creates a big buffer
  var megabig = new Big();

  // this should not trigger a memory leak but it does when using http.get
  function cb() {
    done+=1;
    return megabig;
  }

  extensions.forEach(function(ext) {
    // using setTimeout instead of http.get shows no mem leak
    // setTimeout(cb, 10);

    http.get({
      hostname: 'www.google.' + ext,
      pathname: '/index.html?' + Math.random(),
      port: 80,
      protocol: 'http:'
    }, cb);
  });
}

function Big() {
  this.yo = (new Buffer(1 * 1024 * 1024 * 3)).toString();
}

function status() {
  console.log((process.memoryUsage().heapUsed/1024/1024).toFixed() + 'MB used');
  console.log('Done: '+ done +'/'+ todo);
  if (done === todo) {
    console.log('all requests done, memory should be collected by now ?')
  }
}

After all requests are done, I get ~105MB used memory that will not be freed.
Calling cb() with setTimeout does not leak so it is http related.

I'm using a lot of # domains because memory usage goes up the more domains I have.

Using https://github.com/c4milo/node-webkit-agent (great great tool) I was able to get this retain paths:
Memory leak

And after looking at http.js it seems I solved this, you decide.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions