http: speed up checkIsHttpToken
The Regex implementation is not faster than ascii code compare. the field name is shorter, the speed is faster. benchmark result here: https://bitbucket.org/snippets/JacksonTian/Rnbad/benchmark-result PR-URL: https://github.com/nodejs/node/pull/4790 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net>
This commit is contained in:
parent
293fd04535
commit
089c6a4fba
52
benchmark/http/check_is_http_token.js
Normal file
52
benchmark/http/check_is_http_token.js
Normal file
@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
const _checkIsHttpToken = require('_http_common')._checkIsHttpToken;
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
key: [
|
||||
'TCN',
|
||||
'ETag',
|
||||
'date',
|
||||
'Vary',
|
||||
'server',
|
||||
'Server',
|
||||
'status',
|
||||
'version',
|
||||
'Expires',
|
||||
'alt-svc',
|
||||
'location',
|
||||
'Connection',
|
||||
'Keep-Alive',
|
||||
'content-type',
|
||||
'Content-Type',
|
||||
'Cache-Control',
|
||||
'Last-Modified',
|
||||
'Accept-Ranges',
|
||||
'content-length',
|
||||
'x-frame-options',
|
||||
'x-xss-protection',
|
||||
'Content-Encoding',
|
||||
'Content-Location',
|
||||
'Transfer-Encoding',
|
||||
'alternate-protocol',
|
||||
':', // invalid input
|
||||
'@@',
|
||||
'中文呢', // unicode
|
||||
'((((())))', // invalid
|
||||
':alternate-protocol', // fast bailout
|
||||
'alternate-protocol:' // slow bailout
|
||||
],
|
||||
n: [1e6],
|
||||
});
|
||||
|
||||
function main(conf) {
|
||||
var n = +conf.n;
|
||||
var key = conf.key;
|
||||
|
||||
bench.start();
|
||||
for (var i = 0; i < n; i++) {
|
||||
_checkIsHttpToken(key);
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
@ -225,10 +225,56 @@ exports.httpSocketSetup = httpSocketSetup;
|
||||
/**
|
||||
* Verifies that the given val is a valid HTTP token
|
||||
* per the rules defined in RFC 7230
|
||||
* See https://tools.ietf.org/html/rfc7230#section-3.2.6
|
||||
*
|
||||
* This implementation of checkIsHttpToken() loops over the string instead of
|
||||
* using a regular expression since the former is up to 180% faster with v8 4.9
|
||||
* depending on the string length (the shorter the string, the larger the
|
||||
* performance difference)
|
||||
**/
|
||||
const token = /^[a-zA-Z0-9_!#$%&'*+.^`|~-]+$/;
|
||||
function checkIsHttpToken(val) {
|
||||
return typeof val === 'string' && token.test(val);
|
||||
if (typeof val !== 'string' || val.length === 0)
|
||||
return false;
|
||||
|
||||
for (var i = 0, len = val.length; i < len; i++) {
|
||||
var ch = val.charCodeAt(i);
|
||||
|
||||
if (ch >= 65 && ch <= 90) // A-Z
|
||||
continue;
|
||||
|
||||
if (ch >= 97 && ch <= 122) // a-z
|
||||
continue;
|
||||
|
||||
// ^ => 94
|
||||
// _ => 95
|
||||
// ` => 96
|
||||
// | => 124
|
||||
// ~ => 126
|
||||
if (ch === 94 || ch === 95 || ch === 96 || ch === 124 || ch === 126)
|
||||
continue;
|
||||
|
||||
if (ch >= 48 && ch <= 57) // 0-9
|
||||
continue;
|
||||
|
||||
// ! => 33
|
||||
// # => 35
|
||||
// $ => 36
|
||||
// % => 37
|
||||
// & => 38
|
||||
// ' => 39
|
||||
// * => 42
|
||||
// + => 43
|
||||
// - => 45
|
||||
// . => 46
|
||||
if (ch >= 33 && ch <= 46) {
|
||||
if (ch === 34 || ch === 40 || ch === 41 || ch === 44)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports._checkIsHttpToken = checkIsHttpToken;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user