-
-
Notifications
You must be signed in to change notification settings - Fork 33k
Closed
Labels
httpIssues or PRs related to the http subsystem.Issues or PRs related to the http subsystem.memoryIssues and PRs related to the memory management or memory footprint.Issues and PRs related to the memory management or memory footprint.
Description
- Version:
v7.7.3 - Platform:
macOS/Linux - Subsystem:
net/http
I noticed that n
socket connections obtained with the HTTP upgrade mechanism use a lot more memory than n
socket connections obtained with a plain net server. Consider for example the following test.
net server
'use strict';
const net = require('net');
const headers = [
'HTTP/1.1 101 Switching Protocols',
'Connection: Upgrade',
'Upgrade: foo',
'',
''
].join('\r\n');
let count = 0;
const handler = (socket) => {
socket.resume();
socket.write(headers);
if (++count === 150000) {
gc();
const rss = process.memoryUsage().rss;
console.log(rss / 1024 / 1024);
}
};
const server = net.createServer({ allowHalfOpen: true });
server.on('connection', handler);
server.listen(3000, () => console.log('listening on *:3000'));
net client
'use strict';
const net = require('net');
const headers = [
'GET / HTTP/1.1',
'Connection: Upgrade',
'Upgrade: foo',
'Host: localhost:3000',
'',
''
].join('\r\n');
let i = 0;
(function createClient() {
const socket = net.connect({
localAddress: `127.0.0.${i % 100 + 1}`,
port: 3000
});
socket.on('connect', () => {
socket.resume();
socket.write(headers);
if (++i === 150000) return;
createClient();
});
})();
http server
'use strict';
const http = require('http');
const headers = [
'HTTP/1.1 101 Switching Protocols',
'Connection: Upgrade',
'Upgrade: foo',
'',
''
].join('\r\n');
let count = 0;
const handler = (req, socket, head) => {
socket.resume();
socket.write(headers);
if (++count === 150000) {
gc();
const rss = process.memoryUsage().rss;
console.log(rss / 1024 / 1024);
}
};
const server = http.createServer();
server.setTimeout(0);
server.on('upgrade', handler);
server.listen(3000, () => console.log('listening on *:3000'));
http client
'use strict';
const http = require('http');
let i = 0;
(function createClient() {
const req = http.get({
localAddress: `127.0.0.${i % 100 + 1}`,
port: 3000,
headers: {
'Connection': 'Upgrade',
'Upgrade': 'foo'
}
});
req.on('upgrade', (res, socket, head) => {
socket.resume();
if (++i === 150000) return;
createClient();
});
})();
The first (net) server uses ~295 MiB of memory while the second (http) ~525 MiB. Shouldn't they use more or less the same amount of memory?
It seems that, in part, the difference is caused by the additional event listeners. If I add
socket.removeAllListeners('drain');
socket.removeAllListeners('error');
socket.removeAllListeners('timeout');
in the upgrade
event handler, memory usage drops to ~420 MiB.
Metadata
Metadata
Assignees
Labels
httpIssues or PRs related to the http subsystem.Issues or PRs related to the http subsystem.memoryIssues and PRs related to the memory management or memory footprint.Issues and PRs related to the memory management or memory footprint.