{"action":"created","issue":{"url":"https://api.github.com/repos/vcr/vcr/issues/721","repository_url":"https://api.github.com/repos/vcr/vcr","labels_url":"https://api.github.com/repos/vcr/vcr/issues/721/labels{/name}","comments_url":"https://api.github.com/repos/vcr/vcr/issues/721/comments","events_url":"https://api.github.com/repos/vcr/vcr/issues/721/events","html_url":"https://github.com/vcr/vcr/pull/721","id":363748647,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE4MTA1NDcy","number":721,"title":"Compare JSON bodies quicker by checking for string equivalence first","user":{"login":"laserlemon","id":34264,"node_id":"MDQ6VXNlcjM0MjY0","avatar_url":"https://avatars1.githubusercontent.com/u/34264?v=4","gravatar_id":"","url":"https://api.github.com/users/laserlemon","html_url":"https://github.com/laserlemon","followers_url":"https://api.github.com/users/laserlemon/followers","following_url":"https://api.github.com/users/laserlemon/following{/other_user}","gists_url":"https://api.github.com/users/laserlemon/gists{/gist_id}","starred_url":"https://api.github.com/users/laserlemon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/laserlemon/subscriptions","organizations_url":"https://api.github.com/users/laserlemon/orgs","repos_url":"https://api.github.com/users/laserlemon/repos","events_url":"https://api.github.com/users/laserlemon/events{/privacy}","received_events_url":"https://api.github.com/users/laserlemon/received_events","type":"User","site_admin":true},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-09-25T20:16:30Z","updated_at":"2018-09-25T20:39:06Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https://api.github.com/repos/vcr/vcr/pulls/721","html_url":"https://github.com/vcr/vcr/pull/721","diff_url":"https://github.com/vcr/vcr/pull/721.diff","patch_url":"https://github.com/vcr/vcr/pull/721.patch"},"body":"For identical bodies, comparison can be improved by a few orders of magnitude. For equivalent (but not identical) and different bodies, the difference is negligible. My benchmark script and local results are included below. Thank you! 👏\r\n\r\n<details>\r\n<summary>Benchmark script</summary>\r\n    \r\n    # frozen_string_literal: true\r\n\r\n    begin\r\n      require \"benchmark/ips\"\r\n      require \"faker\"\r\n      require \"json\"\r\n    rescue LoadError\r\n      abort \"Please `gem install benchmark-ips faker json` first!\"\r\n    end\r\n\r\n    data = Faker::Types.complex_rb_hash(1000)\r\n    body = JSON.generate(Faker::Types.complex_rb_hash(1000))\r\n\r\n    identical_body = body.dup\r\n    equivalent_body = JSON.pretty_generate(data)\r\n    different_body = JSON.generate(data.merge(different: true))\r\n    very_different_body = JSON.generate(Faker::Types.complex_rb_hash(1000))\r\n\r\n    def test(body_1, body_2)\r\n      Benchmark.ips do |x|\r\n        x.report \"original\" do\r\n          JSON.parse(body_1) == JSON.parse(body_2)\r\n        end\r\n\r\n        x.report \"improved\" do\r\n          body_1 == body_2 || JSON.parse(body_1) == JSON.parse(body_2)\r\n        end\r\n\r\n        x.compare!\r\n      end\r\n    end\r\n\r\n    puts \"IDENTICAL BODIES\"\r\n    test(body, identical_body)\r\n\r\n    puts \"EQUIVALENT BODIES\"\r\n    test(body, equivalent_body)\r\n\r\n    puts \"DIFFERENT BODIES\"\r\n    test(body, different_body)\r\n\r\n    puts \"VERY DIFFERENT BODIES\"\r\n    test(body, very_different_body)\r\n</details>\r\n\r\n<details>\r\n<summary>Benchmark results</summary>\r\n\r\n    IDENTICAL BODIES\r\n    Warming up --------------------------------------\r\n                original   272.000  i/100ms\r\n                improved   307.430k i/100ms\r\n    Calculating -------------------------------------\r\n                original      2.735k (± 3.5%) i/s -     13.872k in   5.078274s\r\n                improved     10.089M (± 4.0%) i/s -     50.419M in   5.006029s\r\n\r\n    Comparison:\r\n                improved: 10089399.2 i/s\r\n                original:     2735.0 i/s - 3688.97x  slower\r\n\r\n    EQUIVALENT BODIES\r\n    Warming up --------------------------------------\r\n                original   313.000  i/100ms\r\n                improved   298.000  i/100ms\r\n    Calculating -------------------------------------\r\n                original      3.080k (± 3.4%) i/s -     15.650k in   5.088047s\r\n                improved      3.129k (± 2.8%) i/s -     15.794k in   5.051086s\r\n\r\n    Comparison:\r\n                improved:     3129.4 i/s\r\n                original:     3079.6 i/s - same-ish: difference falls within error\r\n\r\n    DIFFERENT BODIES\r\n    Warming up --------------------------------------\r\n                original   315.000  i/100ms\r\n                improved   314.000  i/100ms\r\n    Calculating -------------------------------------\r\n                original      3.189k (± 2.7%) i/s -     16.065k in   5.041486s\r\n                improved      3.163k (± 4.4%) i/s -     16.014k in   5.074614s\r\n\r\n    Comparison:\r\n                original:     3188.9 i/s\r\n                improved:     3162.8 i/s - same-ish: difference falls within error\r\n\r\n    VERY DIFFERENT BODIES\r\n    Warming up --------------------------------------\r\n                original   308.000  i/100ms\r\n                improved   314.000  i/100ms\r\n    Calculating -------------------------------------\r\n                original      3.154k (± 2.5%) i/s -     16.016k in   5.081594s\r\n                improved      3.064k (± 4.5%) i/s -     15.386k in   5.032466s\r\n\r\n    Comparison:\r\n                original:     3153.9 i/s\r\n                improved:     3063.9 i/s - same-ish: difference falls within error\r\n\r\n</details>"},"comment":{"url":"https://api.github.com/repos/vcr/vcr/issues/comments/424493289","html_url":"https://github.com/vcr/vcr/pull/721#issuecomment-424493289","issue_url":"https://api.github.com/repos/vcr/vcr/issues/721","id":424493289,"node_id":"MDEyOklzc3VlQ29tbWVudDQyNDQ5MzI4OQ==","user":{"login":"krainboltgreene","id":334809,"node_id":"MDQ6VXNlcjMzNDgwOQ==","avatar_url":"https://avatars1.githubusercontent.com/u/334809?v=4","gravatar_id":"","url":"https://api.github.com/users/krainboltgreene","html_url":"https://github.com/krainboltgreene","followers_url":"https://api.github.com/users/krainboltgreene/followers","following_url":"https://api.github.com/users/krainboltgreene/following{/other_user}","gists_url":"https://api.github.com/users/krainboltgreene/gists{/gist_id}","starred_url":"https://api.github.com/users/krainboltgreene/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krainboltgreene/subscriptions","organizations_url":"https://api.github.com/users/krainboltgreene/orgs","repos_url":"https://api.github.com/users/krainboltgreene/repos","events_url":"https://api.github.com/users/krainboltgreene/events{/privacy}","received_events_url":"https://api.github.com/users/krainboltgreene/received_events","type":"User","site_admin":false},"created_at":"2018-09-25T20:39:06Z","updated_at":"2018-09-25T20:39:06Z","author_association":"MEMBER","body":"So we have three options:\r\n\r\n  1. Parse bodies, then compare like you suggested, which matches the test and also saves us some comparison time.\r\n  2. Do mime checking maybe? Then compare?\r\n  3. Rewrite the test.\r\n\r\nIn addition, I think we should switch away from JSON and towards oj, considering it's speed.\r\n  "}}
{"actor":{"display_login":"krainboltgreene"}}