Boost .NET Performance with dotTrace Profiling SDK: A Practical Guide

How to Integrate dotTrace Profiling SDK into Your CI Pipeline

Overview

This guide shows a practical, repeatable way to run dotTrace Profiling SDK in CI to collect CPU and memory snapshots, fail builds on regressions, and store artifacts for analysis.

Prerequisites

  • dotTrace Profiling SDK installed on the CI runner or available in the build image.
  • License available for the runner (if required).
  • .NET project with automated tests or benchmark workloads.
  • CI system with scripting (e.g., GitHub Actions, GitLab CI, Azure Pipelines, Jenkins).

High-level steps

  1. Add a profiling script to the repo that:
    • Launches the target process or test runner under dotTrace.
    • Collects snapshots (CPU / memory) and stores them to a known directory.
    • Optionally compares snapshots to a baseline and exits nonzero on regressions.
  2. Install dotTrace runtime and SDK on CI runners (or use a container image that includes it).
  3. Create CI job steps to prepare environment, run the profiling script, upload snapshots as artifacts, and evaluate results.
  4. Optionally set up baseline snapshots and a comparison threshold to fail builds for performance regressions.

Example flow (assumes Windows runner; adapt to Linux/macOS)

  1. CI checkout and restore.
  2. Install dotTrace SDK (download + extract) or ensure it’s present.
  3. Run tests or app under profiler:
    • Use dotTrace command-line (dotTrace.exe) or Profiling API to start/stop profiling.
  4. Save snapshots to ./artifacts/dottrace/.
  5. Compare snapshots to baseline with dotTrace CLI (or use a custom script parsing exported metrics).
  6. Upload artifacts and fail build if regression detected.

Sample script (PowerShell simplified)

powershell

\(dotTrace</span><span> = </span><span class="token" style="color: rgb(163, 21, 21);">"C:\dottrace\dotTrace.exe"</span><span> </span><span></span><span class="token" style="color: rgb(54, 172, 170);">\)target = “dotnet test MyTests.dll –no-build” \(outDir</span><span> = </span><span class="token" style="color: rgb(163, 21, 21);">"</span><span class="token" style="color: rgb(54, 172, 170);">\)PSScriptRoot\artifacts\dottrace” New-Item -ItemType Directory -Path \(outDir</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">-</span><span>Force </span> <span></span><span class="token" style="color: rgb(0, 128, 0); font-style: italic;"># Start profiling, run tests, collect snapshot</span><span> </span><span>& </span><span class="token" style="color: rgb(54, 172, 170);">\)dotTrace run target \(env</span><span class="token" style="color: rgb(163, 21, 21);">:COMSPEC"</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">--</span><span>target-args </span><span class="token" style="color: rgb(163, 21, 21);">"/c </span><span class="token" style="color: rgb(54, 172, 170);">\)target save-to \(outDir</span><span class="token" style="color: rgb(163, 21, 21);">\snapshot1.dtps"</span><span> </span> <span></span><span class="token" style="color: rgb(0, 128, 0); font-style: italic;"># Optionally compare to baseline</span><span> </span><span></span><span class="token" style="color: rgb(54, 172, 170);">\)baseline = \(PSScriptRoot</span><span class="token" style="color: rgb(163, 21, 21);">\baseline\baseline.dtps"</span><span> </span><span></span><span class="token" style="color: rgb(0, 0, 255);">if</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">(</span><span class="token" style="color: rgb(57, 58, 52);">Test-Path</span><span> </span><span class="token" style="color: rgb(54, 172, 170);">\)baseline) { \(result</span><span> = & </span><span class="token" style="color: rgb(54, 172, 170);">\)dotTrace compare baseline \(baseline</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">--</span><span>snapshot </span><span class="token" style="color: rgb(163, 21, 21);">"</span><span class="token" style="color: rgb(54, 172, 170);">\)outDir\snapshot1.dtps” threshold 10 if ($LASTEXITCODE -ne 0) { Write-Error “Performance regression detected”; exit 1 } }

CI job example (GitHub Actions snippet)

yaml

jobs: profile: runs-on: windows-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: ‘8.x’ - name: Install dotTrace SDK run: Invoke-WebRequest -Uri “-zip-url>-OutFile dottrace.zip; Expand-Archive dottrace.zip -DestinationPath C:\dottrace - name: Run profiling run: pwsh ./scripts/run-dottrace.ps1 - name: Upload snapshots uses: actions/upload-artifact@v4 with: name: dottrace-snapshots path: artifacts/dottrace

Best practices

  • Use dedicated profiling runs (not every push) β€” schedule nightly or on release branches.
  • Keep baseline snapshots committed or stored as artifacts for comparisons.
  • Profile representative workloads (integration tests, benchmarks) rather than short unit tests.
  • Automate threshold-based comparisons to catch regressions but avoid flaky failures by tuning thresholds.
  • Collect both CPU and memory snapshots when diagnosing performance issues.
  • Secure license keys and installer artifacts via CI secrets.

Troubleshooting

  • If dotTrace fails to attach, ensure runner has appropriate permissions and required runtime installed.
  • Large snapshots: compress before upload and consider sampling modes to reduce size.
  • If comparisons are noisy, increase comparison threshold or profile multiple runs and use median values.

Deliverables to add to repo

  • scripts/run-dottrace.ps1 (or bash)
  • CI job definition
  • baseline snapshots directory
  • README with instructions and failure thresholds

If you want, I can generate a ready-to-run PowerShell script and a GitHub Actions workflow tailored to your repository layout.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *