{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/corefx/pulls/comments/85828772","pull_request_review_id":6521505,"id":85828772,"diff_hunk":"@@ -657,8 +673,134 @@ public override Task WriteAsync(Byte[] array, int offset, int count, Cancellatio\n \n         public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)\n         {\n-            return StreamHelpers.ArrayPoolCopyToAsync(this, destination, bufferSize, cancellationToken: cancellationToken);\n+            // Validation as base CopyToAsync would do\n+            StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);\n+\n+            // Validation as ReadAsync would do\n+            EnsureDecompressionMode();\n+            if (_asyncOperations != 0) throw new InvalidOperationException(SR.InvalidBeginCall);\n+            EnsureNotDisposed();\n+\n+            // Early check for cancellation\n+            if (cancellationToken.IsCancellationRequested)\n+            {\n+                return Task.FromCanceled<int>(cancellationToken);\n+            }\n+\n+            // The caller asked for a specific bufferSize, but we're going to end up potentially using two buffers:\n+            // a buffer for storing the inflated output and passing along to the destination stream, and whatever\n+            // buffer the source stream creates in its CopyToAsync implementation.  As such, we halve the buffer size,\n+            // to split it across the two.\n+            bufferSize = Math.Max(1, bufferSize / 2);\n+\n+            // Do the copy\n+            return new CopyToAsyncStream(this, destination, ArrayPool<byte>.Shared.Rent(bufferSize), cancellationToken).CopyFromSourceToDestination();\n+        }\n+\n+        private sealed class CopyToAsyncStream : Stream\n+        {\n+            private readonly DeflateStream _deflateStream;\n+            private readonly Stream _destination;\n+            private readonly CancellationToken _cancellationToken;\n+            private readonly byte[] _arrayPoolBuffer;\n+            private int _arrayPoolBufferHighWaterMark;\n+\n+            public CopyToAsyncStream(DeflateStream deflateStream, Stream destination, byte[] arrayPoolBuffer, CancellationToken cancellationToken)\n+            {\n+                Debug.Assert(deflateStream != null);\n+                Debug.Assert(destination != null);\n+                Debug.Assert(arrayPoolBuffer != null && arrayPoolBuffer.Length > 0);\n+\n+                _deflateStream = deflateStream;\n+                _destination = destination;\n+                _arrayPoolBuffer = arrayPoolBuffer;\n+                _cancellationToken = cancellationToken;\n+            }\n+\n+            public async Task CopyFromSourceToDestination()\n+            {\n+                _deflateStream.IncrementAsyncOperations();\n+                try\n+                {\n+                    // Flush any existing data in the inflater to the destination stream.\n+                    while (true)\n+                    {\n+                        int bytesRead = _deflateStream._inflater.Inflate(_arrayPoolBuffer, 0, _arrayPoolBuffer.Length);\n+                        if (bytesRead > 0)\n+                        {\n+                            if (bytesRead > _arrayPoolBufferHighWaterMark) _arrayPoolBufferHighWaterMark = bytesRead;\n+                            await _destination.WriteAsync(_arrayPoolBuffer, 0, bytesRead, _cancellationToken).ConfigureAwait(false);\n+                        }\n+                        else break;\n+                    }\n+\n+                    // Now, use the source stream's CopyToAsync to push directly to our inflater via this helper stream\n+                    await _deflateStream._stream.CopyToAsync(this, _arrayPoolBuffer.Length, _cancellationToken).ConfigureAwait(false);\n+                }\n+                finally\n+                {\n+                    _deflateStream.DecrementAsyncOperations();\n+\n+                    Array.Clear(_arrayPoolBuffer, 0, _arrayPoolBufferHighWaterMark); // clear only the most we used\n+                    ArrayPool<byte>.Shared.Return(_arrayPoolBuffer, clearArray: false);\n+                }\n+            }\n+\n+            public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)\n+            {\n+                // Validate inputs\n+                Debug.Assert(buffer != _arrayPoolBuffer);\n+                _deflateStream.EnsureNotDisposed();\n+                if (count <= 0)\n+                {\n+                    return;\n+                }\n+                else if (count > buffer.Length - offset)\n+                {\n+                    // The source stream is either malicious or poorly implemented and returned a number of\n+                    // bytes larger than the buffer supplied to it.\n+                    throw new InvalidDataException(SR.GenericInvalidData);\n+                }\n+\n+                // Feed the data from base stream into the decompression engine.\n+                _deflateStream._inflater.SetInput(buffer, offset, count);\n+\n+                // While there's more decompressed data available, forward it to the destination stream.\n+                while (true)\n+                {\n+                    int bytesRead = _deflateStream._inflater.Inflate(_arrayPoolBuffer, 0, _arrayPoolBuffer.Length);\n+                    if (bytesRead > 0)\n+                    {\n+                        if (bytesRead > _arrayPoolBufferHighWaterMark) _arrayPoolBufferHighWaterMark = bytesRead;\n+                        await _destination.WriteAsync(_arrayPoolBuffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);\n+                    }\n+                    else break;","path":"src/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs","position":227,"original_position":227,"commit_id":"4df026ae2a202296a5717f7299ac18e600a7ee6a","original_commit_id":"4df026ae2a202296a5717f7299ac18e600a7ee6a","user":{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false},"body":"Interesting. Ok, I'll fix that. Thanks.","created_at":"2016-10-31T20:44:50Z","updated_at":"2016-10-31T20:44:50Z","html_url":"https://github.com/dotnet/corefx/pull/13184#discussion_r85828772","pull_request_url":"https://api.github.com/repos/dotnet/corefx/pulls/13184","_links":{"self":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/comments/85828772"},"html":{"href":"https://github.com/dotnet/corefx/pull/13184#discussion_r85828772"},"pull_request":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/13184"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/corefx/pulls/13184","id":91677072,"html_url":"https://github.com/dotnet/corefx/pull/13184","diff_url":"https://github.com/dotnet/corefx/pull/13184.diff","patch_url":"https://github.com/dotnet/corefx/pull/13184.patch","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/13184","number":13184,"state":"open","locked":false,"title":"Optimize DeflateStream.CopyToAsync","user":{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false},"body":"Today, CopyToAsync on DeflateStream is the basic read/write loop.  However, all CopyToAsync really needs to do on DeflateStream is transform the source data (via a synchronous operation) and pass it along to the destination.  This means that we can improve its implementation by effectively having the source stream CopyToAsync to the destination stream, albeit with that transformation added in the middle.  Doing this has a three key benefits:\r\n- It eliminates the read operations and the associated copy, allowing the source to effectively push directly to the inflater inside DeflateStream.\r\n- It takes advantage of any optimizations the source stream has in its CopyToAsync implementation, e.g. MemoryStream simply passing its whole internal buffer, NetworkStream using a SocketAsyncEventArgs (https://github.com/dotnet/corefx/pull/12664), FileStream reusing its async state (https://github.com/dotnet/corefx/pull/11569), etc.\r\n- CopyToAsync is typically used when no other reading has been done from the stream.  Since this change causes CopyToAsync to bypass the internal buffer used by DeflateStream before the inflater itself, we can avoid allocating that buffer at all if CopyToAsync is used by itself.  This avoids an 8K allocation per DeflateStream instance, and even if we switch to pulling this buffer from ArrayPool, it still avoids needing to rent/return with the ArrayPool in these cases.\r\n\r\n(I also noticed an unnecessary allocation in Inflater, which I removed.)\r\n\r\nThe net effect of this change is a sizeable boost on throughput for many scenarios (I didn't find any scenarios where it regressed).  Here are a few examples.  In this table, \"MS\" is a memory stream, so \"MS to MS\" is using DeflateStream created around a compressed MemoryStream and using CopyToAsync on the DeflateStream to decompress it to another MemoryStream.  \"CMS\" is a \"CustomMemoryStream\", which is simply a type that derives from MemoryStream and doesn't add or override any logic; this derivation defeats some the CopyToAsync optimization in MemoryStream, so this is essentially the worst case for this DeflateStream optimization.  And \"FS\" is FileStream, where a \"(true)\" suffix means useAsync==true (in which case FileStream has its own CopyToAsync implementation) and a \"(false)\" suffix means useAsync==false (in which case it essentially delegates back to the base Stream's CopyToAsync). \"Len\" is the length of the original random input in bytes, and \"Iters\" is the number of iterations (the number of times positions were reset and CopyToAsync was called).\r\n\r\n| Test                                              | Before (s) | After (s)|\r\n|---------------------------------------------------|-----------|-----------|\r\n| MS to MS (Len=1024     Iters=1024000)             |  2.767149 | 1.601566  |\r\n| MS to MS (Len=1048576  Iters=1000)                |  0.419615 | 0.139993  |\r\n| MS to MS (Len=10485760 Iters=100)                 |  0.358287 | 0.223764  |\r\n| CMS to CMS (Len=1024     Iters=1024000)           |  2.832110 | 1.963891  |\r\n| CMS to CMS (Len=1048576  Iters=1000)              |  0.271432 | 0.202536  |\r\n| CMS to CMS (Len=10485760 Iters=100)               |  0.347356 | 0.316338  |\r\n| FS(True) to FS(True) (Len=1024     Iters=102400)  | 10.315941 | 6.909713  |\r\n| FS(True) to FS(True) (Len=1048576  Iters=100)     |  0.940410 | 0.124353  |\r\n| FS(True) to FS(True) (Len=10485760 Iters=10)      |  1.000786 | 0.152991  |\r\n| FS(True) to FS(False) (Len=1024     Iters=102400) |  9.936322 | 6.967522  |\r\n| FS(True) to FS(False) (Len=1048576  Iters=100)    |  0.705946 | 0.085895  |\r\n| FS(True) to FS(False) (Len=10485760 Iters=10)     |  0.925196 | 0.159865  |\r\n| FS(False) toFS (True) (Len=1024     Iters=102400) |  8.630263 | 6.699364  |\r\n| FS(False) toFS (True) (Len=1048576  Iters=100)    |  0.880577 | 0.116051  |\r\n| FS(False) toFS (True) (Len=10485760 Iters=10)     |  0.862978 | 0.142838  |\r\n| FS(False) toFS (False) (Len=1024     Iters=102400)|  5.260478 | 4.388572  |\r\n| FS(False) toFS (False) (Len=1048576  Iters=100)   |  0.346608 | 0.078440  |\r\n| FS(False) toFS (False) (Len=10485760 Iters=10)    |  0.432393 | 0.157312  | \r\n\r\nFixes https://github.com/dotnet/corefx/issues/11571\r\nContributes to https://github.com/dotnet/corefx/issues/12549\r\ncc: @ianhays, @JeremyKuhne, @geoffkizer, @benaadams, @davidfowl \r\n\r\n(@ianhays, please pay careful attention to my use of the inflater.  I essentially copied what was in ReadAsync and refactored it, and I want to make sure I'm using it correctly / didn't misunderstand anything about its behavior.)","created_at":"2016-10-31T19:46:27Z","updated_at":"2016-10-31T20:44:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c79b7ba468551067c26c6fe91bc002485a12b511","assignee":{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false},"assignees":[{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/corefx/pulls/13184/commits","review_comments_url":"https://api.github.com/repos/dotnet/corefx/pulls/13184/comments","review_comment_url":"https://api.github.com/repos/dotnet/corefx/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/13184/comments","statuses_url":"https://api.github.com/repos/dotnet/corefx/statuses/4df026ae2a202296a5717f7299ac18e600a7ee6a","head":{"label":"stephentoub:deflatestream_copytoasync","ref":"deflatestream_copytoasync","sha":"4df026ae2a202296a5717f7299ac18e600a7ee6a","user":{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false},"repo":{"id":26551529,"name":"corefx","full_name":"stephentoub/corefx","owner":{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/stephentoub/corefx","description":"This repository contains the foundational libraries that make up the .NET Core development stack.","fork":true,"url":"https://api.github.com/repos/stephentoub/corefx","forks_url":"https://api.github.com/repos/stephentoub/corefx/forks","keys_url":"https://api.github.com/repos/stephentoub/corefx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/stephentoub/corefx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/stephentoub/corefx/teams","hooks_url":"https://api.github.com/repos/stephentoub/corefx/hooks","issue_events_url":"https://api.github.com/repos/stephentoub/corefx/issues/events{/number}","events_url":"https://api.github.com/repos/stephentoub/corefx/events","assignees_url":"https://api.github.com/repos/stephentoub/corefx/assignees{/user}","branches_url":"https://api.github.com/repos/stephentoub/corefx/branches{/branch}","tags_url":"https://api.github.com/repos/stephentoub/corefx/tags","blobs_url":"https://api.github.com/repos/stephentoub/corefx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/stephentoub/corefx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/stephentoub/corefx/git/refs{/sha}","trees_url":"https://api.github.com/repos/stephentoub/corefx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/stephentoub/corefx/statuses/{sha}","languages_url":"https://api.github.com/repos/stephentoub/corefx/languages","stargazers_url":"https://api.github.com/repos/stephentoub/corefx/stargazers","contributors_url":"https://api.github.com/repos/stephentoub/corefx/contributors","subscribers_url":"https://api.github.com/repos/stephentoub/corefx/subscribers","subscription_url":"https://api.github.com/repos/stephentoub/corefx/subscription","commits_url":"https://api.github.com/repos/stephentoub/corefx/commits{/sha}","git_commits_url":"https://api.github.com/repos/stephentoub/corefx/git/commits{/sha}","comments_url":"https://api.github.com/repos/stephentoub/corefx/comments{/number}","issue_comment_url":"https://api.github.com/repos/stephentoub/corefx/issues/comments{/number}","contents_url":"https://api.github.com/repos/stephentoub/corefx/contents/{+path}","compare_url":"https://api.github.com/repos/stephentoub/corefx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/stephentoub/corefx/merges","archive_url":"https://api.github.com/repos/stephentoub/corefx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/stephentoub/corefx/downloads","issues_url":"https://api.github.com/repos/stephentoub/corefx/issues{/number}","pulls_url":"https://api.github.com/repos/stephentoub/corefx/pulls{/number}","milestones_url":"https://api.github.com/repos/stephentoub/corefx/milestones{/number}","notifications_url":"https://api.github.com/repos/stephentoub/corefx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/stephentoub/corefx/labels{/name}","releases_url":"https://api.github.com/repos/stephentoub/corefx/releases{/id}","deployments_url":"https://api.github.com/repos/stephentoub/corefx/deployments","created_at":"2014-11-12T19:06:24Z","updated_at":"2016-10-22T10:27:30Z","pushed_at":"2016-10-31T19:36:26Z","git_url":"git://github.com/stephentoub/corefx.git","ssh_url":"git@github.com:stephentoub/corefx.git","clone_url":"https://github.com/stephentoub/corefx.git","svn_url":"https://github.com/stephentoub/corefx","homepage":"","size":109303,"stargazers_count":2,"watchers_count":2,"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":2,"default_branch":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"eb883d78defbc7d4cae3b8ebd0fa68852eb583e3","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":26295345,"name":"corefx","full_name":"dotnet/corefx","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/corefx","description":"This repo contains the .NET Core foundational libraries, called CoreFX. It includes classes for collections, file systems, console, XML, async and many others.","fork":false,"url":"https://api.github.com/repos/dotnet/corefx","forks_url":"https://api.github.com/repos/dotnet/corefx/forks","keys_url":"https://api.github.com/repos/dotnet/corefx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/corefx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/corefx/teams","hooks_url":"https://api.github.com/repos/dotnet/corefx/hooks","issue_events_url":"https://api.github.com/repos/dotnet/corefx/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/corefx/events","assignees_url":"https://api.github.com/repos/dotnet/corefx/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/corefx/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/corefx/tags","blobs_url":"https://api.github.com/repos/dotnet/corefx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/corefx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/corefx/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/corefx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/corefx/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/corefx/languages","stargazers_url":"https://api.github.com/repos/dotnet/corefx/stargazers","contributors_url":"https://api.github.com/repos/dotnet/corefx/contributors","subscribers_url":"https://api.github.com/repos/dotnet/corefx/subscribers","subscription_url":"https://api.github.com/repos/dotnet/corefx/subscription","commits_url":"https://api.github.com/repos/dotnet/corefx/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/corefx/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/corefx/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/corefx/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/corefx/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/corefx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/corefx/merges","archive_url":"https://api.github.com/repos/dotnet/corefx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/corefx/downloads","issues_url":"https://api.github.com/repos/dotnet/corefx/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/corefx/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/corefx/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/corefx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/corefx/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/corefx/releases{/id}","deployments_url":"https://api.github.com/repos/dotnet/corefx/deployments","created_at":"2014-11-06T23:42:48Z","updated_at":"2016-10-31T19:00:11Z","pushed_at":"2016-10-31T20:31:07Z","git_url":"git://github.com/dotnet/corefx.git","ssh_url":"git@github.com:dotnet/corefx.git","clone_url":"https://github.com/dotnet/corefx.git","svn_url":"https://github.com/dotnet/corefx","homepage":"https://docs.microsoft.com/dotnet/","size":157949,"stargazers_count":10716,"watchers_count":10716,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2703,"mirror_url":null,"open_issues_count":1421,"forks":2703,"open_issues":1421,"watchers":10716,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/13184"},"html":{"href":"https://github.com/dotnet/corefx/pull/13184"},"issue":{"href":"https://api.github.com/repos/dotnet/corefx/issues/13184"},"comments":{"href":"https://api.github.com/repos/dotnet/corefx/issues/13184/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/13184/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/corefx/pulls/13184/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/corefx/statuses/4df026ae2a202296a5717f7299ac18e600a7ee6a"}}}}
{"actor":{"display_login":"stephentoub"}}