mcpField
E
eval-performance

eval-performance

github.com/dotnet开发5.8k3.6k 次安装1 天前更新
代码仓库

关于 eval-performance

面向 MSBuild 项目的评估性能诊断技能,要求先用测量确认瓶颈,再检查导入、Glob、属性函数及重复评估等因素。

主要功能

  1. 01区分评估与执行耗时
  2. 02使用 binlog 分析评估时长
  3. 03检查导入链与全局属性
  4. 04排查昂贵的 Glob 和属性函数
  5. 05根据测量结果提出优化

适用场景

  1. 01调查构建启动阶段耗时
  2. 02确认项目是否被重复评估
  3. 03定位导入或文件匹配造成的开销

MCP 相关

指导使用 Microsoft.AITools.BinlogMcp 的 evaluations、imports 和 properties 等 MCP 工具检查评估性能。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dotnet/skills --skill eval-performance

安装后在 Claude Code 中输入/eval-performance确认已加载。

详细介绍

诊断 MSBuild 评估性能

评估是 MSBuild 在任何目标运行之前执行的工作,包括读取项目文件、处理导入、展开 glob。此技能可帮助你发现并确认评估瓶颈。先测量;只有测量结果证明有必要时,才建议更改。

更改任何内容之前,先确认问题

只有在评估被测量证实为瓶颈时才采取行动。遇到以下情况时,不要采取行动:

  • 缓慢发生在编译或目标执行期间,而非评估期间。 这不是评估问题——请改用 build-perf-diagnostics。
  • **问题是“重建次数太多”/增量构建。**请改用 incremental-build。
  • **没有测量数据。**如果没有 binlog 或计时摘要显示评估缓慢,请先收集数据(见下文)。不要仅凭查看项目文件来猜测。
  • **出现了下述模式,但评估已经很快。**只有在数据表明会消耗实际时间时,宽泛 glob、深层导入或 EnableDefaultItems 才值得指出。评估很快的项目无需更改。

如果存在某种模式但尚未测量,请将其作为观察结果报告,并让用户决定——不要在没有证据表明会显著增加评估耗时的情况下,为了符合“最佳实践”而重写有效配置。优先选择最小且有针对性的更改;不要一开始就禁用 SDK 默认设置。

MSBuild 评估阶段

如需全面了解 MSBuild 的评估和执行模型,请参阅构建过程概述。

  1. 初始属性:环境变量、全局属性、保留属性
  2. 导入和属性评估:处理 <Import>,从上到下评估 <PropertyGroup>
  3. 项定义评估:<ItemDefinitionGroup> 元数据默认值
  4. 项评估:包含 Include、Remove、Update 和 glob 展开的 <ItemGroup>
  5. UsingTask 评估:注册自定义任务

关键点:评估发生在任何目标运行之前。评估缓慢 = 构建启动缓慢,即使没有内容需要编译也是如此。

诊断评估性能

首选:binlog MCP

使用 binlog MCP 服务(Microsoft.AITools.BinlogMcp,通过 binlog MCP 命名空间公开)分析评估性能:

  1. 使用 evaluations 工具列出所有评估及其耗时
  2. 使用 evaluation_global_properties 检查是否存在全局属性不同的多次评估
  3. 使用 evaluation_properties 检查特定项目和 TFM 的已评估属性
  4. 使用 imports 工具分析导入链的深度和结构
  5. 使用 properties 工具检查耗时较长的属性函数评估
备用方案:文本日志重放和预处理(MCP 不可用时)
使用 binlog
  1. 重放 binlog:dotnet msbuild build.binlog -noconlog -fl "-flp:v=diag;logfile=full.log"
  2. 搜索评估事件:grep -i 'Evaluation started\|Evaluation finished' full.log
  3. 同一项目出现多次评估 = 过度构建
  4. 查找“Project evaluation started/finished”消息及其时间戳
使用 /pp(预处理)
  • dotnet msbuild -pp:full.xml MyProject.csproj
  • 显示所有导入均已内联的完整展开项目
  • 用于了解:导入了哪些内容、导入深度、内容总量
  • 预处理输出较大(超过 10K 行)= 评估负担较重
使用 /clp:PerformanceSummary
  • 将其添加到构建命令中,以获取耗时明细
  • 单独显示评估耗时,以及目标/任务执行耗时

开销较大的 Glob 模式

只有在测量结果表明项评估较慢且原因是 glob 时,才采用这些补救措施;不会遍历大型目录树的自定义 glob 没有问题。

  • 类似 **/*.cs 的 glob 会遍历整个目录树
  • SDK 默认 glob 已经过优化,但自定义 glob 可能没有
  • 问题:对 node_modules/、.git/、bin/、obj/ 执行 glob 操作——这些目录中可能有数百万个文件
  • 补救措施:使用 <DefaultItemExcludes> 排除大型目录
  • 补救措施:明确指定 glob 路径:使用 src/**/*.cs,而不是 **/*.cs
  • 补救措施:将 <EnableDefaultItems>false</EnableDefaultItems> 作为最后手段(会失去 SDK 默认项)——请先优先尝试上述两个选项
  • 检查:在诊断日志中搜索 Compile 项 → 如果 Compile 项包含意外文件,说明 glob 范围过宽

导入链分析

  • 深层导入链(超过 20 层)会拖慢评估
  • 每次导入都会产生文件 I/O、解析和评估开销
  • 常见原因:NuGet 包添加了 .props/.targets、框架 SDK 导入、Directory.Build 链
  • 诊断:查看 /pp 输出 → 搜索 <!-- Importing 注释以查看导入树
  • 补救措施(仅当导入链的开销经测量确实较大时):尽可能减少传递性包导入,合并导入

多次评估

  • 同一项目被评估多次 = 浪费工作
  • 常见原因:被多个其他项目引用,且全局属性各不相同
  • 每组唯一的全局属性都会触发单独评估
  • 诊断:grep 'Evaluation started.*ProjectName' full.log → 如果结果数大于 1,请检查是否存在不同的全局属性
  • 修复:规范化全局属性,使用图构建(/graph)

TreatAsLocalProperty

  • 防止属性值通过 MSBuild 任务传递到子项目
  • 过度使用:声明许多 TreatAsLocalProperty 条目会增加评估开销
  • 正确用法:仅在确实需要覆盖继承属性时使用

属性函数开销

  • 属性函数会在评估期间执行
  • 大多数开销很小(字符串操作)
  • 开销较大:在评估期间执行 $([System.IO.File]::ReadAllText(...))——每次评估都会读取文件
  • 开销较大:网络调用、繁重计算
  • 规则:属性函数应快速执行且无副作用

优化检查清单

  • 检查预处理输出大小:dotnet msbuild -pp:full.xml
  • 验证评估次数:每个项目、每个 TFM 应为 1 次
  • 将大型目录排除在 glob 之外
  • 避免在评估期间于属性函数中执行文件 I/O
  • 尽量减少导入深度
  • 使用图构建以减少重复评估
  • 检查是否存在不必要的 UsingTask 声明

评论

支持 Markdown