{"id":507,"date":"2023-05-24T10:00:14","date_gmt":"2023-05-24T17:00:14","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/?p=507"},"modified":"2024-05-14T13:49:13","modified_gmt":"2024-05-14T20:49:13","slug":"dev-drive-and-copy-on-write-for-developer-performance","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/dev-drive-and-copy-on-write-for-developer-performance\/","title":{"rendered":"Dev Drive and Copy-on-Write for Developer Performance"},"content":{"rendered":"<p>(Edited Apr 4, 2024 with release info.)<\/p>\n<p>Later posts in series: <a href=\"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/dev-drive-is-now-available\/\">Dev Drive has shipped!<\/a>, <a href=\"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/copy-on-write-in-win32-api-early-access\/\">CoW-in-Win32 early access<\/a>, <a href=\"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/copy-on-write-performance-and-debugging\/\">Copy-on-Write performance and debugging<\/a><\/p>\n<p style=\"font-weight: 400;\">\n  At <a href=\"https:\/\/build.microsoft.com\/\">Microsoft Build<\/a> 2023 the Windows team announced Dev Drive, a new evolution of the Windows ReFS filesystem retuned for developer workloads like Git and builds. This new functionality will ship later this year in the Windows 11 23H2 refresh and is available now for early testing via the Windows Insider program.\n<\/p>\n<p style=\"font-weight: 400;\">\n  Microsoft\u2019s One Engineering System team has been testing Dev Drive on internal Windows builds for several months. Building a large internal codebase with more than 500 C# projects, we\u2019re seeing <strong>14%<\/strong> faster full builds moving from NTFS on Windows 11 22H2 to Dev Drive.\n<\/p>\n<p style=\"font-weight: 400;\">\n  There\u2019s even more great news! With the <a href=\"https:\/\/github.com\/microsoft\/MSBuildSdks\/tree\/main\/src\/CopyOnWrite\">Microsoft.Build.CopyOnWrite<\/a> package added to the repo we\u2019re getting an additional 14 percentage point performance improvement \u2013 a total of <strong>28% faster<\/strong> \u2013 just by adding a Dev Drive volume and moving package caches and code to it.\n<\/p>\n<p style=\"font-weight: 400;\">\n  (Methodology note: In all cases the repo directory was excluded from Defender real-time antivirus scanning, a commonly deployed configuration. Testing was not done with the new performance mode of Defender antivirus also announced at Build.)\n<\/p>\n<p style=\"font-weight: 400;\">\n  NTFS also benefits from performance updates in the upcoming Windows release. In early testing we see a 9% improvement versus 22H2 when building with the same repo.\n<\/p>\n<h2>Copy-on-Write on ReFS and Dev Drive<\/h2>\n<p style=\"font-weight: 400;\">\n  Copy-on-write (CoW) linking, also known as <a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/fileio\/block-cloning\">block cloning<\/a> in the Windows API documentation, avoids fully copying a file by creating a metadata reference to the original data on-disk. CoW links are like hardlinks but are safe to write to, as the filesystem lazily copies the original data into the link as needed when opened for append or random-access write. With a CoW link you save disk space and time since the link consists of a small amount of metadata and they <a href=\"https:\/\/github.com\/microsoft\/CopyOnWrite#performance-comparisons\">write fast<\/a>.\n<\/p>\n<p style=\"font-weight: 400;\">\n  CoW linking is available on Windows only in the ReFS filesystem; it\u2019s also available in iOS and Linux. Dev Drive is a special \u201ctrusted\u201d mode for ReFS. We maintain a <a href=\"https:\/\/github.com\/microsoft\/CopyOnWrite\">public repo<\/a> and <a href=\"https:\/\/www.nuget.org\/packages\/CopyOnWrite\">NuGet package<\/a> for CoW for .NET.\n<\/p>\n<p style=\"font-weight: 400;\">\n  CoW links, instead of file copies, are an excellent match for any build or tool that:\n<\/p>\n<ul>\n<li>Makes explicit file copies to create image layouts, such as for microservice deployments.<\/li>\n<li>Uses MSBuild or dotnet for C# builds, as the Resolve Assembly References build task copies .NET assemblies from package directories and parent projects into each new output directory.<\/li>\n<li>Uses MSBuild <span style=\"font-family: 'courier new', courier, monospace;\"><content><\/content><\/span> and other items where MSBuild performs a copy recursively in each dependent project. (See Appendix B for ways to change this behavior.)<\/li>\n<li>Uses caching build engines and accelerators, such as <a href=\"https:\/\/github.com\/microsoft\/BuildXL\">Microsoft Build Accelerator<\/a>, that copy files from a local cache directory into the filesystem when a cache hit is processed.<\/li>\n<\/ul>\n<h2>Best Practices for CoW<\/h2>\n<p style=\"font-weight: 400;\">\n  All files to be CoW linked must reside within the same Dev Drive volume. This should include package caches and any other sources of files copied by the build engine or tools. Instructions for changing your machine\u2019s environment to move package caches are detailed in Appendix A below.\n<\/p>\n<h2>Future of Dev Drive and CoW<\/h2>\n<p style=\"font-weight: 400;\">\n  Dev Drive and all related performance improvements will also be available in the next major version of Windows Server after Server 2022. Internally, we are experimenting with automatic Dev Drive and package cache setup for <a href=\"https:\/\/azure.microsoft.com\/en-us\/products\/dev-box\/\">Microsoft Dev Box<\/a> images for later public rollout. We\u2019ll also add Dev Drive to our internal CloudBuild distributed build system for faster builds and better machine utilization. After Dev Drive is released as part of the regular Windows refreshes we\u2019ll see Dev Drive rolled out to build and release pipelines in Azure Pipelines and GitHub Actions to make it easier to benefit from performance and CoW optimizations. Also see the <a href=\"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/copy-on-write-in-win32-api-early-access\/\">later post<\/a> that discusses CoW built into the Windows copy API.\n<\/p>\n<p style=\"font-weight: 400;\">\n  Dev Drive is one of the most exciting build performance wins I\u2019ve seen in a long time. I\u2019m looking forward to Dev Drive appearing in the main Windows release channel later this year. <a href=\"https:\/\/aka.ms\/devdrive\">Give it a try<\/a> and see if you agree!\n<\/p>\n<p style=\"font-weight: 400;\">\n  More links:\n<\/p>\n<ul>\n<li><a href=\"https:\/\/aka.ms\/devdriveblog\">Windows team blog post<\/a> on Dev Drive.<\/li>\n<li><a href=\"https:\/\/aka.ms\/vsdevdrive\">Visual Studio team blog post<\/a> on Dev Drive and developer tools.<\/li>\n<\/ul>\n<h2>Appendix A: How to move package caches<\/h2>\n<h3>NuGet<\/h3>\n<p style=\"font-weight: 400;\">\n  The NuGet global packages folder is used by dotnet, MSBuild, and Visual Studio. Create a NuGet root directory in your CoW filesystem, then set a global environment variable <span style=\"font-family: 'courier new', courier, monospace;\">NUGET_PACKAGES<\/span> to that path, e.g. <span style=\"font-family: 'courier new', courier, monospace;\">setx \/M NUGET_PACKAGES D:\\packages\\nuget<\/span>. If you have already installed Visual Studio on your machine, move the contents of <span style=\"font-family: 'courier new', courier, monospace;\">%USERPROFILE%\\.nuget\\packages<\/span> to this directory. <a href=\"https:\/\/learn.microsoft.com\/en-us\/nuget\/consume-packages\/managing-the-global-packages-and-cache-folders\">NuGet documentation<\/a>.\n<\/p>\n<h3>NPM (NodeJS)<\/h3>\n<p style=\"font-weight: 400;\">\n  Create an NPM cache directory in your CoW filesystem, then set a global environment variable <span style=\"font-family: 'courier new', courier, monospace;\">npm_config_cache<\/span> to that path, e.g. <span style=\"font-family: 'courier new', courier, monospace;\">setx \/M npm_config_cache D:\\packages\\npm<\/span>. If you have already installed NodeJS on your machine, move the contents of <span style=\"font-family: 'courier new', courier, monospace;\">%AppData%\\npm-cache<\/span> to this directory. NPM <a href=\"https:\/\/docs.npmjs.com\/cli\/v6\/commands\/npm-cache\">cache<\/a>, <a href=\"https:\/\/docs.npmjs.com\/cli\/v9\/using-npm\/config#cache\">config<\/a> documentation.\n<\/p>\n<h3>Yarn (NodeJS)<\/h3>\n<p style=\"font-weight: 400;\">\n  Create an NPM cache directory in your CoW filesystem, then set a global environment variable <span style=\"font-family: 'courier new', courier, monospace;\">YARN_CACHE_FOLDER<\/span> to that path, e.g. <span style=\"font-family: 'courier new', courier, monospace;\">setx \/M YARN_CACHE_FOLDER D:\\packages\\npm<\/span>. <a href=\"https:\/\/classic.yarnpkg.com\/lang\/en\/docs\/cli\/cache\/\">Yarn documentation<\/a>.\n<\/p>\n<h3>vcpkg<\/h3>\n<p style=\"font-weight: 400;\">\n  Create a vcpkg cache directory in your CoW filesystem, then set a global environment variable <span style=\"font-family: 'courier new', courier, monospace;\">VCPKG_DEFAULT_BINARY_CACHE<\/span> to that path, e.g. <span style=\"font-family: 'courier new', courier, monospace;\">setx \/M VCPKG_DEFAULT_BINARY_CACHE D:\\packages\\vcpkg<\/span>. If you have already installed packages, move the contents of <span style=\"font-family: 'courier new', courier, monospace;\">%LOCALAPPDATA%\\vcpkg\\archives<\/span> or <span style=\"font-family: 'courier new', courier, monospace;\">%APPDATA%\\vcpkg\\archives<\/span> to this directory. <a href=\"https:\/\/learn.microsoft.com\/en-us\/vcpkg\/users\/binarycaching\">vcpkg documentation<\/a>.\n<\/p>\n<h3>Pip (Python)<\/h3>\n<p style=\"font-weight: 400;\">\n  Create a Pip cache directory in your CoW filesystem, then set a global environment variable <span style=\"font-family: 'courier new', courier, monospace;\">PIP_CACHE_DIR<\/span> to that path, e.g.<span style=\"font-family: 'courier new', courier, monospace;\"> setx \/M PIP_CACHE_DIR D:\\packages\\pip<\/span>. If you have already restored Pip packages and Wheels on your machine, move the contents of <span style=\"font-family: 'courier new', courier, monospace;\">%LocalAppData%\\pip\\Cache<\/span> to this directory. Pip <a href=\"https:\/\/pip.pypa.io\/en\/stable\/topics\/caching\/\">cache<\/a> documentation, <a href=\"https:\/\/stackoverflow.com\/questions\/64180511\/pip-change-directory-of-pip-cache-on-linux\">StackOverflow question<\/a>.\n<\/p>\n<h3>Cargo (Rust)<\/h3>\n<p style=\"font-weight: 400;\">\n  Create a Cargo cache directory in your CoW filesystem, then set a global environment variable CARGO_HOME to that path, e.g. <span style=\"font-family: 'courier new', courier, monospace;\">setx \/M CARGO_HOME D:\\packages\\cargo<\/span>. If you have already restored Cargo packages on your machine, move the contents of <span style=\"font-family: 'courier new', courier, monospace;\">%USERPROFILE%\\.cargo<\/span> to this directory. <a href=\"https:\/\/doc.rust-lang.org\/cargo\/reference\/environment-variables.html\">Cargo documentation<\/a>.\n<\/p>\n<h3>Maven (Java)<\/h3>\n<p style=\"font-weight: 400;\">\n  Create a Maven cache directory in your CoW filesystem, then set a global environment variable <span style=\"font-family: 'courier new', courier, monospace;\">MAVEN_OPTS<\/span> to add a configuration setting to that path, e.g. <span style=\"font-family: 'courier new', courier, monospace;\">setx \/M MAVEN_OPTS &#8220;-Dmaven.repo.local=D:\\packages\\maven %MAVEN_OPTS%&#8221;<\/span>. Move the contents of %USERPROFILE%\\.m2 to this directory. <a href=\"https:\/\/stackoverflow.com\/questions\/16649420\/how-to-specify-an-alternate-location-for-the-m2-folder-or-settings-xml-permanen\">StackOverflow question<\/a>, <a href=\"https:\/\/maven.apache.org\/settings.html\">Maven documentation<\/a>.\n<\/p>\n<h2>Appendix B: How to disable default file copying in MSBuild<\/h2>\n<p style=\"font-weight: 400;\">\n  In MSBuild 17 and higher the default for <span style=\"font-family: 'courier new', courier, monospace;\"><content><\/content><\/span> and other file reference items is to copy them to dependent projects. To restore older behavior, or to otherwise optimize I\/O in your build, set this in your Directory.Build.props:\n<\/p>\n<pre><code class=\"xml\">&lt;msbuildcopycontenttransitively&gt;false&lt;\/msbuildcopycontenttransitively&gt;\n<\/code><\/pre>\n<p style=\"font-weight: 400;\">\n  This will stop transitive copying globally. You will need to fix up copying for any individual projects that are broken by the global change. Detecting breakage may not be a matter of a build break, but might be a unit test, integration test, or deployment break instead. To restore copies for these cases:\n<\/p>\n<ul>\n<li>Individual projects that need copies from parents can set the property back to true to copy all files from parent projects, or<\/li>\n<li>Add individual <span style=\"font-family: 'courier new', courier, monospace;\">Content<\/span> items as needed, or<\/li>\n<li>Add <span style=\"font-family: 'courier new', courier, monospace;\">Copy<\/span> task calls in a custom target.<\/li>\n<\/ul>\n<p style=\"font-weight: 400;\">\n","protected":false},"excerpt":{"rendered":"<p>At Microsoft Build 2023 the Windows team announced Dev Drive, a new evolution of the Windows ReFS filesystem retuned for developer workloads like Git and builds. This new functionality will ship later this year in the Windows 11 23H2 refresh and is available now for early testing via the Windows Insider program.<\/p>\n","protected":false},"author":119305,"featured_media":725,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[37],"class_list":["post-507","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering-at-microsoft","tag-performance"],"acf":[],"blog_post_summary":"<p>At Microsoft Build 2023 the Windows team announced Dev Drive, a new evolution of the Windows ReFS filesystem retuned for developer workloads like Git and builds. This new functionality will ship later this year in the Windows 11 23H2 refresh and is available now for early testing via the Windows Insider program.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/posts\/507","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/users\/119305"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/comments?post=507"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/posts\/507\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/media\/725"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/media?parent=507"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/categories?post=507"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/engineering-at-microsoft\/wp-json\/wp\/v2\/tags?post=507"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}