{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/corefxlab/pulls/comments/45121887","id":45121887,"diff_hunk":"@@ -162,6 +165,69 @@ public static Span<char> Slice(this string str, int start, int length)\n             cast[0] = value;\n         }\n \n+        /// <summary>\n+        /// Determines whether two spans are equal by comparing the elements by using memcmp\n+        /// </summary>\n+        /// <param name=\"first\">A span of type T to compare to second.</param>\n+        /// <param name=\"second\">A span of type T to compare to first.</param>\n+        public static bool SequenceEqual<T>(this Span<T> first, Span<T> second)\n+            where T : struct, IEquatable<T>\n+        {\n+            if (first.Length != second.Length)\n+            {\n+                return false;\n+            }\n+\n+            var bytesCount = first.Length * PtrUtils.SizeOf<T>();\n+            // pinvoke calls are expensive (mostly due to memory pinning) so we call memcmp only for big slices\n+            if (bytesCount >= 512)\n+            {\n+                return MemoryUtils.MemCmp(first, second);\n+            }\n+\n+            // for small slices we just use simple loop\n+            for (int i = 0; i < first.Length; i++)\n+            {\n+                if (!first.GetItemWithoutBoundariesCheck(i).Equals(second.GetItemWithoutBoundariesCheck(i)))\n+                {\n+                    return false;\n+                }\n+            }\n+            return true;\n+        }\n+\n+        /// <summary>\n+        /// Determines whether two spans are structurally equal by comparing the elements by using memcmp\n+        /// </summary>","path":"src/System.Slices/src/System/SpanExtensions.cs","position":54,"original_position":54,"commit_id":"1835bb01d0348c720434015b900509db6af9c15f","original_commit_id":"1835bb01d0348c720434015b900509db6af9c15f","user":{"login":"VSadov","id":8218165,"avatar_url":"https://avatars.githubusercontent.com/u/8218165?v=3","gravatar_id":"","url":"https://api.github.com/users/VSadov","html_url":"https://github.com/VSadov","followers_url":"https://api.github.com/users/VSadov/followers","following_url":"https://api.github.com/users/VSadov/following{/other_user}","gists_url":"https://api.github.com/users/VSadov/gists{/gist_id}","starred_url":"https://api.github.com/users/VSadov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VSadov/subscriptions","organizations_url":"https://api.github.com/users/VSadov/orgs","repos_url":"https://api.github.com/users/VSadov/repos","events_url":"https://api.github.com/users/VSadov/events{/privacy}","received_events_url":"https://api.github.com/users/VSadov/received_events","type":"User","site_admin":false},"body":"is this a byte-wise comparison?","created_at":"2015-11-17T21:15:32Z","updated_at":"2015-11-17T21:15:32Z","html_url":"https://github.com/dotnet/corefxlab/pull/455#discussion_r45121887","pull_request_url":"https://api.github.com/repos/dotnet/corefxlab/pulls/455","_links":{"self":{"href":"https://api.github.com/repos/dotnet/corefxlab/pulls/comments/45121887"},"html":{"href":"https://github.com/dotnet/corefxlab/pull/455#discussion_r45121887"},"pull_request":{"href":"https://api.github.com/repos/dotnet/corefxlab/pulls/455"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/corefxlab/pulls/455","id":50889676,"html_url":"https://github.com/dotnet/corefxlab/pull/455","diff_url":"https://github.com/dotnet/corefxlab/pull/455.diff","patch_url":"https://github.com/dotnet/corefxlab/pull/455.patch","issue_url":"https://api.github.com/repos/dotnet/corefxlab/issues/455","number":455,"state":"open","locked":false,"title":"Slice: fast SequenceEqual & StructuralEqual","user":{"login":"adamsitnik","id":6011991,"avatar_url":"https://avatars.githubusercontent.com/u/6011991?v=3","gravatar_id":"","url":"https://api.github.com/users/adamsitnik","html_url":"https://github.com/adamsitnik","followers_url":"https://api.github.com/users/adamsitnik/followers","following_url":"https://api.github.com/users/adamsitnik/following{/other_user}","gists_url":"https://api.github.com/users/adamsitnik/gists{/gist_id}","starred_url":"https://api.github.com/users/adamsitnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamsitnik/subscriptions","organizations_url":"https://api.github.com/users/adamsitnik/orgs","repos_url":"https://api.github.com/users/adamsitnik/repos","events_url":"https://api.github.com/users/adamsitnik/events{/privacy}","received_events_url":"https://api.github.com/users/adamsitnik/received_events","type":"User","site_admin":false},"body":"I have implemented fast SequenceEqual & StructuralEqual methods for Span and changed the behaviour of Equals and GetHashCode.\r\n\r\nWhen Span is small, simple for loop iteration is being done. If it is huge, then memcmp is called.\r\n\r\nSequenceEqual compares all elements of Slice, it has generic constraint of IEqutable<T> to make fast comparison possible. Reason: [benchmarks](https://github.com/adamsitnik/DemoCode/blob/master/Performance/Benchmarks/Collections/SequentialEqualityBenchmarks.cs) and [results](https://github.com/adamsitnik/DemoCode/blob/master/Performance/Benchmarks/results/SequentialEqualityBenchmarks.txt)\r\n\r\nStructuralEqual simply casts two Spans of different types  to Span of same type and calls SequenceEqual. If size in bytes is multiplication of 8, then it casts to Span< long >, if % 4 then to Span< int >, if % 2 then Span< short >. Otherwise to Span< byte >. The reason is that comparing N long elements is faster than comparing N*8 byte elements (in a loop, optimization for small, but common slices)\r\n\r\nThe changed behaviour of Equals and GetHashCode is now the same as of any other .NET collection: simple ReferenceEquals. ","created_at":"2015-11-17T00:49:48Z","updated_at":"2015-11-17T21:15:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e4b2208fc6c8ffcef9125a3e0c840804d08c3358","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/corefxlab/pulls/455/commits","review_comments_url":"https://api.github.com/repos/dotnet/corefxlab/pulls/455/comments","review_comment_url":"https://api.github.com/repos/dotnet/corefxlab/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/corefxlab/issues/455/comments","statuses_url":"https://api.github.com/repos/dotnet/corefxlab/statuses/1835bb01d0348c720434015b900509db6af9c15f","head":{"label":"adamsitnik:master","ref":"master","sha":"1835bb01d0348c720434015b900509db6af9c15f","user":{"login":"adamsitnik","id":6011991,"avatar_url":"https://avatars.githubusercontent.com/u/6011991?v=3","gravatar_id":"","url":"https://api.github.com/users/adamsitnik","html_url":"https://github.com/adamsitnik","followers_url":"https://api.github.com/users/adamsitnik/followers","following_url":"https://api.github.com/users/adamsitnik/following{/other_user}","gists_url":"https://api.github.com/users/adamsitnik/gists{/gist_id}","starred_url":"https://api.github.com/users/adamsitnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamsitnik/subscriptions","organizations_url":"https://api.github.com/users/adamsitnik/orgs","repos_url":"https://api.github.com/users/adamsitnik/repos","events_url":"https://api.github.com/users/adamsitnik/events{/privacy}","received_events_url":"https://api.github.com/users/adamsitnik/received_events","type":"User","site_admin":false},"repo":{"id":45297067,"name":"corefxlab","full_name":"adamsitnik/corefxlab","owner":{"login":"adamsitnik","id":6011991,"avatar_url":"https://avatars.githubusercontent.com/u/6011991?v=3","gravatar_id":"","url":"https://api.github.com/users/adamsitnik","html_url":"https://github.com/adamsitnik","followers_url":"https://api.github.com/users/adamsitnik/followers","following_url":"https://api.github.com/users/adamsitnik/following{/other_user}","gists_url":"https://api.github.com/users/adamsitnik/gists{/gist_id}","starred_url":"https://api.github.com/users/adamsitnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamsitnik/subscriptions","organizations_url":"https://api.github.com/users/adamsitnik/orgs","repos_url":"https://api.github.com/users/adamsitnik/repos","events_url":"https://api.github.com/users/adamsitnik/events{/privacy}","received_events_url":"https://api.github.com/users/adamsitnik/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/adamsitnik/corefxlab","description":"This repo is for experimentation and exploring new ideas that may or may not make it into the main corefx repo.","fork":true,"url":"https://api.github.com/repos/adamsitnik/corefxlab","forks_url":"https://api.github.com/repos/adamsitnik/corefxlab/forks","keys_url":"https://api.github.com/repos/adamsitnik/corefxlab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/adamsitnik/corefxlab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/adamsitnik/corefxlab/teams","hooks_url":"https://api.github.com/repos/adamsitnik/corefxlab/hooks","issue_events_url":"https://api.github.com/repos/adamsitnik/corefxlab/issues/events{/number}","events_url":"https://api.github.com/repos/adamsitnik/corefxlab/events","assignees_url":"https://api.github.com/repos/adamsitnik/corefxlab/assignees{/user}","branches_url":"https://api.github.com/repos/adamsitnik/corefxlab/branches{/branch}","tags_url":"https://api.github.com/repos/adamsitnik/corefxlab/tags","blobs_url":"https://api.github.com/repos/adamsitnik/corefxlab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/adamsitnik/corefxlab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/adamsitnik/corefxlab/git/refs{/sha}","trees_url":"https://api.github.com/repos/adamsitnik/corefxlab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/adamsitnik/corefxlab/statuses/{sha}","languages_url":"https://api.github.com/repos/adamsitnik/corefxlab/languages","stargazers_url":"https://api.github.com/repos/adamsitnik/corefxlab/stargazers","contributors_url":"https://api.github.com/repos/adamsitnik/corefxlab/contributors","subscribers_url":"https://api.github.com/repos/adamsitnik/corefxlab/subscribers","subscription_url":"https://api.github.com/repos/adamsitnik/corefxlab/subscription","commits_url":"https://api.github.com/repos/adamsitnik/corefxlab/commits{/sha}","git_commits_url":"https://api.github.com/repos/adamsitnik/corefxlab/git/commits{/sha}","comments_url":"https://api.github.com/repos/adamsitnik/corefxlab/comments{/number}","issue_comment_url":"https://api.github.com/repos/adamsitnik/corefxlab/issues/comments{/number}","contents_url":"https://api.github.com/repos/adamsitnik/corefxlab/contents/{+path}","compare_url":"https://api.github.com/repos/adamsitnik/corefxlab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/adamsitnik/corefxlab/merges","archive_url":"https://api.github.com/repos/adamsitnik/corefxlab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/adamsitnik/corefxlab/downloads","issues_url":"https://api.github.com/repos/adamsitnik/corefxlab/issues{/number}","pulls_url":"https://api.github.com/repos/adamsitnik/corefxlab/pulls{/number}","milestones_url":"https://api.github.com/repos/adamsitnik/corefxlab/milestones{/number}","notifications_url":"https://api.github.com/repos/adamsitnik/corefxlab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/adamsitnik/corefxlab/labels{/name}","releases_url":"https://api.github.com/repos/adamsitnik/corefxlab/releases{/id}","created_at":"2015-10-31T10:07:19Z","updated_at":"2015-10-31T10:07:23Z","pushed_at":"2015-11-17T10:54:09Z","git_url":"git://github.com/adamsitnik/corefxlab.git","ssh_url":"git@github.com:adamsitnik/corefxlab.git","clone_url":"https://github.com/adamsitnik/corefxlab.git","svn_url":"https://github.com/adamsitnik/corefxlab","homepage":"","size":25416,"stargazers_count":0,"watchers_count":0,"language":"C#","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":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"549d68fe835b9c40001a99fdaab71e89ca6ef755","user":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":29504192,"name":"corefxlab","full_name":"dotnet/corefxlab","owner":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dotnet/corefxlab","description":"This repo is for experimentation and exploring new ideas that may or may not make it into the main corefx repo.","fork":false,"url":"https://api.github.com/repos/dotnet/corefxlab","forks_url":"https://api.github.com/repos/dotnet/corefxlab/forks","keys_url":"https://api.github.com/repos/dotnet/corefxlab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/corefxlab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/corefxlab/teams","hooks_url":"https://api.github.com/repos/dotnet/corefxlab/hooks","issue_events_url":"https://api.github.com/repos/dotnet/corefxlab/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/corefxlab/events","assignees_url":"https://api.github.com/repos/dotnet/corefxlab/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/corefxlab/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/corefxlab/tags","blobs_url":"https://api.github.com/repos/dotnet/corefxlab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/corefxlab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/corefxlab/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/corefxlab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/corefxlab/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/corefxlab/languages","stargazers_url":"https://api.github.com/repos/dotnet/corefxlab/stargazers","contributors_url":"https://api.github.com/repos/dotnet/corefxlab/contributors","subscribers_url":"https://api.github.com/repos/dotnet/corefxlab/subscribers","subscription_url":"https://api.github.com/repos/dotnet/corefxlab/subscription","commits_url":"https://api.github.com/repos/dotnet/corefxlab/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/corefxlab/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/corefxlab/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/corefxlab/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/corefxlab/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/corefxlab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/corefxlab/merges","archive_url":"https://api.github.com/repos/dotnet/corefxlab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/corefxlab/downloads","issues_url":"https://api.github.com/repos/dotnet/corefxlab/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/corefxlab/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/corefxlab/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/corefxlab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/corefxlab/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/corefxlab/releases{/id}","created_at":"2015-01-20T00:44:35Z","updated_at":"2015-11-16T20:30:26Z","pushed_at":"2015-11-17T19:24:59Z","git_url":"git://github.com/dotnet/corefxlab.git","ssh_url":"git@github.com:dotnet/corefxlab.git","clone_url":"https://github.com/dotnet/corefxlab.git","svn_url":"https://github.com/dotnet/corefxlab","homepage":"","size":26694,"stargazers_count":197,"watchers_count":197,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":86,"mirror_url":null,"open_issues_count":85,"forks":86,"open_issues":85,"watchers":197,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/corefxlab/pulls/455"},"html":{"href":"https://github.com/dotnet/corefxlab/pull/455"},"issue":{"href":"https://api.github.com/repos/dotnet/corefxlab/issues/455"},"comments":{"href":"https://api.github.com/repos/dotnet/corefxlab/issues/455/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/corefxlab/pulls/455/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/corefxlab/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/corefxlab/pulls/455/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/corefxlab/statuses/1835bb01d0348c720434015b900509db6af9c15f"}}}}