{"id":232146,"date":"2021-04-07T13:00:37","date_gmt":"2021-04-07T20:00:37","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/visualstudio\/?p=232146"},"modified":"2021-04-07T14:14:45","modified_gmt":"2021-04-07T21:14:45","slug":"performance-improvements-in-nuget","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/visualstudio\/performance-improvements-in-nuget\/","title":{"rendered":"Performance Improvements in NuGet"},"content":{"rendered":"<p>With each new release of Visual Studio comes a plethora of performance improvements when restoring NuGet packages, managing project dependencies, and browsing for the next great package to include in your solution.<\/p>\n<h2>NuGet restore<\/h2>\n<p>When you think about NuGet, you probably think about restoring packages in your .NET projects. We have made significant performance optimizations between Visual Studio 16.4 and 16.9 to restore scenarios.<\/p>\n<h3>What is NuGet restore?<\/h3>\n<p>At its core, restore ensures that all your dependencies, declared in either the project file or packages.config, are available prior to build. This means NuGet ensures that the required packages are available in the global packages folder or the local packages cache. For PackageReference projects, this may involve resolving the dependency graph in addition.<\/p>\n<h3>What are the different types of NuGet restores?<\/h3>\n<p>Within NuGet, depending on the outcome, we talk about two types of restores, regular and no-op.<\/p>\n<ul>\n<li><strong>Regular restore<\/strong> \u2013 Any restore that involves a package download, package installation, or dependency graph resolution.<\/li>\n<li><strong>No-op restore<\/strong> \u2013 A no-operation restore, no-op for short, that determines your project state is fully up to date. In most cases, you are running a no-op restore.<\/li>\n<\/ul>\n<h3>Improvements to NuGet restore<\/h3>\n<p>Here is how we have improved NuGet no-op restore performance over the last 5 releases of Visual Studio for large solutions (50+ projects) using PackageReference. These charts use percentiles to best demonstrate how restore ranks for the large solution population in terms such as p95, p75, and p50. <strong>In other words, the higher the percentile, the larger number of projects in a solution.<\/strong><strong>\u00a0<\/strong><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestorep95.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-232150\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestorep95.png\" alt=\"Image nooprestorep95\" width=\"1417\" height=\"618\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestorep95.png 1417w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestorep95-300x131.png 300w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestorep95-1024x447.png 1024w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestorep95-768x335.png 768w\" sizes=\"(max-width: 1417px) 100vw, 1417px\" \/><\/a><\/p>\n<p>These improvements are not only for large solutions! They also have an impact on small to medium solutions (1-50 projects) too.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestore.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-232149\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestore.png\" alt=\"Image nooprestore\" width=\"812\" height=\"651\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestore.png 812w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestore-300x241.png 300w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nooprestore-768x616.png 768w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/a><\/p>\n<p>Additionally, we improved the performance of restore for Visual Studio solution load by grouping restores more efficiently. This leads to a drastic change in solution load performance for large solutions such as <a href=\"https:\/\/github.com\/OrchardCMS\/OrchardCore\">OrchardCore<\/a>(over 150 projects).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/solutionloadrestore.png\"><img decoding=\"async\" class=\"aligncenter wp-image-232152\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/solutionloadrestore.png\" alt=\"Image solutionloadrestore\" width=\"800\" height=\"441\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/solutionloadrestore.png 421w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/solutionloadrestore-300x165.png 300w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>Finally, we have improved the performance of continuous integration scenarios such as NuGet CLI, dotnet CLI, and MSBuild where no packages have been downloaded. Over the last 5 releases of the NuGet Client tooling, restore has improved over 40% for large solutions (50+ projects).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nugetclientrestore.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-232151\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nugetclientrestore.png\" alt=\"Image nugetclientrestore\" width=\"1324\" height=\"774\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nugetclientrestore.png 1324w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nugetclientrestore-300x175.png 300w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nugetclientrestore-1024x599.png 1024w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/nugetclientrestore-768x449.png 768w\" sizes=\"(max-width: 1324px) 100vw, 1324px\" \/><\/a><\/p>\n<h3>What impacts NuGet restore performance?<\/h3>\n<p>As your solution scales with more projects, you may notice that your NuGet restore takes a bit longer. We will also cover other factors that can affect the performance of NuGet restore.<\/p>\n<h4>Solution Size<\/h4>\n<p>The larger your solution is, the longer your NuGet restore may take. This is because as your solution grows, so does your dependency graphs. Your project dependency graph is a graph that represents the dependencies of packages towards each other. Depending on your package management format, you may have a flat dependency graph(packages.config) or a transitive dependency graph (PackageReference).<\/p>\n<p>The larger your package dependency graphs become, the more complex the process of correctly evaluating and resolving all your dependencies becomes.<\/p>\n<h4>Restore Method<\/h4>\n<p>You may not even know how the restore happens but depending on how NuGet restores your packages, it can have an impact to the overall performance. For the sake of classifying restore methods, we will refer to two primary categories:<\/p>\n<ol>\n<li><strong>Implicit<\/strong> \u2013 Using any tool that does a NuGet restore on your behalf.<\/li>\n<li><strong>Explicit<\/strong> \u2013 Using any tool that you manually invoke a NuGet restore with.<\/li>\n<\/ol>\n<p>For example, when you are using tools like Visual Studio or dotnet build, you are using NuGet implicitly when loading your solutions or building your projects.<\/p>\n<h4>Package Sources<\/h4>\n<p>There are a few different types of package sources that NuGet uses to restore your packages with. The two main categories are <strong>file-based sources<\/strong> and <strong>http-based sources<\/strong>. <a href=\"https:\/\/docs.microsoft.com\/en-us\/nuget\/hosting-packages\/local-feeds\">Hierarchical package sources\n<\/a>are faster than flat package sources. The performance among http sources can vary as well. NuGet\u2019s <a href=\"https:\/\/docs.microsoft.com\/en-us\/nuget\/concepts\/package-installation-process\">package installation process<\/a> prefers the most responsive sources. The number of sources may affect the performance because NuGet now must check more sources.<\/p>\n<h4>Package Management Format<\/h4>\n<p>By default, PackageReference is used for .NET Core projects. .NET Framework projects support PackageReference, but currently default to packages.config. <a href=\"https:\/\/docs.microsoft.com\/nuget\/consume-packages\/migrate-packages-config-to-package-reference\">It is recommended that you migrate to PackageReference if you can.<\/a> There are many benefits to using PackageReference such as managing all your dependencies in one place, but most importantly, you get performance improvements due to the nature of how packages are maintained in a global packages folder for performant file operations.<\/p>\n<h4>MSBuild Static Graph Evaluation<\/h4>\n<p>You can restore your project with a concept known as a <a href=\"https:\/\/github.com\/dotnet\/msbuild\/blob\/master\/documentation\/specs\/static-graph.md\">MSBuild static graph evaluation<\/a>, in which NuGet will leverage the MSBuild static graph to evaluate your project graph for restore. If you have a large solution, this may significantly improve your restore performance.<\/p>\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/nuget\/reference\/msbuild-targets#restoring-with-msbuild-static-graph-evaluation\">Learn how you can restore with MSBuild static graph evaluation.<\/a><\/p>\n<h3>How do I improve NuGet restore performance?<\/h3>\n<p>We talked about a few separate ways you can improve NuGet restore performance. Let us summarize:<\/p>\n<ul>\n<li>Ensure you do not have excess package sources in your repositories.<\/li>\n<li>Reduce the number of projects per solution or <a href=\"https:\/\/docs.microsoft.com\/visualstudio\/ide\/filtered-solutions\">filter solutions in Visual Studio<\/a>.<\/li>\n<li>Use the latest tooling that supports NuGet implicitly such as <a href=\"https:\/\/docs.microsoft.com\/nuget\/install-nuget-client-tools\">Visual Studio, MSBuild, and dotnet CLI<\/a>.<\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/nuget\/consume-packages\/migrate-packages-config-to-package-reference\">Migrate to PackageReference<\/a> if your project supports it.<\/li>\n<li>Try <a href=\"https:\/\/docs.microsoft.com\/en-us\/nuget\/reference\/msbuild-targets#restoring-with-msbuild-static-graph-evaluation\">MSBuild static graph evaluation<\/a> within your projects.<\/li>\n<\/ul>\n<h2>Managing Dependencies in Visual Studio<\/h2>\n<p>We have heard from you that one of your biggest pain points is the performance of managing your dependencies as your project gets larger such as switching between tabs, installing new packages, updating outdated packages, and uninstalling unneeded packages.<\/p>\n<p>For the following performance improvements, we benchmarked against the <a href=\"https:\/\/github.com\/OrchardCMS\/OrchardCore\">OrchardCore<\/a> project which contains over 150 projects, and the operations are done on a solution-level.<\/p>\n<ul>\n<li>16.7 \u2013 We made it instantaneous to switch between the <strong>installed and update<\/strong> tabs.<\/li>\n<li>16.8 \u2013 We improved the performance of <strong>updating packages (upgrading\/downgrading)<\/strong> to up to 14x faster.<\/li>\n<li>16.9 \u2013 We improved the performance of <strong>uninstalling packages<\/strong> to be up to 5x faster.<\/li>\n<li>16.10 (Upcoming) \u2013 We improved the performance of <strong>installing packages<\/strong> to be up to 7x faster.<\/li>\n<\/ul>\n<p><div style=\"width: 1920px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-232146-1\" width=\"1920\" height=\"1080\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/installperf.mp4?_=1\" \/><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/installperf.mp4\">https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/installperf.mp4<\/a><\/video><\/div><\/p>\n<p>Try updating to a recent version of Visual Studio and let us know your feedback on these improvements!<\/p>\n<h2>Browsing for Packages in Visual Studio<\/h2>\n<p>We have also heard that browsing for packages in Visual Studio can be an unreliable experience. One major improvement in Visual Studio 16.9 that we have made is making the loading of package details almost instantaneous.<\/p>\n<p><div style=\"width: 1920px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-232146-2\" width=\"1920\" height=\"1080\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/browsecache.mp4?_=2\" \/><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/browsecache.mp4\">https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2021\/04\/browsecache.mp4<\/a><\/video><\/div><\/p>\n<p>We hope that you enjoy a more responsive experience and keep providing us your feedback on how we can improve your browsing experience!<\/p>\n<h2>Summary<\/h2>\n<p>You learned a bit about the performance improvements in NuGet since Visual Studio 16.4. These of improving performance in NuGet restore, managing dependencies, and browsing for packages could not have been possible without your feedback and the NuGet team. Thank you for all your help and we are excited to bring you better package management experiences in future releases of Visual Studio. Update to the latest version of Visual Studio and let us know your thoughts in the comments below!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With each new release of Visual Studio comes a plethora of performance improvements when restoring NuGet packages, managing project dependencies, and browsing for the next great package to include in your solution.<\/p>\n","protected":false},"author":51887,"featured_media":232150,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[155],"tags":[298,6806,6808,6804,6805,53,6807],"class_list":["post-232146","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-studio","tag-nuget","tag-nuget-packages","tag-nuget-performance","tag-nuget-restore","tag-package-management","tag-performance","tag-solution-load-performance"],"acf":[],"blog_post_summary":"<p>With each new release of Visual Studio comes a plethora of performance improvements when restoring NuGet packages, managing project dependencies, and browsing for the next great package to include in your solution.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/232146","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/users\/51887"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/comments?post=232146"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/232146\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media\/232150"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media?parent=232146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/categories?post=232146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/tags?post=232146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}