mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
http: improve performance for incoming headers
PR-URL: https://github.com/nodejs/node/pull/26041 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
This commit is contained in:
parent
9c9aefe2a0
commit
51982978eb
|
|
@ -25,8 +25,11 @@ class AutocannonBenchmarker {
|
|||
'-c', options.connections,
|
||||
'-j',
|
||||
'-n',
|
||||
`http://127.0.0.1:${options.port}${options.path}`,
|
||||
];
|
||||
for (const field in options.headers) {
|
||||
args.push('-H', `${field}=${options.headers[field]}`);
|
||||
}
|
||||
args.push(`http://127.0.0.1:${options.port}${options.path}`);
|
||||
const child = child_process.spawn(this.executable, args);
|
||||
return child;
|
||||
}
|
||||
|
|
|
|||
35
benchmark/http/incoming_headers.js
Normal file
35
benchmark/http/incoming_headers.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
const common = require('../common.js');
|
||||
const http = require('http');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
// unicode confuses ab on os x.
|
||||
c: [50, 500],
|
||||
headerDuplicates: [0, 5, 20]
|
||||
});
|
||||
|
||||
function main({ c, headerDuplicates }) {
|
||||
const server = http.createServer((req, res) => {
|
||||
res.end();
|
||||
});
|
||||
|
||||
server.listen(common.PORT, () => {
|
||||
const headers = {
|
||||
'Content-Type': 'text/plain',
|
||||
'Accept': 'text/plain',
|
||||
'User-Agent': 'nodejs-benchmark',
|
||||
'Date': new Date().toString(),
|
||||
'Cache-Control': 'no-cache'
|
||||
};
|
||||
for (let i = 0; i < headerDuplicates; i++) {
|
||||
headers[`foo${i}`] = `some header value ${i}`;
|
||||
}
|
||||
bench.http({
|
||||
path: '/',
|
||||
connections: c,
|
||||
headers
|
||||
}, () => {
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -135,133 +135,101 @@ function _addHeaderLines(headers, n) {
|
|||
// TODO: perhaps http_parser could be returning both raw and lowercased versions
|
||||
// of known header names to avoid us having to call toLowerCase() for those
|
||||
// headers.
|
||||
|
||||
// 'array' header list is taken from:
|
||||
// https://mxr.mozilla.org/mozilla/source/netwerk/protocol/http/src/nsHttpHeaderArray.cpp
|
||||
function matchKnownFields(field) {
|
||||
var low = false;
|
||||
while (true) {
|
||||
switch (field) {
|
||||
case 'Content-Type':
|
||||
case 'content-type':
|
||||
return 'content-type';
|
||||
case 'Content-Length':
|
||||
case 'content-length':
|
||||
return 'content-length';
|
||||
case 'User-Agent':
|
||||
case 'user-agent':
|
||||
return 'user-agent';
|
||||
case 'Referer':
|
||||
case 'referer':
|
||||
return 'referer';
|
||||
case 'Host':
|
||||
case 'host':
|
||||
return 'host';
|
||||
case 'Authorization':
|
||||
case 'authorization':
|
||||
return 'authorization';
|
||||
case 'Proxy-Authorization':
|
||||
case 'proxy-authorization':
|
||||
return 'proxy-authorization';
|
||||
case 'If-Modified-Since':
|
||||
case 'if-modified-since':
|
||||
return 'if-modified-since';
|
||||
case 'If-Unmodified-Since':
|
||||
case 'if-unmodified-since':
|
||||
return 'if-unmodified-since';
|
||||
case 'From':
|
||||
case 'from':
|
||||
return 'from';
|
||||
case 'Location':
|
||||
case 'location':
|
||||
function matchKnownFields(field, lowercased) {
|
||||
switch (field.length) {
|
||||
case 3:
|
||||
if (field === 'Age' || field === 'age') return 'age';
|
||||
break;
|
||||
case 4:
|
||||
if (field === 'Host' || field === 'host') return 'host';
|
||||
if (field === 'From' || field === 'from') return 'from';
|
||||
if (field === 'ETag' || field === 'etag') return 'etag';
|
||||
if (field === 'Date' || field === 'date') return '\u0000date';
|
||||
if (field === 'Vary' || field === 'vary') return '\u0000vary';
|
||||
break;
|
||||
case 6:
|
||||
if (field === 'Server' || field === 'server') return 'server';
|
||||
if (field === 'Cookie' || field === 'cookie') return '\u0002cookie';
|
||||
if (field === 'Origin' || field === 'origin') return '\u0000origin';
|
||||
if (field === 'Expect' || field === 'expect') return '\u0000expect';
|
||||
if (field === 'Accept' || field === 'accept') return '\u0000accept';
|
||||
break;
|
||||
case 7:
|
||||
if (field === 'Referer' || field === 'referer') return 'referer';
|
||||
if (field === 'Expires' || field === 'expires') return 'expires';
|
||||
if (field === 'Upgrade' || field === 'upgrade') return '\u0000upgrade';
|
||||
break;
|
||||
case 8:
|
||||
if (field === 'Location' || field === 'location')
|
||||
return 'location';
|
||||
case 'Max-Forwards':
|
||||
case 'max-forwards':
|
||||
return 'max-forwards';
|
||||
case 'Retry-After':
|
||||
case 'retry-after':
|
||||
return 'retry-after';
|
||||
case 'ETag':
|
||||
case 'etag':
|
||||
return 'etag';
|
||||
case 'Last-Modified':
|
||||
case 'last-modified':
|
||||
return 'last-modified';
|
||||
case 'Server':
|
||||
case 'server':
|
||||
return 'server';
|
||||
case 'Age':
|
||||
case 'age':
|
||||
return 'age';
|
||||
case 'Expires':
|
||||
case 'expires':
|
||||
return 'expires';
|
||||
case 'Set-Cookie':
|
||||
case 'set-cookie':
|
||||
return '\u0001';
|
||||
case 'Cookie':
|
||||
case 'cookie':
|
||||
return '\u0002cookie';
|
||||
// The fields below are not used in _addHeaderLine(), but they are common
|
||||
// headers where we can avoid toLowerCase() if the mixed or lower case
|
||||
// versions match the first time through.
|
||||
case 'Transfer-Encoding':
|
||||
case 'transfer-encoding':
|
||||
return '\u0000transfer-encoding';
|
||||
case 'Date':
|
||||
case 'date':
|
||||
return '\u0000date';
|
||||
case 'Connection':
|
||||
case 'connection':
|
||||
return '\u0000connection';
|
||||
case 'Cache-Control':
|
||||
case 'cache-control':
|
||||
return '\u0000cache-control';
|
||||
case 'Vary':
|
||||
case 'vary':
|
||||
return '\u0000vary';
|
||||
case 'Content-Encoding':
|
||||
case 'content-encoding':
|
||||
return '\u0000content-encoding';
|
||||
case 'Origin':
|
||||
case 'origin':
|
||||
return '\u0000origin';
|
||||
case 'Upgrade':
|
||||
case 'upgrade':
|
||||
return '\u0000upgrade';
|
||||
case 'Expect':
|
||||
case 'expect':
|
||||
return '\u0000expect';
|
||||
case 'If-Match':
|
||||
case 'if-match':
|
||||
if (field === 'If-Match' || field === 'if-match')
|
||||
return '\u0000if-match';
|
||||
case 'If-None-Match':
|
||||
case 'if-none-match':
|
||||
break;
|
||||
case 10:
|
||||
if (field === 'User-Agent' || field === 'user-agent')
|
||||
return 'user-agent';
|
||||
if (field === 'Set-Cookie' || field === 'set-cookie')
|
||||
return '\u0001';
|
||||
if (field === 'Connection' || field === 'connection')
|
||||
return '\u0000connection';
|
||||
break;
|
||||
case 11:
|
||||
if (field === 'Retry-After' || field === 'retry-after')
|
||||
return 'retry-after';
|
||||
break;
|
||||
case 12:
|
||||
if (field === 'Content-Type' || field === 'content-type')
|
||||
return 'content-type';
|
||||
if (field === 'Max-Forwards' || field === 'max-forwards')
|
||||
return 'max-forwards';
|
||||
break;
|
||||
case 13:
|
||||
if (field === 'Authorization' || field === 'authorization')
|
||||
return 'authorization';
|
||||
if (field === 'Last-Modified' || field === 'last-modified')
|
||||
return 'last-modified';
|
||||
if (field === 'Cache-Control' || field === 'cache-control')
|
||||
return '\u0000cache-control';
|
||||
if (field === 'If-None-Match' || field === 'if-none-match')
|
||||
return '\u0000if-none-match';
|
||||
case 'Accept':
|
||||
case 'accept':
|
||||
return '\u0000accept';
|
||||
case 'Accept-Encoding':
|
||||
case 'accept-encoding':
|
||||
break;
|
||||
case 14:
|
||||
if (field === 'Content-Length' || field === 'content-length')
|
||||
return 'content-length';
|
||||
break;
|
||||
case 15:
|
||||
if (field === 'Accept-Encoding' || field === 'accept-encoding')
|
||||
return '\u0000accept-encoding';
|
||||
case 'Accept-Language':
|
||||
case 'accept-language':
|
||||
if (field === 'Accept-Language' || field === 'accept-language')
|
||||
return '\u0000accept-language';
|
||||
case 'X-Forwarded-For':
|
||||
case 'x-forwarded-for':
|
||||
if (field === 'X-Forwarded-For' || field === 'x-forwarded-for')
|
||||
return '\u0000x-forwarded-for';
|
||||
case 'X-Forwarded-Host':
|
||||
case 'x-forwarded-host':
|
||||
break;
|
||||
case 16:
|
||||
if (field === 'Content-Encoding' || field === 'content-encoding')
|
||||
return '\u0000content-encoding';
|
||||
if (field === 'X-Forwarded-Host' || field === 'x-forwarded-host')
|
||||
return '\u0000x-forwarded-host';
|
||||
case 'X-Forwarded-Proto':
|
||||
case 'x-forwarded-proto':
|
||||
break;
|
||||
case 17:
|
||||
if (field === 'If-Modified-Since' || field === 'if-modified-since')
|
||||
return 'if-modified-since';
|
||||
if (field === 'Transfer-Encoding' || field === 'transfer-encoding')
|
||||
return '\u0000transfer-encoding';
|
||||
if (field === 'X-Forwarded-Proto' || field === 'x-forwarded-proto')
|
||||
return '\u0000x-forwarded-proto';
|
||||
default:
|
||||
if (low)
|
||||
return '\u0000' + field;
|
||||
field = field.toLowerCase();
|
||||
low = true;
|
||||
break;
|
||||
case 19:
|
||||
if (field === 'Proxy-Authorization' || field === 'proxy-authorization')
|
||||
return 'proxy-authorization';
|
||||
if (field === 'If-Unmodified-Since' || field === 'if-unmodified-since')
|
||||
return 'if-unmodified-since';
|
||||
break;
|
||||
}
|
||||
if (lowercased) {
|
||||
return '\u0000' + field;
|
||||
} else {
|
||||
return matchKnownFields(field.toLowerCase(), true);
|
||||
}
|
||||
}
|
||||
// Add the given (field, value) pair to the message
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user