Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Visual studio build path for Ram disk

Currently I have Visual Studio 17 V 15.4.2

Is it possible to set different build path for projects? for example instead of

C:\Users\[UserName]\source\repos\[MyProject]\[bin|obj]

move it on

M:\Users\[UserName]\source\repos\[MyProject]\[bin|obj]

note that project it self is inside C but temporary files are moved somewhere else. I have drive M which is a 16GB ram disk.

Benefits of using RAM disk:(reasons that is tempting me to do this)

  • faster build times (no real IO)

  • SSD doesn't wear out with repetitive rebuilds.

  • projects are inherently cleaned up (which brings following benefits)

  • share faster, your projects are not filled with unnecessary files so that you can easily share folders with others. (code size is usually less than 1MB but build objects can go beyond 1GB)

  • fast backups, for same reason your project folders always remain cleaned up and you can backup project much faster. (especially when you have many projects, eg. you would only backup 100MB istead of 10GB)

  • less chance of creating locked files. (which cause build desync, errors etc) in that case formatting ramdisk is easier than mucking with VS settings or restarting it.

Drawbacks:

  • you need much more RAM, in my case I have 32GB which I can spare 16GB for it.

  • if you reset VS or computer you loose compiled objects and you have to rebuild (once)

but benefits of using RAM disk clearly overweight its drawbacks.

Ok, now that I convinced you reasonably why I want this give me paths :)

like image 245
M.kazem Akhgary Avatar asked Nov 02 '17 09:11

M.kazem Akhgary


2 Answers

It is possible to change the project files (at least for .NET applications) which bin- and obj-path should be used. But you need to change this manually on every project. And if you check in these changes it might cause problems for someone else that is trying to build.

Instead you change the bin- and obj-directories to be a symbolic link to a ramdisk. This will not affect your project and solution files (except that git might treat this links as file so you might want to add these to your .gitignore).

I’ve created two Powershell scripts to manage this. I’m running these in the same directory as the solution file. Be aware that the bin- and obj directories will be removed when you are running these.

This script will remove bin- and obj-folders in all directories where these is a csproj-file and replace them with symbolic links:

$ramDiskDrive = "R:"

# Find all project files...
$projectFiles = Get-ChildItem -Filter *.csproj -Recurse 
# Get project directories
$projectDirectories = $projectFiles | ForEach-Object { $_.DirectoryName } | Get-Unique


# Create a bin-directory on the RAM-drive
$projectDirectories | ForEach-Object { New-Item -ItemType Directory -Force -Path "$ramDiskDrive$($_.Substring(2))\bin" } 

# Remove existing bin-directories
$projectDirectories | ForEach-Object { Remove-Item "$($_)\bin" -Force -Recurse }

# Link bin-directories to ramdisk
$projectDirectories | ForEach-Object { cmd /c mklink /D "$($_)\bin" "$ramDiskDrive$($_.Substring(2))\bin" }


# Create a obj-directory on the RAM-drive
$projectDirectories | ForEach-Object { New-Item -ItemType Directory -Force -Path "$ramDiskDrive$($_.Substring(2))\obj" } 

# Remove existing obj-directories
$projectDirectories | ForEach-Object { Remove-Item "$($_)\obj" -Force -Recurse }

# Link obj-directories to ramdisk
$projectDirectories | ForEach-Object { cmd /c mklink /D "$($_)\obj" "$ramDiskDrive$($_.Substring(2))\obj" }

This script will remove the symbolic links:

# Find all project files...
$projectFiles = Get-ChildItem -Filter *.csproj -Recurse 
# Get project directories
$projectDirectories = $projectFiles | ForEach-Object { $_.DirectoryName } | Get-Unique


# Unlink bin-directories to ramdisk
$projectDirectories | ForEach-Object { cmd /c rmdir "$($_)\bin"   }

# Unlink obj-directories to ramdisk
$projectDirectories | ForEach-Object { cmd /c rmdir "$($_)\obj"   }

If you are running the same script twice you will get error messages, but these could be ignored.

All this said, from my experience there is no major difference to use a RAM-disk instead of an SSD-drive. It is faster but not that much as you might expect.

like image 179
PEK Avatar answered Sep 29 '22 17:09

PEK


Fully working solution for "obj" directory

  1. Create EnviromentVariable BUILD_RAMDRIVE which points to your ramdrive.
  2. Create "Directory.Build.props" file inside your solution dir with this content:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <BuildRamdrive>$([System.Environment]::GetEnvironmentVariable("BUILD_RAMDRIVE",System.EnvironmentVariableTarget.Machine))</BuildRamdrive>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(BuildRamdrive)' != '' AND '$(MSBuildProjectFile)' != ''">
        <BaseIntermediateOutputPath>$(BuildRamdrive)\Projects\$(SolutionName)\$(MSBuildProjectFile)\obj\</BaseIntermediateOutputPath>
        <IntermediateOutputPath>$(BuildRamdrive)\Projects\$(SolutionName)\$(MSBuildProjectFile)\obj\$(Configuration)\</IntermediateOutputPath>
        <MSBuildProjectExtensionsPath>$(BuildRamdrive)\Projects\$(SolutionName)\$(MSBuildProjectFile)\obj\</MSBuildProjectExtensionsPath>
    </PropertyGroup>
</Project>

Thats all :-)

This MSBuild scripts takes BUILD_RAMDRIVE environment variable from your computer. Then redirect all obj files of all projects inside this solution to $BUILD_RAMDRIVE\Projects\$(SolutionName)\$(MSBuildProjectFile)\obj\ directory

If your computer has no BUILD_RAMDRIVE environment variable it will do nothing.

like image 44
Alexei Shcherbakov Avatar answered Sep 29 '22 16:09

Alexei Shcherbakov