build-parallelism

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

MSBuild Parallelism Model

MSBuild并行构建模型

  • /maxcpucount
    (or
    -m
    ): number of worker nodes (processes)
  • Default: 1 node (sequential!). Always use
    -m
    for parallel builds
  • Recommended:
    -m
    without a number = use all logical processors
  • Each node builds one project at a time
  • Projects are scheduled based on dependency graph
  • /maxcpucount
    (或
    -m
    ):工作节点(进程)数量
  • 默认值:1个节点(即串行构建!)。并行构建时务必使用
    -m
    参数
  • 推荐用法:不带数字的
    -m
    = 使用所有逻辑处理器
  • 每个节点一次仅构建一个项目
  • 项目基于依赖图进行调度

Project Dependency Graph

项目依赖图

  • MSBuild builds projects in dependency order (topological sort)
  • Critical path: longest chain of dependent projects determines minimum build time
  • Bottleneck: if project A depends on B, C, D and B takes 60s while C and D take 5s, B is the bottleneck
  • Diagnosis: replay binlog to diagnostic log with
    performancesummary
    and check Project Performance Summary — shows per-project time; grep for
    node.*assigned
    to check scheduling
  • Wide graphs (many independent projects) parallelize well; deep graphs (long chains) don't
  • MSBuild按照依赖顺序构建项目(拓扑排序)
  • 关键路径:最长的依赖项目链决定了最短构建时间
  • 瓶颈:如果项目A依赖于B、C、D,且B需要60秒而C和D仅需5秒,那么B就是瓶颈
  • 诊断方法:使用
    performancesummary
    参数重放binlog生成诊断日志,查看“项目性能摘要”——其中显示每个项目的构建时间;通过搜索
    node.*assigned
    来检查调度情况
  • 宽依赖图(大量独立项目)的并行化效果好;深依赖图(长依赖链)的并行化效果差

Graph Build Mode (
/graph
)

图构建模式(
/graph

  • dotnet build /graph
    or
    msbuild /graph
  • What it changes: MSBuild constructs the full project dependency graph BEFORE building
  • Benefits: better scheduling, avoids redundant evaluations, enables isolated builds
  • Limitations: all projects must use
    <ProjectReference>
    (no programmatic MSBuild task references)
  • When to use: large solutions with many projects, CI builds
  • When NOT to use: projects that dynamically discover references at build time
  • 命令:
    dotnet build /graph
    msbuild /graph
  • 变更点:MSBuild会在构建前先构建完整的项目依赖图
  • 优势:调度更合理,避免重复评估,支持隔离构建
  • 限制:所有项目必须使用
    <ProjectReference>
    (不支持程序化的MSBuild任务引用)
  • 适用场景:包含大量项目的大型解决方案、CI构建
  • 不适用场景:在构建时动态发现引用的项目

Optimizing Project References

优化项目引用

  • Reduce unnecessary
    <ProjectReference>
    — each adds to the dependency chain
  • Use
    <ProjectReference ... SkipGetTargetFrameworkProperties="true">
    to avoid extra evaluations
  • <ProjectReference ... ReferenceOutputAssembly="false">
    for build-order-only dependencies
  • Consider if a ProjectReference should be a PackageReference instead (pre-built NuGet)
  • Use
    solution filters
    (
    .slnf
    ) to build subsets of the solution
  • 减少不必要的
    <ProjectReference>
    ——每个引用都会增加依赖链长度
  • 使用
    <ProjectReference ... SkipGetTargetFrameworkProperties="true">
    来避免额外评估
  • 对于仅需保证构建顺序的依赖,使用
    <ProjectReference ... ReferenceOutputAssembly="false">
  • 考虑将ProjectReference替换为PackageReference(预构建的NuGet包)
  • 使用解决方案筛选器(
    .slnf
    )来构建解决方案的子集

BuildInParallel

BuildInParallel属性

  • <MSBuild Projects="@(ProjectsToBuild)" BuildInParallel="true" />
    in custom targets
  • Without
    BuildInParallel="true"
    , MSBuild task batches projects sequentially
  • Ensure
    /maxcpucount
    > 1 for this to have effect
  • 在自定义目标中使用
    <MSBuild Projects="@(ProjectsToBuild)" BuildInParallel="true" />
  • 如果不设置
    BuildInParallel="true"
    ,MSBuild任务会按顺序批处理项目
  • 需确保
    /maxcpucount
    > 1才能生效

Multi-threaded MSBuild Tasks

多线程MSBuild任务

  • Individual tasks can run multi-threaded within a single project build
  • Tasks implementing
    IMultiThreadableTask
    can run on multiple threads
  • Tasks must declare thread-safety via
    [MSBuildMultiThreadableTask]
  • 单个任务可在单个项目构建过程中以多线程运行
  • 实现
    IMultiThreadableTask
    接口的任务可在多线程上运行
  • 任务必须通过
    [MSBuildMultiThreadableTask]
    特性声明线程安全性

Analyzing Parallelism with Binlog

使用Binlog分析并行构建情况

Step-by-step:
  1. Replay the binlog:
    dotnet msbuild build.binlog -noconlog -fl -flp:v=diag;logfile=full.log;performancesummary
  2. Check Project Performance Summary at the end of
    full.log
  3. Ideal: build time should be much less than sum of project times (parallelism)
  4. If build time ≈ sum of project times: too many serial dependencies, or one slow project blocking others
  5. grep 'Target Performance Summary' -A 30 full.log
    → find the bottleneck targets
  6. Consider splitting large projects or optimizing the critical path
步骤:
  1. 重放binlog:
    dotnet msbuild build.binlog -noconlog -fl -flp:v=diag;logfile=full.log;performancesummary
  2. 查看
    full.log
    末尾的“项目性能摘要”
  3. 理想情况:构建时间应远小于所有项目构建时间的总和(体现并行性)
  4. 如果构建时间≈所有项目构建时间的总和:依赖关系过于串行,或者存在某个慢项目阻塞了其他项目
  5. 执行
    grep 'Target Performance Summary' -A 30 full.log
    → 找到瓶颈目标
  6. 考虑拆分大型项目或优化关键路径

CI/CD Parallelism Tips

CI/CD并行构建技巧

  • Use
    -m
    in CI (many CI runners have multiple cores)
  • Consider splitting solution into build stages for extreme parallelism
  • Use build caching (NuGet lock files, deterministic builds) to avoid rebuilding unchanged projects
  • dotnet build /graph
    works well with structured CI pipelines
  • 在CI中使用
    -m
    参数(许多CI运行器配备多核CPU)
  • 为实现极致并行性,可考虑将解决方案拆分为多个构建阶段
  • 使用构建缓存(NuGet锁定文件、确定性构建)避免重新构建未变更的项目
  • dotnet build /graph
    适用于结构化CI流水线