http_parser: use pushValueToArray for headers
For performance add headers to the headers Array by pushing them on from JS. Benchmark added to demonstrate this case. PR-URL: https://github.com/nodejs/node/pull/3780 Reviewed-By: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
parent
83524b3c18
commit
d39ace16ba
55
benchmark/http/bench-parser.js
Normal file
55
benchmark/http/bench-parser.js
Normal file
@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const HTTPParser = process.binding('http_parser').HTTPParser;
|
||||
const REQUEST = HTTPParser.REQUEST;
|
||||
const kOnHeaders = HTTPParser.kOnHeaders | 0;
|
||||
const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
|
||||
const kOnBody = HTTPParser.kOnBody | 0;
|
||||
const kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
|
||||
const CRLF = '\r\n';
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
fields: [4, 8, 16, 32],
|
||||
n: [1e5],
|
||||
});
|
||||
|
||||
|
||||
function main(conf) {
|
||||
const fields = conf.fields >>> 0;
|
||||
const n = conf.n >>> 0;
|
||||
var header = `GET /hello HTTP/1.1${CRLF}Content-Type: text/plain${CRLF}`;
|
||||
|
||||
for (var i = 0; i < fields; i++) {
|
||||
header += `X-Filler${i}: ${Math.random().toString(36).substr(2)}${CRLF}`;
|
||||
}
|
||||
header += CRLF;
|
||||
|
||||
processHeader(new Buffer(header), n);
|
||||
}
|
||||
|
||||
|
||||
function processHeader(header, n) {
|
||||
const parser = newParser(REQUEST);
|
||||
|
||||
bench.start();
|
||||
for (var i = 0; i < n; i++) {
|
||||
parser.execute(header, 0, header.length);
|
||||
parser.reinitialize(REQUEST);
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
||||
|
||||
|
||||
function newParser(type) {
|
||||
const parser = new HTTPParser(type);
|
||||
|
||||
parser.headers = [];
|
||||
|
||||
parser[kOnHeaders] = function() { };
|
||||
parser[kOnHeadersComplete] = function() { };
|
||||
parser[kOnBody] = function() { };
|
||||
parser[kOnMessageComplete] = function() { };
|
||||
|
||||
return parser;
|
||||
}
|
@ -632,12 +632,23 @@ class Parser : public BaseObject {
|
||||
Local<Array> CreateHeaders() {
|
||||
// num_values_ is either -1 or the entry # of the last header
|
||||
// so num_values_ == 0 means there's a single header
|
||||
Local<Array> headers = Array::New(env()->isolate(), 2 * num_values_);
|
||||
Local<Array> headers = Array::New(env()->isolate());
|
||||
Local<Function> fn = env()->push_values_to_array_function();
|
||||
Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX * 2];
|
||||
int i = 0;
|
||||
|
||||
for (int i = 0; i < num_values_; ++i) {
|
||||
headers->Set(2 * i, fields_[i].ToString(env()));
|
||||
headers->Set(2 * i + 1, values_[i].ToString(env()));
|
||||
}
|
||||
do {
|
||||
size_t j = 0;
|
||||
while (i < num_values_ && j < ARRAY_SIZE(argv) / 2) {
|
||||
argv[j * 2] = fields_[i].ToString(env());
|
||||
argv[j * 2 + 1] = values_[i].ToString(env());
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
if (j > 0) {
|
||||
fn->Call(env()->context(), headers, j * 2, argv).ToLocalChecked();
|
||||
}
|
||||
} while (i < num_values_);
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user