Thursday, September 19, 2024

Part 2: How to optimize increase speed of .Net solution build process in Azure Devops Pipeline?

 To improve the time taken by the VSBuild@1 task in an Azure DevOps pipeline for building .NET applications, you can optimize various parameters and configurations similar to the general techniques used for improving build times. Below are specific recommendations for optimizing the VSBuild@1 task:

1. Enable Multi-Processor Builds (Parallel Builds)

You can pass the /m flag to enable multi-core builds, which can significantly reduce build time for solutions with multiple projects.

steps:
- task: VSBuild@1
  inputs:
    solution: '**/*.sln'
    msbuildArgs: '/m'

Explanation:

  • /m enables multi-threaded building, allowing multiple projects to be built concurrently on agents with multiple processors.

2. Use Incremental Builds

Incremental builds can save time by only building projects that have changed since the last build. By default, the VSBuild task cleans the project before building, which can be inefficient. Disable cleaning unless necessary:

steps:
- task: VSBuild@1
  inputs:
    solution: '**/*.sln'
    clean: false

Explanation:

  • clean: false ensures that the build output from previous builds is not deleted, enabling incremental builds where only the projects that have changed are rebuilt.

3. Optimize Build Configuration

Build the solution in Release mode only if necessary (e.g., for production builds). For development or non-critical builds, Debug mode is often faster.

steps:
- task: VSBuild@1
  inputs:
    solution: '**/*.sln'
    configuration: 'Debug'

Explanation:

  • configuration: 'Debug' builds the solution in Debug mode, which generally takes less time than Release mode.

4. Leverage Build Caching

Use caching to prevent repetitive tasks from being executed. Specifically, caching the NuGet packages and intermediate build outputs can significantly reduce the build time.

Cache NuGet Packages:

Use the Cache@2 task to cache your NuGet packages:

steps:
- task: Cache@2
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/*.csproj'
    path: $(NuGetPackageRoot)
    cacheHitVar: NUGET_RESTORED

Explanation:

  • The Cache@2 task saves the downloaded NuGet packages from one pipeline run and reuses them in subsequent runs, reducing the time spent on restoring packages.

Cache Intermediate Build Outputs:

You can also cache build outputs (e.g., compiled libraries) to avoid recompiling them:

steps:
- task: Cache@2
  inputs:
    key: 'build | $(Agent.OS) | $(Build.SourcesDirectory)'
    path: $(Build.BinariesDirectory)
    cacheHitVar: BUILD_CACHE_HIT

5. Use Specific MSBuild Arguments

You can pass additional MSBuild arguments to fine-tune the build process:

  • /p:DeployOnBuild=false prevents deploying during the build, which is useful if you don’t need deployment in your pipeline.

  • /p:RestorePackages=false skips NuGet package restore if it's already handled in a previous step.

  • /p:WarningLevel=1 lowers the verbosity of build warnings, though use this cautiously.

Example:

steps:
- task: VSBuild@1
  inputs:
    solution: '**/*.sln'
    msbuildArgs: '/m /p:DeployOnBuild=false /p:RestorePackages=false'

6. Reduce Verbosity

Reducing the verbosity of logs can slightly speed up the build process by minimizing the amount of data logged:

steps:
- task: VSBuild@1
  inputs:
    solution: '**/*.sln'
    logLevel: 'minimal'

Explanation:

  • logLevel: 'minimal' reduces the amount of output generated during the build, which can improve performance and also make the logs easier to read.

7. Disable Tests During Build (if not needed)

If you are running tests separately in your pipeline, you can disable test execution during the build by using the /p:RunTests=false argument.

steps:
- task: VSBuild@1
  inputs:
    solution: '**/*.sln'
    msbuildArgs: '/p:RunTests=false'

8. Use Hosted Agents with More Resources

If your builds are still taking a long time, consider using agents with more resources (e.g., more CPU and memory). Azure DevOps offers different tiers of hosted agents, and using more powerful agents can reduce build times.

To specify a more powerful hosted agent, use:

pool:
  vmImage: 'windows-latest'  # or 'windows-2022' for better performance

9. Enable NuGet Restore with Parallel Processing

To make NuGet restore faster, use parallel processing:

steps:
- task: NuGetCommand@2
  inputs:
    command: 'restore'
    restoreSolution: '**/*.sln'
    feedsToUse: 'select'
    noCache: false
    disableParallelProcessing: false

Explanation:

  • disableParallelProcessing: false ensures NuGet restore is performed in parallel, which can be faster for solutions with many dependencies.

10. Split Build and Test Phases

If your build process includes running tests, you can separate the build and test phases to avoid unnecessary rebuilds and gain better control over parallelism:

steps:
- task: VSBuild@1
  inputs:
    solution: '**/*.sln'
    msbuildArgs: '/m'
- task: VSTest@2
  inputs:
    testSelector: 'testAssemblies'
    testAssemblyVer2: |
      **\$(BuildConfiguration)\*.Test.dll
    searchFolder: '$(Build.SourcesDirectory)'

This helps by only running tests after the build completes and can allow parallel execution of tests.

11. Use Self-Hosted Agents

If your builds are large and resource-intensive, you can use self-hosted agents with better hardware configurations (e.g., more CPU and RAM). You can configure self-hosted agents to avoid the time it takes for the default Azure DevOps hosted agents to spin up and download all required tools.

Conclusion:

To summarize, improving the time for the VSBuild@1 task in Azure DevOps involves using:

  • Parallel builds with /m.

  • Incremental builds by disabling the clean option.

  • Build caching for NuGet and build outputs.

  • Specific MSBuild arguments like /p:DeployOnBuild=false and /p:RestorePackages=false.

  • Lower log verbosity and splitting build and test tasks.

By fine-tuning the pipeline with these optimizations, you can reduce the build time for your .NET solution.

No comments :