{"action":"created","comment":{"url":"https://api.github.com/repos/iojs/io.js/pulls/comments/26895545","id":26895545,"diff_hunk":"@@ -432,51 +282,35 @@ function urlResolveObject(source, relative) {\n }\n \n Url.prototype.resolveObject = function(relative) {\n-  if (typeof relative === 'string') {\n-    var rel = new Url();\n-    rel.parse(relative, false, true);\n-    relative = rel;\n-  }\n+  if (typeof relative === 'string')\n+    relative = urlParse(relative, false, true);\n \n-  var result = new Url();\n-  var tkeys = Object.keys(this);\n-  for (var tk = 0; tk < tkeys.length; tk++) {\n-    var tkey = tkeys[tk];\n-    result[tkey] = this[tkey];\n-  }\n+  var result = this._clone();\n \n-  // hash is always overridden, no matter what.\n-  // even href=\"\" will remove it.\n+  // Hash is always overridden, no matter what.\n+  // even href='' will remove it.\n   result.hash = relative.hash;\n \n-  // if the relative url is empty, then there's nothing left to do here.\n-  if (relative.href === '') {\n-    result.href = result.format();\n+  // If the relative url is empty, then there's nothing left to do here.\n+  if (!relative.href) {\n+    result._href = '';\n     return result;\n   }\n \n-  // hrefs like //foo/bar always cut to the protocol.\n-  if (relative.slashes && !relative.protocol) {\n-    // take everything except the protocol from relative\n-    var rkeys = Object.keys(relative);\n-    for (var rk = 0; rk < rkeys.length; rk++) {\n-      var rkey = rkeys[rk];\n-      if (rkey !== 'protocol')\n-        result[rkey] = relative[rkey];\n-    }\n+  // Hrefs like //foo/bar always cut to the protocol.\n+  if (relative.slashes && !relative._protocol) {\n+    relative._copyPropsTo(result, true);\n \n-    //urlParse appends trailing / to urls like http://www.example.com\n-    if (slashedProtocol[result.protocol] &&\n+    if (_slashProtocols[result._protocol] &&\n         result.hostname && !result.pathname) {\n-      result.path = result.pathname = '/';\n+      result.pathname = '/';","path":"lib/url.js","position":658,"original_position":658,"commit_id":"dc3c64ee28726bdb43e7a651dfb8cef77244f103","original_commit_id":"dc3c64ee28726bdb43e7a651dfb8cef77244f103","user":{"login":"petkaantonov","id":829734,"avatar_url":"https://avatars.githubusercontent.com/u/829734?v=3","gravatar_id":"","url":"https://api.github.com/users/petkaantonov","html_url":"https://github.com/petkaantonov","followers_url":"https://api.github.com/users/petkaantonov/followers","following_url":"https://api.github.com/users/petkaantonov/following{/other_user}","gists_url":"https://api.github.com/users/petkaantonov/gists{/gist_id}","starred_url":"https://api.github.com/users/petkaantonov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petkaantonov/subscriptions","organizations_url":"https://api.github.com/users/petkaantonov/orgs","repos_url":"https://api.github.com/users/petkaantonov/repos","events_url":"https://api.github.com/users/petkaantonov/events{/privacy}","received_events_url":"https://api.github.com/users/petkaantonov/received_events","type":"User","site_admin":false},"body":".path is a getter function","created_at":"2015-03-21T18:37:53Z","updated_at":"2015-03-21T18:37:53Z","html_url":"https://github.com/iojs/io.js/pull/933#discussion_r26895545","pull_request_url":"https://api.github.com/repos/iojs/io.js/pulls/933","_links":{"self":{"href":"https://api.github.com/repos/iojs/io.js/pulls/comments/26895545"},"html":{"href":"https://github.com/iojs/io.js/pull/933#discussion_r26895545"},"pull_request":{"href":"https://api.github.com/repos/iojs/io.js/pulls/933"}}},"pull_request":{"url":"https://api.github.com/repos/iojs/io.js/pulls/933","id":29864270,"html_url":"https://github.com/iojs/io.js/pull/933","diff_url":"https://github.com/iojs/io.js/pull/933.diff","patch_url":"https://github.com/iojs/io.js/pull/933.patch","issue_url":"https://api.github.com/repos/iojs/io.js/issues/933","number":933,"state":"open","locked":false,"title":"url: significantly improve the performance of the url module","user":{"login":"petkaantonov","id":829734,"avatar_url":"https://avatars.githubusercontent.com/u/829734?v=3","gravatar_id":"","url":"https://api.github.com/users/petkaantonov","html_url":"https://github.com/petkaantonov","followers_url":"https://api.github.com/users/petkaantonov/followers","following_url":"https://api.github.com/users/petkaantonov/following{/other_user}","gists_url":"https://api.github.com/users/petkaantonov/gists{/gist_id}","starred_url":"https://api.github.com/users/petkaantonov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petkaantonov/subscriptions","organizations_url":"https://api.github.com/users/petkaantonov/orgs","repos_url":"https://api.github.com/users/petkaantonov/repos","events_url":"https://api.github.com/users/petkaantonov/events{/privacy}","received_events_url":"https://api.github.com/users/petkaantonov/received_events","type":"User","site_admin":false},"body":"\r\nSee issues: https://github.com/iojs/io.js/issues/643, https://github.com/joyent/node/issues/6788\r\n\r\nOriginal message:\r\n\r\nI have rewritten the url parser module of node core as it was/is a serious bottleneck in some of the [techempower benchmarks](https://www.techempower.com/benchmarks/)\r\n\r\nRunning node's urlparser benchmark using iojs it's still 16x faster when not retrieving properties and 11x faster when retrieving all properties (which are lazy getters in my implementation). In absolute terms the current iojs urlparser throughputs 25k parses per second vs 400k lazy/270k eager parses per second. `format` and `resolve` are also affected in similar magnitudes.\r\n\r\nTesting this PR on my VM ubuntu I get\r\n\r\nAfter\r\n\r\n    $ bleed benchmark/misc/url.js\r\n    misc/url.js parse(): 1.6529e+5\r\n    misc/url.js format(): 1.9114e+5\r\n    misc/url.js resolve(\"../foo/bar?baz=boom\"): 24302\r\n    misc/url.js resolve(\"foo/bar\"): 35696\r\n    misc/url.js resolve(\"http://nodejs.org\"): 68003\r\n    misc/url.js resolve(\"./foo/bar?baz\"): 29983\r\n\r\n    $ bleed benchmark/common.js url\r\n    url/url-parse.js\r\n    url/url-parse.js type=one n=250000: 1244025.74054\r\n    url/url-parse.js type=two n=250000: 2071492.21773\r\n    url/url-parse.js type=three n=250000: 1113916.06067\r\n    url/url-parse.js type=four n=250000: 3416688.31936\r\n    url/url-parse.js type=five n=250000: 1620766.16897\r\n    url/url-parse.js type=six n=250000: 1659564.59318\r\n\r\n    url/url-resolve.js\r\n    url/url-resolve.js type=one n=100000: 184353.89591\r\n\r\nBefore\r\n\r\n    $ git checkout v1.x && make -j4 && bleed benchmark/misc/url.js\r\n    misc/url.js parse(): 16510\r\n    misc/url.js format(): 18309\r\n    misc/url.js resolve(\"../foo/bar?baz=boom\"): 8929.9\r\n    misc/url.js resolve(\"foo/bar\"): 9919.5\r\n    misc/url.js resolve(\"http://nodejs.org\"): 8177.6\r\n    misc/url.js resolve(\"./foo/bar?baz\"): 8984.4\r\n\r\n    $ bleed benchmark/common.js url\r\n    url/url-parse.js\r\n    url/url-parse.js type=one n=250000: 82666.55318\r\n    url/url-parse.js type=two n=250000: 84669.54973\r\n    url/url-parse.js type=three n=250000: 80308.64406\r\n    url/url-parse.js type=four n=250000: 262017.65403\r\n    url/url-parse.js type=five n=250000: 203834.95043\r\n    url/url-parse.js type=six n=250000: 68911.18834\r\n\r\n    url/url-resolve.js\r\n    url/url-resolve.js type=one n=100000: 42331.42854\r\n\r\nThat's 10-24x faster depending on url.\r\n\r\n**Caveats**\r\n\r\nThis implementation uses getters/setters on the prototype instead of own properties like current url. This is because often the properties are not needed and take time to calculate. Additionally @chrisdickinson introduced another reason to use setters at https://github.com/iojs/io.js/pull/893#issuecomment-75360607.\r\n\r\nThis patch is technically backward incompatible but to minimize any compatibility issues I made `util._extend` to call `toJSON`, because some core modules pass the Url instance directly to `util._extend`. The `toJSON` also means that serialized output of current url and the new url stay the same.\r\n\r\n/cc @trevnorris @mikeal","created_at":"2015-02-24T01:42:38Z","updated_at":"2015-03-21T18:37:53Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0caa1bd22b82960058f84b7348673559eb883013","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/iojs/io.js/pulls/933/commits","review_comments_url":"https://api.github.com/repos/iojs/io.js/pulls/933/comments","review_comment_url":"https://api.github.com/repos/iojs/io.js/pulls/comments{/number}","comments_url":"https://api.github.com/repos/iojs/io.js/issues/933/comments","statuses_url":"https://api.github.com/repos/iojs/io.js/statuses/dc3c64ee28726bdb43e7a651dfb8cef77244f103","head":{"label":"petkaantonov:faster-url-parser","ref":"faster-url-parser","sha":"dc3c64ee28726bdb43e7a651dfb8cef77244f103","user":{"login":"petkaantonov","id":829734,"avatar_url":"https://avatars.githubusercontent.com/u/829734?v=3","gravatar_id":"","url":"https://api.github.com/users/petkaantonov","html_url":"https://github.com/petkaantonov","followers_url":"https://api.github.com/users/petkaantonov/followers","following_url":"https://api.github.com/users/petkaantonov/following{/other_user}","gists_url":"https://api.github.com/users/petkaantonov/gists{/gist_id}","starred_url":"https://api.github.com/users/petkaantonov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petkaantonov/subscriptions","organizations_url":"https://api.github.com/users/petkaantonov/orgs","repos_url":"https://api.github.com/users/petkaantonov/repos","events_url":"https://api.github.com/users/petkaantonov/events{/privacy}","received_events_url":"https://api.github.com/users/petkaantonov/received_events","type":"User","site_admin":false},"repo":{"id":30495325,"name":"io.js","full_name":"petkaantonov/io.js","owner":{"login":"petkaantonov","id":829734,"avatar_url":"https://avatars.githubusercontent.com/u/829734?v=3","gravatar_id":"","url":"https://api.github.com/users/petkaantonov","html_url":"https://github.com/petkaantonov","followers_url":"https://api.github.com/users/petkaantonov/followers","following_url":"https://api.github.com/users/petkaantonov/following{/other_user}","gists_url":"https://api.github.com/users/petkaantonov/gists{/gist_id}","starred_url":"https://api.github.com/users/petkaantonov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petkaantonov/subscriptions","organizations_url":"https://api.github.com/users/petkaantonov/orgs","repos_url":"https://api.github.com/users/petkaantonov/repos","events_url":"https://api.github.com/users/petkaantonov/events{/privacy}","received_events_url":"https://api.github.com/users/petkaantonov/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/petkaantonov/io.js","description":"A friendly fork of Node.js with an open governance model","fork":true,"url":"https://api.github.com/repos/petkaantonov/io.js","forks_url":"https://api.github.com/repos/petkaantonov/io.js/forks","keys_url":"https://api.github.com/repos/petkaantonov/io.js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/petkaantonov/io.js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/petkaantonov/io.js/teams","hooks_url":"https://api.github.com/repos/petkaantonov/io.js/hooks","issue_events_url":"https://api.github.com/repos/petkaantonov/io.js/issues/events{/number}","events_url":"https://api.github.com/repos/petkaantonov/io.js/events","assignees_url":"https://api.github.com/repos/petkaantonov/io.js/assignees{/user}","branches_url":"https://api.github.com/repos/petkaantonov/io.js/branches{/branch}","tags_url":"https://api.github.com/repos/petkaantonov/io.js/tags","blobs_url":"https://api.github.com/repos/petkaantonov/io.js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/petkaantonov/io.js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/petkaantonov/io.js/git/refs{/sha}","trees_url":"https://api.github.com/repos/petkaantonov/io.js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/petkaantonov/io.js/statuses/{sha}","languages_url":"https://api.github.com/repos/petkaantonov/io.js/languages","stargazers_url":"https://api.github.com/repos/petkaantonov/io.js/stargazers","contributors_url":"https://api.github.com/repos/petkaantonov/io.js/contributors","subscribers_url":"https://api.github.com/repos/petkaantonov/io.js/subscribers","subscription_url":"https://api.github.com/repos/petkaantonov/io.js/subscription","commits_url":"https://api.github.com/repos/petkaantonov/io.js/commits{/sha}","git_commits_url":"https://api.github.com/repos/petkaantonov/io.js/git/commits{/sha}","comments_url":"https://api.github.com/repos/petkaantonov/io.js/comments{/number}","issue_comment_url":"https://api.github.com/repos/petkaantonov/io.js/issues/comments{/number}","contents_url":"https://api.github.com/repos/petkaantonov/io.js/contents/{+path}","compare_url":"https://api.github.com/repos/petkaantonov/io.js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/petkaantonov/io.js/merges","archive_url":"https://api.github.com/repos/petkaantonov/io.js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/petkaantonov/io.js/downloads","issues_url":"https://api.github.com/repos/petkaantonov/io.js/issues{/number}","pulls_url":"https://api.github.com/repos/petkaantonov/io.js/pulls{/number}","milestones_url":"https://api.github.com/repos/petkaantonov/io.js/milestones{/number}","notifications_url":"https://api.github.com/repos/petkaantonov/io.js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/petkaantonov/io.js/labels{/name}","releases_url":"https://api.github.com/repos/petkaantonov/io.js/releases{/id}","created_at":"2015-02-08T15:30:16Z","updated_at":"2015-02-08T15:30:19Z","pushed_at":"2015-03-21T15:15:37Z","git_url":"git://github.com/petkaantonov/io.js.git","ssh_url":"git@github.com:petkaantonov/io.js.git","clone_url":"https://github.com/petkaantonov/io.js.git","svn_url":"https://github.com/petkaantonov/io.js","homepage":"https://iojs.org","size":121147,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"v1.x"}},"base":{"label":"iojs:v1.x","ref":"v1.x","sha":"99c79f8d41c706ddcffed7137f971a6cb62e2230","user":{"login":"iojs","id":9950313,"avatar_url":"https://avatars.githubusercontent.com/u/9950313?v=3","gravatar_id":"","url":"https://api.github.com/users/iojs","html_url":"https://github.com/iojs","followers_url":"https://api.github.com/users/iojs/followers","following_url":"https://api.github.com/users/iojs/following{/other_user}","gists_url":"https://api.github.com/users/iojs/gists{/gist_id}","starred_url":"https://api.github.com/users/iojs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iojs/subscriptions","organizations_url":"https://api.github.com/users/iojs/orgs","repos_url":"https://api.github.com/users/iojs/repos","events_url":"https://api.github.com/users/iojs/events{/privacy}","received_events_url":"https://api.github.com/users/iojs/received_events","type":"Organization","site_admin":false},"repo":{"id":27193779,"name":"io.js","full_name":"iojs/io.js","owner":{"login":"iojs","id":9950313,"avatar_url":"https://avatars.githubusercontent.com/u/9950313?v=3","gravatar_id":"","url":"https://api.github.com/users/iojs","html_url":"https://github.com/iojs","followers_url":"https://api.github.com/users/iojs/followers","following_url":"https://api.github.com/users/iojs/following{/other_user}","gists_url":"https://api.github.com/users/iojs/gists{/gist_id}","starred_url":"https://api.github.com/users/iojs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iojs/subscriptions","organizations_url":"https://api.github.com/users/iojs/orgs","repos_url":"https://api.github.com/users/iojs/repos","events_url":"https://api.github.com/users/iojs/events{/privacy}","received_events_url":"https://api.github.com/users/iojs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/iojs/io.js","description":"A friendly fork of Node.js with an open governance model","fork":false,"url":"https://api.github.com/repos/iojs/io.js","forks_url":"https://api.github.com/repos/iojs/io.js/forks","keys_url":"https://api.github.com/repos/iojs/io.js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/iojs/io.js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/iojs/io.js/teams","hooks_url":"https://api.github.com/repos/iojs/io.js/hooks","issue_events_url":"https://api.github.com/repos/iojs/io.js/issues/events{/number}","events_url":"https://api.github.com/repos/iojs/io.js/events","assignees_url":"https://api.github.com/repos/iojs/io.js/assignees{/user}","branches_url":"https://api.github.com/repos/iojs/io.js/branches{/branch}","tags_url":"https://api.github.com/repos/iojs/io.js/tags","blobs_url":"https://api.github.com/repos/iojs/io.js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/iojs/io.js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/iojs/io.js/git/refs{/sha}","trees_url":"https://api.github.com/repos/iojs/io.js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/iojs/io.js/statuses/{sha}","languages_url":"https://api.github.com/repos/iojs/io.js/languages","stargazers_url":"https://api.github.com/repos/iojs/io.js/stargazers","contributors_url":"https://api.github.com/repos/iojs/io.js/contributors","subscribers_url":"https://api.github.com/repos/iojs/io.js/subscribers","subscription_url":"https://api.github.com/repos/iojs/io.js/subscription","commits_url":"https://api.github.com/repos/iojs/io.js/commits{/sha}","git_commits_url":"https://api.github.com/repos/iojs/io.js/git/commits{/sha}","comments_url":"https://api.github.com/repos/iojs/io.js/comments{/number}","issue_comment_url":"https://api.github.com/repos/iojs/io.js/issues/comments{/number}","contents_url":"https://api.github.com/repos/iojs/io.js/contents/{+path}","compare_url":"https://api.github.com/repos/iojs/io.js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/iojs/io.js/merges","archive_url":"https://api.github.com/repos/iojs/io.js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/iojs/io.js/downloads","issues_url":"https://api.github.com/repos/iojs/io.js/issues{/number}","pulls_url":"https://api.github.com/repos/iojs/io.js/pulls{/number}","milestones_url":"https://api.github.com/repos/iojs/io.js/milestones{/number}","notifications_url":"https://api.github.com/repos/iojs/io.js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/iojs/io.js/labels{/name}","releases_url":"https://api.github.com/repos/iojs/io.js/releases{/id}","created_at":"2014-11-26T19:57:11Z","updated_at":"2015-03-21T18:12:31Z","pushed_at":"2015-03-21T17:02:32Z","git_url":"git://github.com/iojs/io.js.git","ssh_url":"git@github.com:iojs/io.js.git","clone_url":"https://github.com/iojs/io.js.git","svn_url":"https://github.com/iojs/io.js","homepage":"https://iojs.org","size":165191,"stargazers_count":11206,"watchers_count":11206,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":755,"mirror_url":null,"open_issues_count":209,"forks":755,"open_issues":209,"watchers":11206,"default_branch":"v1.x"}},"_links":{"self":{"href":"https://api.github.com/repos/iojs/io.js/pulls/933"},"html":{"href":"https://github.com/iojs/io.js/pull/933"},"issue":{"href":"https://api.github.com/repos/iojs/io.js/issues/933"},"comments":{"href":"https://api.github.com/repos/iojs/io.js/issues/933/comments"},"review_comments":{"href":"https://api.github.com/repos/iojs/io.js/pulls/933/comments"},"review_comment":{"href":"https://api.github.com/repos/iojs/io.js/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/iojs/io.js/pulls/933/commits"},"statuses":{"href":"https://api.github.com/repos/iojs/io.js/statuses/dc3c64ee28726bdb43e7a651dfb8cef77244f103"}}}}