Skip to content

Keepalive prevents garbage collection on unread responses #29394

@orgads

Description

@orgads

If keepAlive is enabled for the agent, and the response is not read by the client, the memory consumption grows very fast.

This is possibly similar (but not caused by) to recent fixes like #29297 and its predecessors.

const app = require('express')();
app.get('/test', (req, res) => res.sendFile(__filename));
app.listen(3000);

const http = require('http');
http.globalAgent.keepAlive = true;

setInterval(() => console.log(process.memoryUsage()), 1000);
setInterval(() => {
  http.get('http://127.0.0.1:3000/test', (res) => { /*res.resume();*/ });
}, 1);

If I uncomment res.resume() (or comment out keepAlive) then memory consumption is sane (around 120M). But when it is commented out, memory usage reaches 280M.

Using the inspector, I see that there are many stale Socket objects, which are retained by onIncoming in HTTPParser in FreeList. There are no application retainers. The application has no access to this IncomingMessage since it is not stored anywhere by the application, so it should be garbage collected eventually.

It looks like after a lot of time, this HTTPParser is reallocated for another request, and only then this response is GC'ed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    httpIssues or PRs related to the http subsystem.memoryIssues and PRs related to the memory management or memory footprint.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions