joyent/node — pull request #8958 by mscdex (2014-12-31 02:36:46+00:00)
Title: querystring: improve parse() performance

The big differences in this improvment come from moving the try-catch out of `parse()` and from the new `indexOf()` check. The gains are significant on unencoded strings and speed impact for encoded strings is negligible.

I have a version of this for the v0.10 branch where the gains on unencoded strings are slightly higher and the speed impact for encoded strings is about the same as on v0.12.

On v0.12 I get these kinds of results:

```
Benchmarking non-encoded data:
querystring#oldParse x 292,698 ops/sec ±0.11% (196 runs sampled)
querystring#newParse x 431,425 ops/sec ±0.15% (193 runs sampled)
Fastest is querystring#newParse

Benchmarking encoded data:
querystring#oldParse x 246,595 ops/sec ±0.16% (196 runs sampled)
querystring#newParse x 287,151 ops/sec ±0.25% (196 runs sampled)
Fastest is querystring#newParse
```

On v0.10 I get these kinds of results:

```
Benchmarking non-encoded data:
querystring#oldParse x 297,629 ops/sec ±0.19% (195 runs sampled)
querystring#newParse x 511,708 ops/sec ±0.08% (198 runs sampled)
Fastest is querystring#newParse

Benchmarking encoded data:
querystring#oldParse x 252,407 ops/sec ±0.21% (197 runs sampled)
querystring#newParse x 279,290 ops/sec ±0.16% (195 runs sampled)
Fastest is querystring#newParse
```

Here is my benchmark code:

```javascript
var Benchmark = require('benchmark');
var oldQSParse = require('querystring').parse,
newQSParse = require('./querystring').parse;
var QSTR = 'foo=bar&baz=quux&xyzzy=thud',
QSTR_ENC = '%66%6F%6F=bar&%62%61%7A=quux&xyzzy=%74h%75d';

console.log('Benchmarking non-encoded data:');
var suite = new Benchmark.Suite();
suite.add('querystring#oldParse', function() {
var r = oldQSParse(QSTR);
}, { minSamples: 100 });
suite.add('querystring#newParse', function() {
var r = newQSParse(QSTR);
}, { minSamples: 100 });
suite.on('cycle', function(event) {
console.log(String(event.target));
});
suite.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
});
suite.run({ async: false });

console.log('\nBenchmarking encoded data:');
suite = new Benchmark.Suite();
suite.add('querystring#oldParse', function() {
var r = oldQSParse(QSTR_ENC);
}, { minSamples: 100 });
suite.add('querystring#newParse', function() {
var r = newQSParse(QSTR_ENC);
}, { minSamples: 100 });
suite.on('cycle', function(event) {
console.log(String(event.target));
});
suite.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
});
suite.run({ async: false });
```