Bazel 构建性能指标提取全指南BEP、查询命令、Trace Profile、执行日志与基准测试【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel构建变慢是几乎每个 Bazel 用户都会遇到的问题。对于高频迭代的核心开发目标、被大量目标依赖的公共库或是自定义规则等代表性目标提升单次构建性能的价值尤为突出。而改进性能的第一步是搞清楚资源究竟消耗在哪里。本文基于 Bazel 官方文档整理了一套完整的构建性能指标采集体系Build Event ProtocolBEP、query/cquery/aquery 查询命令、JSON Trace Profile、Execution Log、Execution Graph Log以及 bazel-bench 基准测试工具。读完本文你将掌握每种指标采集途径的适用场景、关键参数与实现原理能够针对自己的构建建立性能基线并定位瓶颈。为什么要采集构建性能指标Bazel 构建流程由加载loading、分析analysis和执行execution等多个阶段组成耗时可能来自包加载、规则分析、action 执行调度、I/O 与 GC 等不同环节。仅有构建很慢的笼统感知是不够的需要把时间拆解到具体阶段和具体 action才能确定优化方向。官方建议优先关注三类目标核心开发者目标被高频迭代和重建的目标其单次构建的每次提速都会反复兑现。被广泛依赖的公共库它们的编译时间会传导到下游大量目标。某类目标的代表如自定义规则诊断并修复一次构建中的问题往往能推广到更大规模。采集指标正是为了回答资源花在了哪里这个问题。下面逐一介绍 Bazel 提供的六种主要采集途径。途径一Build Event ProtocolBEPBEP 是 Bazel 对外输出构建过程与结果的标准协议。Bazel 会通过 build_event_stream.proto 中定义的一系列 protobuf 消息将构建事件流发送给你指定的后端backend再由后端按需聚合。常用 BEP 输出标志BEP 数据可以落地为本地文件或推送到远程 Build Event Service--build_event_json_filepath以换行分隔的 JSON 形式写出 BEP 事件流便于脚本直接解析--build_event_binary_filepath以 length-delimited 二进制 protobuf 形式写出体积更小--bes_backendendpoint将事件流推送到指定的 Build Event Service 后端适合团队级的集中式指标收集。这些标志在源码中的定义可参见 BuildEventStreamOptions.javabuild_event_binary_file、build_event_json_file与 BuildEventServiceOptions.javabes_backend。值得重点关注的 BEP 指标字段无论聚合方式如何BuildMetrics消息定义于 build_event_stream.proto中的以下子消息是通用的核心指标来源子消息关键字段含义ActionSummaryactions_created/actions_executed本次构建创建/执行的总 action 数含 aspectsactions_executed含远端缓存命中、不含本地 action 缓存命中action_data按 mnemonic 细分每种 action 的执行数、首末执行时间、累计 CPU 时间MemoryMetricsused_heap_size_post_build、peak_post_gc_heap_size等JVM 堆使用情况仅在设置--memory_profile强制一次 Full GC时采集TargetMetricstargets_configured本次构建配置的目标/aspect 数量PackageMetricspackages_loaded成功加载的 BUILD 文件包数量附package_load_metrics明细TimingMetricscpu_time_in_ms、wall_time_in_ms、analysis_phase_time_in_ms、execution_phase_time_in_ms各阶段耗时在 Skymeld 下分析和执行阶段交错两阶段时间之和可能大于墙钟时间此外BuildFinished事件携带退出码与完成时间TargetSummary汇总每个目标的构建/测试状态都是做构建健康度面板的基础数据。途径二query / cquery / aquery 查询命令Bazel 提供三种查询模式分别作用于目标图target graph、配置目标图configured target graph和 action 图action graphquery查询未配置的目标依赖关系cquery基于具体配置查询目标及其依赖能反映配置对图的影响aquery查询 action 图展示构建会产生哪些 action、每个 action 的输入输出与命令行直接服务于性能与正确性分析。三种模式共享同一套查询语言函数库如deps()、rdeps()、somepath()等可以组合出满足需求的复杂查询。例如用aquery查看某个目标的所有 action 及其 mnemonics能够快速发现不必要的 action 数量或过大的 action 粒度。途径三JSON Trace Profile每次构建类命令以及query执行时Bazel 都会自动写出一份 JSON 格式的 trace profile用于快速定位本次调用中时间花在了哪里。Profile 文件的生成与配置默认写入 output base 下的command-$INVOCATION_ID.profile.gz同时创建一个指向最近一次 profile 的符号链接command.profile.gz是否生成由--generate_json_trace_profile控制输出位置由--profile指定以.gz结尾的路径会启用 GZIP 压缩Bazel 默认在 output base 保留最近 5 份 profile由--profiles_to_retain配置显式指定--profile路径会禁用自动回收。可视化与分析工具chrome://tracing在 Chrome 中打开chrome://tracing点击 Load 选择 profile 文件即可可视化。键盘快捷键1选择模式查看/聚合选中事件、2平移、3缩放、4测量两个事件间距、?查看全部快捷键。下图为一份典型的 profile 可视化结果Bazel JSON Trace Profile 在 chrome://tracing 中的可视化界面jq适合脚本化提取。例如提取本地 action 执行中沙箱创建步骤的所有耗时$ zcat $(bazel info output_base)/command.profile.gz | jq .traceEvents | .[] | select(.name sandbox.createFileSystem) | .dur 6378 7247 11850 ...Profile 中的特殊行与常见性能问题Profile 中除各 Bazel 线程的事件外还包含若干特殊行action count并发执行的 action 数干净构建时应逼近--jobs的值CPU usage (Bazel)Bazel 每秒的 CPU 占用值为 1 表示占满一个核Critical Path关键路径上的每个 action 一块Main ThreadBazel 主线程的高层事件如 Launch Blaze、runAnalysisPhaseGarbage Collectorminor/major GC 停顿。分析时应重点查找分析阶段runAnalysisPhase明显慢于预期可能是不良 rule 实现或过度展开 depset关键路径上的单个慢 action可考虑拆分 action 或削减传递依赖以及只有少数线程繁忙、其余都在等待的瓶颈现象。Profile 文件格式顶层对象包含元数据otherData如 invocation ID、日期、output base和实际跟踪数据traceEvents。事件中的ts/dur单位为微秒cat取自ProfilerTask枚举。极短且相邻的事件会被自动合并如需保留原始粒度可传--noslim_profile。途径四Execution Logspawn 执行日志当远端缓存命中率低于预期时Execution Log 是排查机器/环境差异与 action 非确定性non-determinism的关键工具。它记录每个已执行 spawn 的完整信息命令行、环境变量、输入输出文件及其 digest、执行平台与运行结果。三种日志格式与对应标志三个标志互斥定义见 ExecutionOptions.java标志格式说明--execution_log_binary_filelength-delimitedSpawnExecprotobuf旧格式体积较大--execution_log_json_file换行分隔的 JSON便于人工阅读与脚本处理--execution_log_compact_filelength-delimitedExecLogEntryprotobuf整文件 zstd 压缩官方推荐的格式显著更小、生成代价更低三者均可接受布尔值或路径字符串传路径则写入本地文件传true则需配合--experimental_stream_log_file_uploads将日志流式上传到远端存储。附加 spawn 指标在 Execution Log 基础上可额外开启--experimental_execution_log_spawn_metricsBazel 5.2 起可用。开启后日志会包含详细的 spawn 指标本地与远端执行的 action 均适用例如排队时间queuingspawn 等待执行的时间setup / fetch / upload / network 等细分耗时定位执行中被持续拖慢的环节可用于对比本地与远端机器的执行性能差异。典型用法是同一目标分别在本地与远端执行并导出两份日志逐 spawn 对比指标找出差异来源。途径五Execution Graph Log执行图日志JSON Trace Profile 能给出关键路径信息但有时还需要了解已执行 action 之间的完整依赖关系。从 Bazel 6.0 起可以开启执行图日志bazel build //your:target \ --experimental_enable_execution_graph_log \ --experimental_execution_graph_log_dep_typeall其实现位于 ExecutionGraphModule.java输出为一个 zstd 压缩、length-delimited 的execution_graph.Nodeprotobuf 文件默认execution_graph_dump.proto.zst。相关标志包括experimental_enable_execution_graph_log开启执行图日志experimental_execution_graph_log_dep_type依赖信息粒度none/runfiles/allall报告每一条 action 间边experimental_execution_graph_log_path指定本地输出路径支持绝对路径、相对路径或%workspace%前缀设置该路径且未开启主开关会直接报错experimental_execution_graph_log_queue_size/execution_graph_log_queued_bytes_limit写盘队列大小与字节上限用于在峰值内存与写盘阻塞之间权衡-1 表示无界。日志中的每个节点记录Metrics开始时间戳、总耗时、fetch/discover_inputs/parse/process/queue/retry/setup/upload/network等细分耗时、mnemonic、所属 rule class 与 target label并通过dependent_index记录依赖边。从源码看节点还特别处理了 retryretryOf指向先前尝试与 action 缓存命中情况ExecutionGraphModule.java 中CachedActionEvent的注释说明关键路径中间存在缓存命中的 action 时必须记录它们才能正确重建依赖树。该日志的核心价值在于计算drag——某个节点对关键路径施加的拖累即从执行图中移除该节点理论上能节省的时间。基于此可以在真正改动之前预测对构建图与 action 图的影响。途径六使用 bazel-bench 做基准测试除单次构建的指标采集外跨版本、跨提交的性能回归检测需要可重复的基准测试。bazel-bench 是面向 Git 项目的基准测试工具支持两类场景Project benchmark在同一个 Bazel 版本下对比两个 git commit 的构建性能用于检测构建自身的回归通常源于新增依赖Bazel benchmark在同一个 git commit 下对比两个 Bazel 版本用于检测 Bazel 本身的回归适合 Bazel 维护者或 fork 场景。它监控的指标包括墙钟时间wall time、CPU 时间、系统时间以及 Bazel 的 retained heap 大小。官方建议在专用的物理机上运行 bazel-bench避免其他进程干扰以降低结果方差。六种途径的选型建议需求推荐途径建立构建健康度基线、做团队级趋势面板BEPBuildMetrics各字段定位某次构建内部的耗时分布JSON Trace Profilecommand.profile.gz chrome://tracing排查远端缓存命中率低、action 非确定性Execution Log--execution_log_compact_file--experimental_execution_log_spawn_metrics评估改动 action 图的影响、计算关键路径 dragExecution Graph Log--experimental_enable_execution_graph_log检查目标/action 图结构本身query / cquery / aquery跨提交或跨版本做性能回归对比bazel-bench更完整的指标 → 诊断 → 修复闭环流程可进一步阅读构建性能拆解相关章节以及仓库中同目录下的迭代速度优化、内存优化等配套文档。掌握上述采集手段你就拥有了把感觉慢转化为数据慢的能力接下来的一切优化都将有据可依。【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考