{"action":"created","issue":{"url":"https://api.github.com/repos/ramda/ramda/issues/1512","labels_url":"https://api.github.com/repos/ramda/ramda/issues/1512/labels{/name}","comments_url":"https://api.github.com/repos/ramda/ramda/issues/1512/comments","events_url":"https://api.github.com/repos/ramda/ramda/issues/1512/events","html_url":"https://github.com/ramda/ramda/pull/1512","id":116435383,"number":1512,"title":"Perfomance improvements to `uniq` and `contains`","user":{"login":"scott-christopher","id":8951601,"avatar_url":"https://avatars.githubusercontent.com/u/8951601?v=3","gravatar_id":"","url":"https://api.github.com/users/scott-christopher","html_url":"https://github.com/scott-christopher","followers_url":"https://api.github.com/users/scott-christopher/followers","following_url":"https://api.github.com/users/scott-christopher/following{/other_user}","gists_url":"https://api.github.com/users/scott-christopher/gists{/gist_id}","starred_url":"https://api.github.com/users/scott-christopher/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scott-christopher/subscriptions","organizations_url":"https://api.github.com/users/scott-christopher/orgs","repos_url":"https://api.github.com/users/scott-christopher/repos","events_url":"https://api.github.com/users/scott-christopher/events{/privacy}","received_events_url":"https://api.github.com/users/scott-christopher/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-11-11T22:30:57Z","updated_at":"2015-11-14T16:45:45Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ramda/ramda/pulls/1512","html_url":"https://github.com/ramda/ramda/pull/1512","diff_url":"https://github.com/ramda/ramda/pull/1512.diff","patch_url":"https://github.com/ramda/ramda/pull/1512.patch"},"body":"Addresses #1449, #1500, #1503 & #1508 regarding performance concerns with `uniq` and `contains`.\r\n\r\nThe main changes include:\r\n* Refactoring the various internal currying functions to ensure the args are `Object`s before checking for the placeholder property, preventing unnecessary boxing/unboxing of primitives.\r\n* Some tweaks to the conditional layout of the internal currying functions to reduce redundant conditional tests.\r\n* `_contains` and `uniqBy` now make use of a native `Set` where possible – given the history of this, I'd appreciate people paying close attention here to ensure the existing semantics of `equals` are upheld.\r\n\r\nI have also included a simple benchmark script for `uniq`, which produced the following results:\r\n\r\nCurrent HEAD of master:\r\n```\r\n┌────────────────────────┬────────────────────────┬────────────────────────┐\r\n│ uniq                   │ Hertz                  │ Margin of Error        │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqBy(id, arr1)       │ 21.52                  │ 0.60%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqWith(equals, arr1) │ 21.81                  │ 0.68%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniq(arr1)             │ 21.66                  │ 0.81%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqBy(id, arr2)       │ 8.73                   │ 0.72%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqWith(equals, arr2) │ 8.72                   │ 0.58%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniq(arr2)             │ 8.67                   │ 0.83%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqBy(id, arr3)       │ 692                    │ 0.55%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqWith(equals, arr3) │ 695                    │ 0.60%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniq(arr3)             │ 686                    │ 0.72%                  │\r\n└────────────────────────┴────────────────────────┴────────────────────────┘\r\n```\r\nThis branch:\r\n```\r\n┌────────────────────────┬────────────────────────┬────────────────────────┐\r\n│ uniq                   │ Hertz                  │ Margin of Error        │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqBy(id, arr1)       │ 94.13                  │ 0.57%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqWith(equals, arr1) │ 40.21                  │ 0.55%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniq(arr1)             │ 87.88                  │ 0.62%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqBy(id, arr2)       │ 21,299                 │ 0.45%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqWith(equals, arr2) │ 25.60                  │ 0.46%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniq(arr2)             │ 18,967                 │ 0.65%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqBy(id, arr3)       │ 787                    │ 0.51%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniqWith(equals, arr3) │ 808                    │ 0.53%                  │\r\n├────────────────────────┼────────────────────────┼────────────────────────┤\r\n│ uniq(arr3)             │ 783                    │ 0.61%                  │\r\n└────────────────────────┴────────────────────────┴────────────────────────┘\r\n```"},"comment":{"url":"https://api.github.com/repos/ramda/ramda/issues/comments/156718681","html_url":"https://github.com/ramda/ramda/pull/1512#issuecomment-156718681","issue_url":"https://api.github.com/repos/ramda/ramda/issues/1512","id":156718681,"user":{"login":"asaf-romano","id":11056617,"avatar_url":"https://avatars.githubusercontent.com/u/11056617?v=3","gravatar_id":"","url":"https://api.github.com/users/asaf-romano","html_url":"https://github.com/asaf-romano","followers_url":"https://api.github.com/users/asaf-romano/followers","following_url":"https://api.github.com/users/asaf-romano/following{/other_user}","gists_url":"https://api.github.com/users/asaf-romano/gists{/gist_id}","starred_url":"https://api.github.com/users/asaf-romano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asaf-romano/subscriptions","organizations_url":"https://api.github.com/users/asaf-romano/orgs","repos_url":"https://api.github.com/users/asaf-romano/repos","events_url":"https://api.github.com/users/asaf-romano/events{/privacy}","received_events_url":"https://api.github.com/users/asaf-romano/received_events","type":"User","site_admin":false},"created_at":"2015-11-14T16:45:45Z","updated_at":"2015-11-14T16:45:45Z","body":"uniq and friends are going to be faster when they use native Set implementation (assuming we return~~ Array.from(set.values()) at the end). That limits us to optimizing cases where the initial value for comparison is a primitive. However, for an array of Dates object (or anything with friendly valueOf implementation), a Set won't do, because we need to uniq-by valueOf return values, but return the initial values. Here a Map could help because we can use the keys side for comparison and the values side for the return value."}}