http: optimize checkInvalidHeaderChar()
This commit optimizes checkInvalidHeaderChar() by unrolling the character checking loop a bit. Additionally, some changes to the benchmark runner are needed in order for the included benchmark to be run correctly. Specifically, the regexp used to parse `key=value` parameters contained a greedy quantifier that was causing the `key` to match part of the `value` if `value` contained an equals sign. PR-URL: https://github.com/nodejs/node/pull/6570 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com>
This commit is contained in:
parent
918159e0f6
commit
83432bfff1
@ -191,7 +191,7 @@ function parseOpts(options) {
|
|||||||
var num = keys.length;
|
var num = keys.length;
|
||||||
var conf = {};
|
var conf = {};
|
||||||
for (var i = 2; i < process.argv.length; i++) {
|
for (var i = 2; i < process.argv.length; i++) {
|
||||||
var match = process.argv[i].match(/^(.+)=(.*)$/);
|
var match = process.argv[i].match(/^(.+?)=([\s\S]*)$/);
|
||||||
if (!match || !match[1] || !options[match[1]]) {
|
if (!match || !match[1] || !options[match[1]]) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -238,8 +238,6 @@ Benchmark.prototype.report = function(value) {
|
|||||||
console.log('%s: %s', heading, value.toFixed(5));
|
console.log('%s: %s', heading, value.toFixed(5));
|
||||||
else if (outputFormat == 'csv')
|
else if (outputFormat == 'csv')
|
||||||
console.log('%s,%s', heading, value.toFixed(5));
|
console.log('%s,%s', heading, value.toFixed(5));
|
||||||
|
|
||||||
process.exit(0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Benchmark.prototype.getHeading = function() {
|
Benchmark.prototype.getHeading = function() {
|
||||||
@ -247,11 +245,11 @@ Benchmark.prototype.getHeading = function() {
|
|||||||
|
|
||||||
if (outputFormat == 'default') {
|
if (outputFormat == 'default') {
|
||||||
return this._name + ' ' + Object.keys(conf).map(function(key) {
|
return this._name + ' ' + Object.keys(conf).map(function(key) {
|
||||||
return key + '=' + conf[key];
|
return key + '=' + JSON.stringify('' + conf[key]);
|
||||||
}).join(' ');
|
}).join(' ');
|
||||||
} else if (outputFormat == 'csv') {
|
} else if (outputFormat == 'csv') {
|
||||||
return this._name + ',' + Object.keys(conf).map(function(key) {
|
return this._name + ',' + Object.keys(conf).map(function(key) {
|
||||||
return conf[key];
|
return JSON.stringify('' + conf[key]);
|
||||||
}).join(',');
|
}).join(',');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
42
benchmark/http/check_invalid_header_char.js
Normal file
42
benchmark/http/check_invalid_header_char.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common.js');
|
||||||
|
const _checkInvalidHeaderChar = require('_http_common')._checkInvalidHeaderChar;
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
key: [
|
||||||
|
// Valid
|
||||||
|
'',
|
||||||
|
'1',
|
||||||
|
'\t\t\t\t\t\t\t\t\t\tFoo bar baz',
|
||||||
|
'keep-alive',
|
||||||
|
'close',
|
||||||
|
'gzip',
|
||||||
|
'20091',
|
||||||
|
'private',
|
||||||
|
'text/html; charset=utf-8',
|
||||||
|
'text/plain',
|
||||||
|
'Sat, 07 May 2016 16:54:48 GMT',
|
||||||
|
'SAMEORIGIN',
|
||||||
|
'en-US',
|
||||||
|
|
||||||
|
// Invalid
|
||||||
|
'Here is a value that is really a folded header value\r\n this should be \
|
||||||
|
supported, but it is not currently',
|
||||||
|
'中文呢', // unicode
|
||||||
|
'foo\nbar',
|
||||||
|
'\x7F'
|
||||||
|
],
|
||||||
|
n: [5e8],
|
||||||
|
});
|
||||||
|
|
||||||
|
function main(conf) {
|
||||||
|
var n = +conf.n;
|
||||||
|
var key = conf.key;
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
_checkInvalidHeaderChar(key);
|
||||||
|
}
|
||||||
|
bench.end(n);
|
||||||
|
}
|
@ -301,13 +301,32 @@ exports._checkIsHttpToken = checkIsHttpToken;
|
|||||||
* field-value = *( field-content / obs-fold )
|
* field-value = *( field-content / obs-fold )
|
||||||
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||||
* field-vchar = VCHAR / obs-text
|
* field-vchar = VCHAR / obs-text
|
||||||
|
*
|
||||||
|
* checkInvalidHeaderChar() is currently designed to be inlinable by v8,
|
||||||
|
* so take care when making changes to the implementation so that the source
|
||||||
|
* code size does not exceed v8's default max_inlined_source_size setting.
|
||||||
**/
|
**/
|
||||||
function checkInvalidHeaderChar(val) {
|
function checkInvalidHeaderChar(val) {
|
||||||
val = '' + val;
|
val += '';
|
||||||
for (var i = 0; i < val.length; i++) {
|
if (val.length < 1)
|
||||||
const ch = val.charCodeAt(i);
|
return false;
|
||||||
if (ch === 9) continue;
|
var c = val.charCodeAt(0);
|
||||||
if (ch <= 31 || ch > 255 || ch === 127) return true;
|
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
|
||||||
|
return true;
|
||||||
|
if (val.length < 2)
|
||||||
|
return false;
|
||||||
|
c = val.charCodeAt(1);
|
||||||
|
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
|
||||||
|
return true;
|
||||||
|
if (val.length < 3)
|
||||||
|
return false;
|
||||||
|
c = val.charCodeAt(2);
|
||||||
|
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
|
||||||
|
return true;
|
||||||
|
for (var i = 3; i < val.length; ++i) {
|
||||||
|
c = val.charCodeAt(i);
|
||||||
|
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user