mirror of https://github.com/lukechilds/node.git
Browse Source
* add benchmark to compare the performance of getting url properties between the WHATWG URL and the legacy implementation * add benchmark to compare the performance of serializing urls between the WHATWG URL and the legacy implementation * refactor the benchmark for comparing parsing performance between the two implementations PR-URL: https://github.com/nodejs/node/pull/10678 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net>v7.x
committed by
Italo A. Casas
4 changed files with 249 additions and 57 deletions
@ -0,0 +1,109 @@ |
|||
'use strict'; |
|||
const common = require('../common.js'); |
|||
const url = require('url'); |
|||
const URL = url.URL; |
|||
const assert = require('assert'); |
|||
|
|||
const inputs = { |
|||
long: 'http://nodejs.org:89/docs/latest/api/url.html#test?' + |
|||
'payload1=true&payload2=false&test=1&benchmark=3&' + |
|||
'foo=38.38.011.293&bar=1234834910480&test=19299&3992&' + |
|||
'key=f5c65e1e98fe07e648249ad41e1cfdb0', |
|||
short: 'https://nodejs.org/en/blog/', |
|||
idn: 'http://你好你好', |
|||
auth: 'https://user:pass@example.com/path?search=1', |
|||
special: 'file:///foo/bar/test/node.js', |
|||
percent: 'https://%E4%BD%A0/foo', |
|||
dot: 'https://example.org/./a/../b/./c' |
|||
}; |
|||
|
|||
const bench = common.createBenchmark(main, { |
|||
type: Object.keys(inputs), |
|||
method: ['legacy', 'whatwg'], |
|||
n: [1e5] |
|||
}); |
|||
|
|||
// At the time of writing, when using a passed property name to index
|
|||
// the object, Crankshaft would generate a LoadKeyedGeneric even when it
|
|||
// remains a constant in the function, so here we must use the literal
|
|||
// instead to get a LoadNamedField.
|
|||
function useLegacy(n, input) { |
|||
var obj = url.parse(input); |
|||
var noDead = { |
|||
protocol: obj.protocol, |
|||
auth: obj.auth, |
|||
host: obj.host, |
|||
hostname: obj.hostname, |
|||
port: obj.port, |
|||
pathname: obj.pathname, |
|||
search: obj.search, |
|||
hash: obj.hash |
|||
}; |
|||
// It's necessary to assign the values to an object
|
|||
// to avoid loop invariant code motion.
|
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) { |
|||
noDead.protocol = obj.protocol; |
|||
noDead.auth = obj.auth; |
|||
noDead.host = obj.host; |
|||
noDead.hostname = obj.hostname; |
|||
noDead.port = obj.port; |
|||
noDead.pathname = obj.pathname; |
|||
noDead.search = obj.search; |
|||
noDead.hash = obj.hash; |
|||
} |
|||
bench.end(n); |
|||
return noDead; |
|||
} |
|||
|
|||
function useWHATWG(n, input) { |
|||
var obj = new URL(input); |
|||
var noDead = { |
|||
protocol: obj.protocol, |
|||
auth: obj.username + ':' + obj.password, |
|||
host: obj.host, |
|||
hostname: obj.hostname, |
|||
port: obj.port, |
|||
pathname: obj.pathname, |
|||
search: obj.search, |
|||
hash: obj.hash |
|||
}; |
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) { |
|||
noDead.protocol = obj.protocol; |
|||
noDead.auth = obj.username + ':' + obj.password; |
|||
noDead.host = obj.host; |
|||
noDead.hostname = obj.hostname; |
|||
noDead.port = obj.port; |
|||
noDead.pathname = obj.pathname; |
|||
noDead.search = obj.search; |
|||
noDead.hash = obj.hash; |
|||
} |
|||
bench.end(n); |
|||
return noDead; |
|||
} |
|||
|
|||
function main(conf) { |
|||
const type = conf.type; |
|||
const n = conf.n | 0; |
|||
const method = conf.method; |
|||
|
|||
const input = inputs[type]; |
|||
if (!input) { |
|||
throw new Error('Unknown input type'); |
|||
} |
|||
|
|||
var noDead; // Avoid dead code elimination.
|
|||
switch (method) { |
|||
case 'legacy': |
|||
noDead = useLegacy(n, input); |
|||
break; |
|||
case 'whatwg': |
|||
noDead = useWHATWG(n, input); |
|||
break; |
|||
default: |
|||
throw new Error('Unknown method'); |
|||
} |
|||
|
|||
assert.ok(noDead); |
|||
} |
@ -0,0 +1,69 @@ |
|||
'use strict'; |
|||
const common = require('../common.js'); |
|||
const url = require('url'); |
|||
const URL = url.URL; |
|||
const assert = require('assert'); |
|||
|
|||
const inputs = { |
|||
long: 'http://nodejs.org:89/docs/latest/api/url.html#test?' + |
|||
'payload1=true&payload2=false&test=1&benchmark=3&' + |
|||
'foo=38.38.011.293&bar=1234834910480&test=19299&3992&' + |
|||
'key=f5c65e1e98fe07e648249ad41e1cfdb0', |
|||
short: 'https://nodejs.org/en/blog/', |
|||
idn: 'http://你好你好', |
|||
auth: 'https://user:pass@example.com/path?search=1', |
|||
special: 'file:///foo/bar/test/node.js', |
|||
percent: 'https://%E4%BD%A0/foo', |
|||
dot: 'https://example.org/./a/../b/./c' |
|||
}; |
|||
|
|||
const bench = common.createBenchmark(main, { |
|||
type: Object.keys(inputs), |
|||
method: ['legacy', 'whatwg'], |
|||
n: [1e5] |
|||
}); |
|||
|
|||
function useLegacy(n, input) { |
|||
var noDead = url.parse(input); |
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) { |
|||
noDead = url.parse(input); |
|||
} |
|||
bench.end(n); |
|||
return noDead; |
|||
} |
|||
|
|||
function useWHATWG(n, input) { |
|||
var noDead = url.parse(input); |
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) { |
|||
noDead = new URL(input); |
|||
} |
|||
bench.end(n); |
|||
return noDead; |
|||
} |
|||
|
|||
function main(conf) { |
|||
const type = conf.type; |
|||
const n = conf.n | 0; |
|||
const method = conf.method; |
|||
|
|||
const input = inputs[type]; |
|||
if (!input) { |
|||
throw new Error('Unknown input type'); |
|||
} |
|||
|
|||
var noDead; // Avoid dead code elimination.
|
|||
switch (method) { |
|||
case 'legacy': |
|||
noDead = useLegacy(n, input); |
|||
break; |
|||
case 'whatwg': |
|||
noDead = useWHATWG(n, input); |
|||
break; |
|||
default: |
|||
throw new Error('Unknown method'); |
|||
} |
|||
|
|||
assert.ok(noDead); |
|||
} |
@ -0,0 +1,71 @@ |
|||
'use strict'; |
|||
const common = require('../common.js'); |
|||
const url = require('url'); |
|||
const URL = url.URL; |
|||
const assert = require('assert'); |
|||
|
|||
const inputs = { |
|||
long: 'http://nodejs.org:89/docs/latest/api/url.html#test?' + |
|||
'payload1=true&payload2=false&test=1&benchmark=3&' + |
|||
'foo=38.38.011.293&bar=1234834910480&test=19299&3992&' + |
|||
'key=f5c65e1e98fe07e648249ad41e1cfdb0', |
|||
short: 'https://nodejs.org/en/blog/', |
|||
idn: 'http://你好你好', |
|||
auth: 'https://user:pass@example.com/path?search=1', |
|||
special: 'file:///foo/bar/test/node.js', |
|||
percent: 'https://%E4%BD%A0/foo', |
|||
dot: 'https://example.org/./a/../b/./c' |
|||
}; |
|||
|
|||
const bench = common.createBenchmark(main, { |
|||
type: Object.keys(inputs), |
|||
method: ['legacy', 'whatwg'], |
|||
n: [1e5] |
|||
}); |
|||
|
|||
function useLegacy(n, input, prop) { |
|||
var obj = url.parse(input); |
|||
var noDead = url.format(obj); |
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) { |
|||
noDead = url.format(obj); |
|||
} |
|||
bench.end(n); |
|||
return noDead; |
|||
} |
|||
|
|||
function useWHATWG(n, input, prop) { |
|||
var obj = new URL(input); |
|||
var noDead = obj.toString(); |
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) { |
|||
noDead = obj.toString(); |
|||
} |
|||
bench.end(n); |
|||
return noDead; |
|||
} |
|||
|
|||
function main(conf) { |
|||
const type = conf.type; |
|||
const n = conf.n | 0; |
|||
const method = conf.method; |
|||
|
|||
const input = inputs[type]; |
|||
if (!input) { |
|||
throw new Error('Unknown input type'); |
|||
} |
|||
|
|||
var noDead; // Avoid dead code elimination.
|
|||
switch (method) { |
|||
case 'legacy': |
|||
noDead = useLegacy(n, input); |
|||
break; |
|||
case 'whatwg': |
|||
noDead = useWHATWG(n, input); |
|||
break; |
|||
default: |
|||
throw new Error('Unknown method'); |
|||
} |
|||
|
|||
assert.ok(noDead); |
|||
} |
@ -1,57 +0,0 @@ |
|||
'use strict'; |
|||
const common = require('../common.js'); |
|||
const url = require('url'); |
|||
const v8 = require('v8'); |
|||
|
|||
const bench = common.createBenchmark(main, { |
|||
type: 'one two three four five'.split(' '), |
|||
method: ['old', 'new'], |
|||
n: [25e4] |
|||
}); |
|||
|
|||
function useOld(n, input) { |
|||
// Force-optimize url.parse() so that the benchmark doesn't get
|
|||
// disrupted by the optimizer kicking in halfway through.
|
|||
url.parse(input); |
|||
v8.setFlagsFromString('--allow_natives_syntax'); |
|||
eval('%OptimizeFunctionOnNextCall(url.parse)'); |
|||
|
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) |
|||
url.parse(input); |
|||
bench.end(n); |
|||
} |
|||
|
|||
function useNew(n, input) { |
|||
bench.start(); |
|||
for (var i = 0; i < n; i += 1) |
|||
new url.URL(input); |
|||
bench.end(n); |
|||
} |
|||
|
|||
function main(conf) { |
|||
const type = conf.type; |
|||
const n = conf.n | 0; |
|||
const method = conf.method; |
|||
|
|||
var inputs = { |
|||
one: 'http://nodejs.org/docs/latest/api/url.html#url_url_format_urlobj', |
|||
two: 'http://blog.nodejs.org/', |
|||
three: 'https://encrypted.google.com/search?q=url&q=site:npmjs.org&hl=en', |
|||
four: 'javascript:alert("node is awesome");', |
|||
//five: 'some.ran/dom/url.thing?oh=yes#whoo',
|
|||
five: 'https://user:pass@example.com/', |
|||
}; |
|||
var input = inputs[type] || ''; |
|||
|
|||
switch (method) { |
|||
case 'old': |
|||
useOld(n, input); |
|||
break; |
|||
case 'new': |
|||
useNew(n, input); |
|||
break; |
|||
default: |
|||
throw new Error('Unknown method'); |
|||
} |
|||
} |
Loading…
Reference in new issue