{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/corefxlab/pulls/comments/45546123","id":45546123,"diff_hunk":"@@ -0,0 +1,60 @@\n+﻿// Copyright (c) Microsoft. All rights reserved.\n+// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n+\n+using System.Runtime.InteropServices;\n+\n+namespace System\n+{\n+    internal static partial class MemoryUtils\n+    {\n+        /// <summary>\n+        /// platform independent fast memory comparison based on idea from String.EqualsHelper \n+        /// </summary>\n+        internal static bool MemCmp<[Primitive]T>(Span<T> first, Span<T> second)\n+            where T : struct\n+        {\n+            unsafe\n+            {\n+                // prevent GC from moving memory\n+                var firstPinnedHandle = GCHandle.Alloc(first.Object, GCHandleType.Pinned);\n+                var secondPinnedHandle = GCHandle.Alloc(second.Object, GCHandleType.Pinned);\n+\n+                try\n+                {\n+                    byte* firstPointer = (byte*)PtrUtils.ComputeAddress(first.Object, first.Offset).ToPointer();\n+                    byte* secondPointer = (byte*)PtrUtils.ComputeAddress(second.Object, second.Offset).ToPointer();\n+\n+                    long bytesCount = first.Length * PtrUtils.SizeOf<T>();\n+","path":"src/System.Slices/src/System/MemoryUtils.Other.cs","position":null,"original_position":28,"commit_id":"eab5e2c9aa02db7d2cd5225e4dd5f1651a2b27da","original_commit_id":"115277173077637f57e4f11e200672ba8c6def8b","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":"@VSadov  I took your sample code and all your hints and worked a little on. The result is platform independent MemCmp, which for x64 it is as fast as memcmp of msvcrt.dll, for x86 it is up to two times faster!!\r\n\r\nIn the next few hours my machines should finish executing full benchmarks, I will update them then.","created_at":"2015-11-21T13:36:42Z","updated_at":"2015-11-21T13:36:42Z","html_url":"https://github.com/dotnet/corefxlab/pull/455#discussion_r45546123","pull_request_url":"https://api.github.com/repos/dotnet/corefxlab/pulls/455","_links":{"self":{"href":"https://api.github.com/repos/dotnet/corefxlab/pulls/comments/45546123"},"html":{"href":"https://github.com/dotnet/corefxlab/pull/455#discussion_r45546123"},"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\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) It does not call the memcmp to avoid any custom IEqutable implementations problems.\r\n\r\nThere are also new dedicated SequenceEqual methods for most common primitive types (byte, char, long etc). When such Span is small, simple for loop iteration is being done. If it is huge, then memcmp is called. Reason: pinning is expensive, as you can see in previous benchmark.\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. \r\n\r\nMoreover there is no ReferenceEquals check in SequenceEqual/StructuralEqual. I believe that Spans of bytes are going to be the most common ones, and if they are small, then the cost of such a check is relatively expensive. I also think that comparison of Spans referencing same memory is going to be very uncommon so I chose the certain gain in most common scenario with possible huge loss in most pessimistic case.  ","created_at":"2015-11-17T00:49:48Z","updated_at":"2015-11-21T13:36:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"23836abe8955b4ebc95f63a1f12145c411b59a41","assignee":{"login":"krwq","id":660048,"avatar_url":"https://avatars.githubusercontent.com/u/660048?v=3","gravatar_id":"","url":"https://api.github.com/users/krwq","html_url":"https://github.com/krwq","followers_url":"https://api.github.com/users/krwq/followers","following_url":"https://api.github.com/users/krwq/following{/other_user}","gists_url":"https://api.github.com/users/krwq/gists{/gist_id}","starred_url":"https://api.github.com/users/krwq/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krwq/subscriptions","organizations_url":"https://api.github.com/users/krwq/orgs","repos_url":"https://api.github.com/users/krwq/repos","events_url":"https://api.github.com/users/krwq/events{/privacy}","received_events_url":"https://api.github.com/users/krwq/received_events","type":"User","site_admin":false},"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/eab5e2c9aa02db7d2cd5225e4dd5f1651a2b27da","head":{"label":"adamsitnik:master","ref":"master","sha":"eab5e2c9aa02db7d2cd5225e4dd5f1651a2b27da","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-21T13:25:27Z","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":26287,"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":"d751b83dee4731fc9a39da50154aa6e812c9ccb5","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-20T08:23:41Z","pushed_at":"2015-11-21T13:25:27Z","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":26816,"stargazers_count":198,"watchers_count":198,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":88,"mirror_url":null,"open_issues_count":83,"forks":88,"open_issues":83,"watchers":198,"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/eab5e2c9aa02db7d2cd5225e4dd5f1651a2b27da"}}}}