-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance of WHATWG URL API #30334
Comments
The last time I looked into the performance of the WHATWG URL parsing the bottleneck lies in the usage of I wonder what the performance drop from v8.x to v10.x could be from though.. |
benchmark run on
And still, Legacy URL API is way faster (at least 2x) than The WHATWG URL API. |
# Description Fix a bug where an URL containing both a trailing slash and a querystring would be incorrectly parsed. # How to reproduce The following HTTP GET request works fine: `http://localhost:7512/_now?pretty` But not this one without this PR: `http://localhost:7512/_now/?pretty` Both requests are equivalent and should be regarded as identical. # Other changes ~Use the WHATWG URL parsing API instead of the legacy (and deprecated) Node.js URL parser. Unfortunately, the latter was much more adapted to URL parsing server-side than the former. 😑~ Reverted to the legacy URL API because of: * nodejs/node#30334 (huge performance hit with WHATWG) * nodejs/node#30776 (bug with relative URLs starting with double-slashes)
I'm seeing Reproducible here https://repl.it/repls/LimpingQuarrelsomeCoins
|
|
@SukkaW it was slower in your benchmarks for two reasons: 1) you had an extra function call, and 2) the second one always threw, and throwing is a slower path than not throwing. I would argue it shouldn't have been throwing anyway because you should have passed a base to it like you did the other relative test.
'use strict';
const Benchmark = require('benchmark');
const Suite = new Benchmark.Suite;
// const { URL } = require('url') is only needed for Nodejs 8.
const { parse, URL } = require('url');
Suite.add('Absolute URL - Legacy URL parse()', () => {
return parse('https://skk.moe/path/to/something');
}).add('Absolute URL - WHATWG URL API', () => {
return new URL('https://skk.moe/path/to/something');
}).add('Absolute URL - safe WHATWG URL', () => {
const str = 'https://skk.moe/path/to/something';
try {
return new URL(str);
} catch {
return str;
}
}).add('Relative Path - Legacy URL parse()', () => {
return parse('/path/to/something');
}).add('Relative Path - WHATWG URL API', () => {
return new URL('/path/to/something', 'https://skk.moe/');
}).add('Relative Path - safe WHATWG URL', () => {
const str = '/path/to/something';
try {
return new URL(str, 'https://skk.moe');
} catch {
return str;
}
}).on('cycle', function(event) {
console.info(String(event.target));
}).run(); |
As you can see, the WHATWG URL API just can not handle any relative path. There are always cases that no const safeWhatwgUrl = (str) => {
// Handle relative path
try {
return new URL(str);
} catch (e) {
return str;
}
};
And even a |
@SukkaW right... I agree that the whatwg parser is slower. My point was that your comparison was not really apples to apples (you were comparing a parse that always passed to a parse that always failed), and that try/catch isn't really slow. |
@devsnek we both agree that However in the specific case related to this issue, people are using So in the second part of my benchmark I setup a case when only relative path to be parsed (and Adding a case that has |
@SukkaW thanks, I didn't know try/catch was that slow. However, once |
Unfortunately there's not a lot we can do here. The existing |
According to my benchmark, the WHATWG URL API is only 15% slower than the Legacy URL API for Node.js 8. But for Node.js 10 it becomes nearly 40% slower. There is space for performance improvement, right? |
For sure yes! Just need to make certain we do not sacrifice spec compliance at all |
C:\Users\Himself65\Desktop\github\node>node benchmark/compare.js --old node --new ./Release/node.exe --filter legacy-vs-whatwg-url-parse url > compare-12-6-3-vs-master.csv
[00:03:30|% 100| 1/1 files | 60/60 runs | 40/40 configs]: Done
C:\Users\Himself65\Desktop\github\node>cat compare-12-6-3-vs-master.csv | Rscript benchmark/compare.R
confidence improvement accuracy (*) (**) (***)
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='auth' withBase='false' *** -8.23 % ?±4.44% ?±5.92% ?±7.70%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='auth' withBase='true' ** -6.77 % ?±4.90% ?±6.52% ?±8.49%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='dot' withBase='false' *** -6.90 % ?±3.12% ?±4.15% ?±5.40%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='dot' withBase='true' *** -9.36 % ?±4.93% ?±6.58% ?±8.61%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='file' withBase='false' ** -6.48 % ?±3.79% ?±5.05% ?±6.58%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='file' withBase='true' *** -9.01 % ?±3.50% ?±4.65% ?±6.05%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='idn' withBase='false' *** -10.69 % ?±5.55% ?±7.39% ?±9.62%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='idn' withBase='true' *** -11.18 % ?±3.30% ?±4.39% ?±5.71%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='javascript' withBase='false' ** -6.08 % ?±3.83% ?±5.10% ?±6.64%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='javascript' withBase='true' ** -7.69 % ?±4.90% ?±6.53% ?±8.52%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='long' withBase='false' *** -11.66 % ?±5.12% ?±6.81% ?±8.88%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='long' withBase='true' *** -14.55 % ?±4.39% ?±5.85% ?±7.62%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='percent' withBase='false' *** -8.77 % ?±3.33% ?±4.43% ?±5.76%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='percent' withBase='true' *** -11.25 % ?±4.28% ?±5.70% ?±7.42%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='short' withBase='false' ** -7.81 % ?±5.29% ?±7.04% ?±9.18%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='short' withBase='true' *** -7.96 % ?±4.17% ?±5.55% ?±7.23%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='wpt' withBase='false' *** -8.19 % ?±3.87% ?±5.15% ?±6.70%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='wpt' withBase='true' *** -9.38 % ?±3.60% ?±4.79% ?±6.24%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='ws' withBase='false' -1.54 % ?±4.23% ?±5.63% ?±7.35%
url\\legacy-vs-whatwg-url-parse.js method='legacy' e=1 type='ws' withBase='true' * -6.93 % ?±6.47% ?±8.65% ?±11.33%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='auth' withBase='false' *** -16.04 % ?±3.35% ?±4.46% ?±5.82%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='auth' withBase='true' *** -17.67 % ?±3.71% ?±4.95% ?±6.46%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='dot' withBase='false' *** -14.78 % ?±5.06% ?±6.76% ?±8.86%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='dot' withBase='true' *** -16.43 % ?±4.48% ?±5.96% ?±7.77%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='file' withBase='false' *** -9.65 % ?±4.20% ?±5.60% ?±7.33%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='file' withBase='true' *** -15.20 % ?±3.90% ?±5.20% ?±6.80%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='idn' withBase='false' *** -18.98 % ?±3.26% ?±4.34% ?±5.65%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='idn' withBase='true' *** -14.30 % ?±3.14% ?±4.18% ?±5.45%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='javascript' withBase='false' *** -15.15 % ?±4.37% ?±5.82% ?±7.59%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='javascript' withBase='true' *** -16.06 % ?±3.90% ?±5.19% ?±6.76%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='long' withBase='false' *** -13.63 % ?±4.67% ?±6.23% ?±8.12%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='long' withBase='true' *** -23.90 % ?±3.82% ?±5.09% ?±6.65%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='percent' withBase='false' *** -18.69 % ?±3.43% ?±4.57% ?±5.94%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='percent' withBase='true' *** -15.60 % ?±4.03% ?±5.36% ?±6.98%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='short' withBase='false' *** -16.93 % ?±3.44% ?±4.57% ?±5.96%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='short' withBase='true' *** -14.26 % ?±4.01% ?±5.36% ?±7.02%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='wpt' withBase='false' *** -15.15 % ?±3.69% ?±4.94% ?±6.47%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='wpt' withBase='true' *** -14.99 % ?±4.73% ?±6.29% ?±8.20%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='ws' withBase='false' *** -19.27 % ?±5.87% ?±7.85% ?±10.29%
url\\legacy-vs-whatwg-url-parse.js method='whatwg' e=1 type='ws' withBase='true' *** -17.64 % ?±5.16% ?±6.88% ?±8.98%
|
I'm also sharing benchmark results that I ran. It's fair to say that legacy URL is faster than WHATWG's URL as legacy one has less processing and the newer version of WHATWG's URL should have more logics within WHATWG's URL itself just because some updates in the module are Refs: v12.18.3 vs v14.11.0
v12.18.3 vs master
v14.11.0 vs master
|
@anonrig Thanks for your hard work! I was not expecting this issue to get fixed after years. |
Version:
Subsystem:
url
I have encountered performance regression when mitigating deprecated Legacy URL API to newer recommended WHATWG URL API for a performance-sensitive application. I have set up a benchmark: https://runkit.com/sukkaw/5dc5924f1ba0d60013d87cb3
Resulted in:
Node.js 8.16.2
On Node.js 8.16.2, The WHATWG URL API is 15% slower than Legacy URL API when handle a normal URL. It seems normal and acceptable.
Node.js 10.17.0
On Node.js 10.17.0, The WHATWG URL API is 40% slower than Legacy URL API when handle a normal URL.
Node.js 12.13.0
On Node.js 12.13.0, The WHATWG URL API is 42% slower than Legacy URL API when handle a normal URL.
Node.js 13.1.0
On Node.js 13.1.0, The WHATWG URL API is 38% slower than Legacy URL API when handle a normal URL.
And when I try to pass a
base
to handle relative path, it becomes even more slower. I believe it is because I pass a string tobase
so The WHATWG URL have to parsebase
first.The text was updated successfully, but these errors were encountered: