{"action":"created","comment":{"url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments/87859188","pull_request_review_id":8453245,"id":87859188,"diff_hunk":"@@ -0,0 +1,171 @@\n+﻿// Copyright (c) .NET Foundation. All rights reserved.\n+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n+\n+using System;\n+using System.Collections.Generic;\n+using System.IO;\n+using Newtonsoft.Json;\n+using NuGet.RuntimeModel;\n+\n+namespace NuGet.ProjectModel\n+{\n+    /// <summary>\n+    /// Generates a hash from an object graph.\n+    ///\n+    /// This is non-private only to facilitate unit testing.\n+    /// </summary>\n+    public sealed class HashWriter : IObjectWriter, IDisposable\n+    {\n+        private const int _defaultBufferSize = 4096;\n+\n+        private readonly byte[] _buffer;\n+        private readonly IHashFunction _hashFunc;\n+        private bool _isReadOnly;\n+        private int _nestLevel;\n+        private CircularMemoryStream _stream;","path":"src/NuGet.Core/NuGet.ProjectModel/HashWriter.cs","position":25,"original_position":25,"commit_id":"3e77be68818217012163813143c15a2b6d819e82","original_commit_id":"3e77be68818217012163813143c15a2b6d819e82","user":{"login":"alpaix","id":8239356,"avatar_url":"https://avatars.githubusercontent.com/u/8239356?v=3","gravatar_id":"","url":"https://api.github.com/users/alpaix","html_url":"https://github.com/alpaix","followers_url":"https://api.github.com/users/alpaix/followers","following_url":"https://api.github.com/users/alpaix/following{/other_user}","gists_url":"https://api.github.com/users/alpaix/gists{/gist_id}","starred_url":"https://api.github.com/users/alpaix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alpaix/subscriptions","organizations_url":"https://api.github.com/users/alpaix/orgs","repos_url":"https://api.github.com/users/alpaix/repos","events_url":"https://api.github.com/users/alpaix/events{/privacy}","received_events_url":"https://api.github.com/users/alpaix/received_events","type":"User","site_admin":false},"body":"Add `readonly` where necessary.","created_at":"2016-11-14T18:15:37Z","updated_at":"2016-11-14T18:15:37Z","html_url":"https://github.com/NuGet/NuGet.Client/pull/1014#discussion_r87859188","pull_request_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014","_links":{"self":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments/87859188"},"html":{"href":"https://github.com/NuGet/NuGet.Client/pull/1014#discussion_r87859188"},"pull_request":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014"}}},"pull_request":{"url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014","id":92990834,"html_url":"https://github.com/NuGet/NuGet.Client/pull/1014","diff_url":"https://github.com/NuGet/NuGet.Client/pull/1014.diff","patch_url":"https://github.com/NuGet/NuGet.Client/pull/1014.patch","issue_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/1014","number":1014,"state":"open","locked":false,"title":"Generate hash for DependencyGraphSpec","user":{"login":"dtivel","id":12734758,"avatar_url":"https://avatars.githubusercontent.com/u/12734758?v=3","gravatar_id":"","url":"https://api.github.com/users/dtivel","html_url":"https://github.com/dtivel","followers_url":"https://api.github.com/users/dtivel/followers","following_url":"https://api.github.com/users/dtivel/following{/other_user}","gists_url":"https://api.github.com/users/dtivel/gists{/gist_id}","starred_url":"https://api.github.com/users/dtivel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dtivel/subscriptions","organizations_url":"https://api.github.com/users/dtivel/orgs","repos_url":"https://api.github.com/users/dtivel/repos","events_url":"https://api.github.com/users/dtivel/events{/privacy}","received_events_url":"https://api.github.com/users/dtivel/received_events","type":"User","site_admin":false},"body":"The current implementation walks a `DependencyGraphSpec` object graph, creates a JSON object representation, serializes the JSON object to string, and uses `string.GetHashCode()` to generate a hash code.  This creates a lot of temporary objects in memory.  On a large project the memory usage for this operation averaged ~1.8 MB.\r\n\r\nThese changes switch to generating a SHA-512 hash over a `DependencyGraphSpec` object graph using the same code path as JSON serialization.  On a large project CPU performance is on par with the existing solution while memory performance is significantly and consistently better (on average <0.25 MB).\r\n\r\nSince sort order is crucial to producing stable hashing results, I've added sorting of some data in both `PackageSpecWriter` and `JsonRuntimeFormat`.  Since the same code path is used for JSON serialization, I ask that you scrutinize those changes carefully to verify I haven't introduced undesirable behavior.\r\n\r\n@rrelyea @emgarten @joelverhagen @drewgil @alpaix @mishra14 @jainaashish @zhili1208 @rohit21agrawal","created_at":"2016-11-09T16:09:16Z","updated_at":"2016-11-14T18:15:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ba060fe05e2256c01296e12c91158bf77e44cc0d","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014/commits","review_comments_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014/comments","review_comment_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments{/number}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/1014/comments","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Client/statuses/3e77be68818217012163813143c15a2b6d819e82","head":{"label":"dtivel:dev-dtivel-hash-dependencygraphspec","ref":"dev-dtivel-hash-dependencygraphspec","sha":"3e77be68818217012163813143c15a2b6d819e82","user":{"login":"dtivel","id":12734758,"avatar_url":"https://avatars.githubusercontent.com/u/12734758?v=3","gravatar_id":"","url":"https://api.github.com/users/dtivel","html_url":"https://github.com/dtivel","followers_url":"https://api.github.com/users/dtivel/followers","following_url":"https://api.github.com/users/dtivel/following{/other_user}","gists_url":"https://api.github.com/users/dtivel/gists{/gist_id}","starred_url":"https://api.github.com/users/dtivel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dtivel/subscriptions","organizations_url":"https://api.github.com/users/dtivel/orgs","repos_url":"https://api.github.com/users/dtivel/repos","events_url":"https://api.github.com/users/dtivel/events{/privacy}","received_events_url":"https://api.github.com/users/dtivel/received_events","type":"User","site_admin":false},"repo":{"id":71278672,"name":"NuGet.Client","full_name":"dtivel/NuGet.Client","owner":{"login":"dtivel","id":12734758,"avatar_url":"https://avatars.githubusercontent.com/u/12734758?v=3","gravatar_id":"","url":"https://api.github.com/users/dtivel","html_url":"https://github.com/dtivel","followers_url":"https://api.github.com/users/dtivel/followers","following_url":"https://api.github.com/users/dtivel/following{/other_user}","gists_url":"https://api.github.com/users/dtivel/gists{/gist_id}","starred_url":"https://api.github.com/users/dtivel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dtivel/subscriptions","organizations_url":"https://api.github.com/users/dtivel/orgs","repos_url":"https://api.github.com/users/dtivel/repos","events_url":"https://api.github.com/users/dtivel/events{/privacy}","received_events_url":"https://api.github.com/users/dtivel/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dtivel/NuGet.Client","description":"Core client libraries for NuGet Services","fork":true,"url":"https://api.github.com/repos/dtivel/NuGet.Client","forks_url":"https://api.github.com/repos/dtivel/NuGet.Client/forks","keys_url":"https://api.github.com/repos/dtivel/NuGet.Client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dtivel/NuGet.Client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dtivel/NuGet.Client/teams","hooks_url":"https://api.github.com/repos/dtivel/NuGet.Client/hooks","issue_events_url":"https://api.github.com/repos/dtivel/NuGet.Client/issues/events{/number}","events_url":"https://api.github.com/repos/dtivel/NuGet.Client/events","assignees_url":"https://api.github.com/repos/dtivel/NuGet.Client/assignees{/user}","branches_url":"https://api.github.com/repos/dtivel/NuGet.Client/branches{/branch}","tags_url":"https://api.github.com/repos/dtivel/NuGet.Client/tags","blobs_url":"https://api.github.com/repos/dtivel/NuGet.Client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dtivel/NuGet.Client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dtivel/NuGet.Client/git/refs{/sha}","trees_url":"https://api.github.com/repos/dtivel/NuGet.Client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dtivel/NuGet.Client/statuses/{sha}","languages_url":"https://api.github.com/repos/dtivel/NuGet.Client/languages","stargazers_url":"https://api.github.com/repos/dtivel/NuGet.Client/stargazers","contributors_url":"https://api.github.com/repos/dtivel/NuGet.Client/contributors","subscribers_url":"https://api.github.com/repos/dtivel/NuGet.Client/subscribers","subscription_url":"https://api.github.com/repos/dtivel/NuGet.Client/subscription","commits_url":"https://api.github.com/repos/dtivel/NuGet.Client/commits{/sha}","git_commits_url":"https://api.github.com/repos/dtivel/NuGet.Client/git/commits{/sha}","comments_url":"https://api.github.com/repos/dtivel/NuGet.Client/comments{/number}","issue_comment_url":"https://api.github.com/repos/dtivel/NuGet.Client/issues/comments{/number}","contents_url":"https://api.github.com/repos/dtivel/NuGet.Client/contents/{+path}","compare_url":"https://api.github.com/repos/dtivel/NuGet.Client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dtivel/NuGet.Client/merges","archive_url":"https://api.github.com/repos/dtivel/NuGet.Client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dtivel/NuGet.Client/downloads","issues_url":"https://api.github.com/repos/dtivel/NuGet.Client/issues{/number}","pulls_url":"https://api.github.com/repos/dtivel/NuGet.Client/pulls{/number}","milestones_url":"https://api.github.com/repos/dtivel/NuGet.Client/milestones{/number}","notifications_url":"https://api.github.com/repos/dtivel/NuGet.Client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dtivel/NuGet.Client/labels{/name}","releases_url":"https://api.github.com/repos/dtivel/NuGet.Client/releases{/id}","deployments_url":"https://api.github.com/repos/dtivel/NuGet.Client/deployments","created_at":"2016-10-18T18:26:58Z","updated_at":"2016-10-18T18:27:07Z","pushed_at":"2016-11-11T15:31:43Z","git_url":"git://github.com/dtivel/NuGet.Client.git","ssh_url":"git@github.com:dtivel/NuGet.Client.git","clone_url":"https://github.com/dtivel/NuGet.Client.git","svn_url":"https://github.com/dtivel/NuGet.Client","homepage":null,"size":23884,"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":"dev"}},"base":{"label":"NuGet:dev","ref":"dev","sha":"00b3b0f3776b889266b36201383191ffaf71438e","user":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"repo":{"id":19330736,"name":"NuGet.Client","full_name":"NuGet/NuGet.Client","owner":{"login":"NuGet","id":968310,"avatar_url":"https://avatars.githubusercontent.com/u/968310?v=3","gravatar_id":"","url":"https://api.github.com/users/NuGet","html_url":"https://github.com/NuGet","followers_url":"https://api.github.com/users/NuGet/followers","following_url":"https://api.github.com/users/NuGet/following{/other_user}","gists_url":"https://api.github.com/users/NuGet/gists{/gist_id}","starred_url":"https://api.github.com/users/NuGet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NuGet/subscriptions","organizations_url":"https://api.github.com/users/NuGet/orgs","repos_url":"https://api.github.com/users/NuGet/repos","events_url":"https://api.github.com/users/NuGet/events{/privacy}","received_events_url":"https://api.github.com/users/NuGet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NuGet/NuGet.Client","description":"Core client libraries for NuGet Services","fork":false,"url":"https://api.github.com/repos/NuGet/NuGet.Client","forks_url":"https://api.github.com/repos/NuGet/NuGet.Client/forks","keys_url":"https://api.github.com/repos/NuGet/NuGet.Client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NuGet/NuGet.Client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NuGet/NuGet.Client/teams","hooks_url":"https://api.github.com/repos/NuGet/NuGet.Client/hooks","issue_events_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/events{/number}","events_url":"https://api.github.com/repos/NuGet/NuGet.Client/events","assignees_url":"https://api.github.com/repos/NuGet/NuGet.Client/assignees{/user}","branches_url":"https://api.github.com/repos/NuGet/NuGet.Client/branches{/branch}","tags_url":"https://api.github.com/repos/NuGet/NuGet.Client/tags","blobs_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/refs{/sha}","trees_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NuGet/NuGet.Client/statuses/{sha}","languages_url":"https://api.github.com/repos/NuGet/NuGet.Client/languages","stargazers_url":"https://api.github.com/repos/NuGet/NuGet.Client/stargazers","contributors_url":"https://api.github.com/repos/NuGet/NuGet.Client/contributors","subscribers_url":"https://api.github.com/repos/NuGet/NuGet.Client/subscribers","subscription_url":"https://api.github.com/repos/NuGet/NuGet.Client/subscription","commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/commits{/sha}","git_commits_url":"https://api.github.com/repos/NuGet/NuGet.Client/git/commits{/sha}","comments_url":"https://api.github.com/repos/NuGet/NuGet.Client/comments{/number}","issue_comment_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues/comments{/number}","contents_url":"https://api.github.com/repos/NuGet/NuGet.Client/contents/{+path}","compare_url":"https://api.github.com/repos/NuGet/NuGet.Client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NuGet/NuGet.Client/merges","archive_url":"https://api.github.com/repos/NuGet/NuGet.Client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NuGet/NuGet.Client/downloads","issues_url":"https://api.github.com/repos/NuGet/NuGet.Client/issues{/number}","pulls_url":"https://api.github.com/repos/NuGet/NuGet.Client/pulls{/number}","milestones_url":"https://api.github.com/repos/NuGet/NuGet.Client/milestones{/number}","notifications_url":"https://api.github.com/repos/NuGet/NuGet.Client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NuGet/NuGet.Client/labels{/name}","releases_url":"https://api.github.com/repos/NuGet/NuGet.Client/releases{/id}","deployments_url":"https://api.github.com/repos/NuGet/NuGet.Client/deployments","created_at":"2014-04-30T23:46:11Z","updated_at":"2016-11-14T14:18:07Z","pushed_at":"2016-11-12T18:10:17Z","git_url":"git://github.com/NuGet/NuGet.Client.git","ssh_url":"git@github.com:NuGet/NuGet.Client.git","clone_url":"https://github.com/NuGet/NuGet.Client.git","svn_url":"https://github.com/NuGet/NuGet.Client","homepage":null,"size":32271,"stargazers_count":119,"watchers_count":119,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":153,"mirror_url":null,"open_issues_count":19,"forks":153,"open_issues":19,"watchers":119,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014"},"html":{"href":"https://github.com/NuGet/NuGet.Client/pull/1014"},"issue":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/issues/1014"},"comments":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/issues/1014/comments"},"review_comments":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014/comments"},"review_comment":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/pulls/1014/commits"},"statuses":{"href":"https://api.github.com/repos/NuGet/NuGet.Client/statuses/3e77be68818217012163813143c15a2b6d819e82"}}}}
{"actor":{"display_login":"alpaix"}}