Skip to content

Commit aff56cd

Browse files
committed
lib: micro-optimize url.resolve()
Replace the call to Array#splice() with a faster open-coded version that creates less garbage. Add a new benchmark to prove it. With the change applied, it scores about 5% higher and that is nothing to sneeze at. PR-URL: #184 Reviewed-By: Chris Dickinson <[email protected]>
1 parent 6b2af5f commit aff56cd

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

benchmark/url/url-resolve.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
var common = require('../common.js');
2+
var url = require('url');
3+
var v8 = require('v8');
4+
5+
var bench = common.createBenchmark(main, {
6+
type: ['one'],
7+
n: [1e5],
8+
});
9+
10+
function main(conf) {
11+
var type = conf.type;
12+
var n = conf.n | 0;
13+
14+
var inputs = {
15+
one: ['http://example.com/', '../../../../../etc/passwd'],
16+
};
17+
var input = inputs[type] || [];
18+
19+
// Force-optimize url.resolve() so that the benchmark doesn't get
20+
// disrupted by the optimizer kicking in halfway through.
21+
for (var name in inputs)
22+
url.resolve(inputs[name][0], inputs[name][1]);
23+
24+
v8.setFlagsFromString('--allow_natives_syntax');
25+
eval('%OptimizeFunctionOnNextCall(url.resolve)');
26+
27+
bench.start();
28+
for (var i = 0; i < n; i += 1)
29+
url.resolve(input[0], input[1]);
30+
bench.end(n);
31+
}

lib/url.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,12 +670,12 @@ Url.prototype.resolveObject = function(relative) {
670670
for (var i = srcPath.length; i >= 0; i--) {
671671
last = srcPath[i];
672672
if (last === '.') {
673-
srcPath.splice(i, 1);
673+
spliceOne(srcPath, i);
674674
} else if (last === '..') {
675-
srcPath.splice(i, 1);
675+
spliceOne(srcPath, i);
676676
up++;
677677
} else if (up) {
678-
srcPath.splice(i, 1);
678+
spliceOne(srcPath, i);
679679
up--;
680680
}
681681
}
@@ -750,3 +750,10 @@ Url.prototype.parseHost = function() {
750750
}
751751
if (host) this.hostname = host;
752752
};
753+
754+
// About 1.5x faster than the two-arg version of Array#splice().
755+
function spliceOne(list, index) {
756+
for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
757+
list[i] = list[k];
758+
list.pop();
759+
}

0 commit comments

Comments
 (0)