Repository navigation
增加coverage test并发数降低耗时 - #79927
增加coverage test并发数降低耗时#79927Ray961123 wants to merge 4 commits into
Conversation
Paddle-Bot Review Board (review完成)
可维护性建议(总分 85.4 / 100,只给建议,不影响评审结论)
各维度得分(仅评本 PR 改动,点击展开)
Powered by Nyanpasu claude with Opus 5.5 默认推理级别, please check the suggestions carefully. |
| docker exec -t ${{ env.container_name }} /bin/bash -c ' | ||
| source ${{ github.workspace }}/../../../proxy | ||
| bash $ci_scripts/coverage_test.sh | ||
| bash $ci_scripts/coverage_test.sh parallel |
There was a problem hiding this comment.
| CCACHE_DIR: "/root/.ccache/coverage" | ||
| FLAGS_fraction_of_gpu_memory_to_use: 0.15 | ||
| CTEST_PARALLEL_LEVEL: 2 | ||
| CTEST_PARALLEL_LEVEL: 4 |
There was a problem hiding this comment.
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| shard: [0, 1, 2, 3] |
There was a problem hiding this comment.
加上 matrix 后,GitHub 显示的 job 名会变成
Coverage test (0) 到 Coverage test (3)。.github/workflows/rerun.yml:185 仍传入 JOB_NAME: 'Coverage test',而 .github/actions/rerun-workflow/rerun.sh:60-61 用 select(.name == $job_name) 做精确匹配,所以评论触发的 coverage test 重跑将找不到任何 job。新增的 Coverage collect job 也没有对应的重跑入口。如果分支保护把 Coverage test 设为必需检查,也需要同步调整。建议同步更新 rerun.yml,例如为每个分片名称各加一项,或改为前缀匹配。
| for f in ${SHARD_ROOT}/shard-*/coverage-full.info; do | ||
| [ -f "${f}" ] && lcov_args+=("-a" "${f}") | ||
| done | ||
| if [ ${#lcov_args[@]} -eq 0 ]; then |
There was a problem hiding this comment.
这里只在一个分片报告都没有时才报错。如果只有部分分片的
coverage-full.info 存在,脚本会用不完整的数据继续合并并做 diff 判定。这种情况是可能发生的:coverage_info.sh 全程 set +e,gen_full_report || true(第 187 行)失败或第 214 行 cp 失败时,仍会 exit 0,测试 job 照样显示成功。缺了分片,覆盖率会被低估,给出误导性的 exit 9 失败。建议把 NUM_SHARDS 传入 collect 容器,并检查 shard-0 到 shard-$((NUM_SHARDS-1)) 是否都存在 coverage-full.info,缺失时以非 0 退出并打印缺失的分片编号。
| if [ "${NUM_SHARDS}" -gt 1 ]; then | ||
| echo "::group::Generate shard ${SHARD_INDEX}/${NUM_SHARDS} ut_list" | ||
| ctest -N | awk -F ': ' '{print $2}' | sed '/^$/d' | sed '$d' > all_ut_list | ||
| python ${PADDLE_ROOT}/tools/shard_ut_list.py ${PADDLE_ROOT} ${SHARD_INDEX} ${NUM_SHARDS} |
|
|
||
| # Concatenate shard cost data into the canonical CFS path | ||
| mkdir -p /home/data/cfs/coverage/${PR_ID}/${COMMIT_ID} | ||
| cat ${SHARD_ROOT}/shard-*/CTestCostData.txt > /home/data/cfs/coverage/${PR_ID}/${COMMIT_ID}/CTestCostData.txt 2>/dev/null || true |
There was a problem hiding this comment.
There was a problem hiding this comment.
新版本改为按用例名去重,但还有两个问题:
- 第 71-73 行注释说每个分片只记录了实际运行的用例,这与实际不符。
ci/utils.sh:787-789在测试前会把全量基线CTestCostData.txt复制到Testing/Temporary,所以每个分片上传的文件都包含全部用例,未在本分片运行的用例保留的是基线旧值。 lines[$1] = $0保留最后读到的记录,shard-*展开后shard-3最后读入,因此除 shard-3 实际运行的用例外,其它分片的真实耗时都会被基线旧值覆盖。另外---之后的失败用例名会被丢弃,最终只输出一个空的---。
建议各分片上传 CostData 时一并上传本分片的 ut_list,合并时每个用例只取其所属分片的记录,失败用例名合并去重后放在 --- 之后。
| NO_PYTHON_COVERAGE_DATA=1 | ||
| fi | ||
|
|
||
| # ---- C++ diff part (same logic as coverage_info.sh) ---- |
There was a problem hiding this comment.
💡 可维护性建议(设计一致性,不阻塞合入):第 66-103 行的 C++/Python diff 抽取逻辑,以及第 25-36 行的 lcov 安装逻辑,与 ci/coverage_info.sh 第 20-31 行和第 224-287 行基本逐行相同,第 66 行注释也写了 “same logic as coverage_info.sh”。以后调整 diff 规则需要同时改两处,容易不一致。建议把这两段抽成函数供两边复用,例如放到 ci/utils.sh 或新建一个 coverage_common.sh。
There was a problem hiding this comment.
最新提交删除了 ci/coverage_common.sh,这条建议的问题又出现了:ci/coverage_collect.sh 第 76-110 行与 ci/coverage_info.sh 第 210-241 行的 gen_coverage_diff() 再次逐行重复,lcov 安装代码也在 coverage_collect.sh:25-36、coverage_info.sh:20-31、coverage_all_info.sh:20-31 三处各有一份。如果有意不引入新的公共文件,可以考虑把这两段函数放进 ci/utils.sh,coverage_collect.sh 只 source 后直接调用。
| # "Coverage collect" job merges all shard reports and does the diff/judge part. | ||
| if [ "${COVERAGE_SHARD_ONLY:-OFF}" == "ON" ]; then | ||
| echo "::group::Gen python full report (shard ${SHARD_INDEX})" | ||
| coverage combine $(ls python-coverage.data.*) || NO_PYTHON_COVERAGE_DATA=1 |
There was a problem hiding this comment.
💡 可维护性建议(底层优雅度,不阻塞合入):第 196-209 行重新写了一遍同文件第 244-267 行 gen_python_full_report() 的处理流程(combine、xml、extract、remove)。建议把函数定义移到分片分支之前直接调用,这样 Python 覆盖率的过滤规则只需维护一份。
There was a problem hiding this comment.
gen_python_full_report 已移到公共文件,原问题中的 extract/remove 部分已消除。但分片分支第 188-190 行与普通路径第 208-214 行仍重复 coverage combine、coverage xml、coverage_python_coverage.py 三步,而且后续处理已经出现差异(分片分支用 if 判断 NO_PYTHON_COVERAGE_DATA,普通路径用 || true)。建议把这三步连同 gen_python_full_report 放进 coverage_common.sh 的同一个函数,两条路径共用。
| timeout-minutes: 180 | ||
| env: | ||
| SHARD_INDEX: ${{ matrix.shard }} | ||
| NUM_SHARDS: 4 |
There was a problem hiding this comment.
💡 可维护性建议(逻辑清晰度,不阻塞合入):NUM_SHARDS: 4 与第 306 行的 shard: [0, 1, 2, 3] 必须手动保持一致。如果只扩展 matrix 而忘了改这里,新增分片会因 shard_index 越界而失败;而且由于前面提到的返回值未检查,该分片会静默回退为跑全量测试。建议改为 NUM_SHARDS: ${{ strategy.job-total }}。
| # fi | ||
| if [ -z "$block_jobs" ]; then | ||
| block_jobs=$(echo "$jobs_response" | jq -r --arg job_name "$JOB_NAME" \ | ||
| '.jobs[] | select(.name | startswith($job_name + " (")) | .id') |
There was a problem hiding this comment.
前缀匹配会命中
Coverage test (0) 到 Coverage test (3) 四个 job,但下方循环是对每个 job 单独调用 POST /actions/jobs/{job_id}/rerun。根据 GitHub 社区反馈(https://github.com/orgs/community/discussions/176756 ),第一次调用会为整个 run 创建新的 attempt,之后再重跑上一 attempt 中的其它 job 会返回 403 Only jobs from the current attempt can be re-run。这样评论重跑实际只会重跑第一个分片及其依赖的 collect,真正失败的分片可能没有被重跑;第 74 行的 curl 也没有检查返回码,日志里不容易发现。建议匹配到多个 job 时改为调用一次 /actions/runs/$run_id/rerun-failed-jobs。
| for f in ${SHARD_ROOT}/shard-*/coverage-full.info; do | ||
| [ -f "${f}" ] && lcov_args+=("-a" "${f}") | ||
| done | ||
| lcov "${lcov_args[@]}" -o coverage-full.info --rc lcov_branch_coverage=0 |
There was a problem hiding this comment.
💡 可维护性建议(错误处理一致性,不阻塞合入):脚本开头是 set +e,这里和第 63 行的 lcov 合并失败(例如某个分片的 tracefile 损坏)时都不会中止。C++ 合并失败而 Python 数据正常时,coverage-full.info 和 coverage-diff.info 都不会生成,第 84 行的 cp 仍会成功;随后 coverage_judge.sh 调用的 coverage_lines.py 遇到不存在的文件会直接返回 0,C++ 覆盖率门禁会静默通过。第 40-48 行已经对缺失分片显式 exit 101,建议对两处 lcov 合并也检查返回值并以同样方式失败。
| # defines functions and does not execute anything by itself. | ||
|
|
||
| # Install lcov from the cached tarball (shared CFS cache at /root/.cache). | ||
| function install_lcov() { |
There was a problem hiding this comment.
💡 可维护性建议(跨模块架构,不阻塞合入):install_lcov 抽成公共函数后,ci/coverage_all_info.sh:21-31 仍保留一份逐行相同的安装代码(全量覆盖率流程由 ci/utils.sh:1022 调用)。以后升级 lcov 版本或更换下载地址需要同时改两处。建议 coverage_all_info.sh 也 source coverage_common.sh 并调用 install_lcov。
|
|
||
| # Concatenate shard cost data into the canonical CFS path | ||
| mkdir -p /home/data/cfs/coverage/${PR_ID}/${COMMIT_ID} | ||
| cat ${SHARD_ROOT}/shard-*/CTestCostData.txt > /home/data/cfs/coverage/${PR_ID}/${COMMIT_ID}/CTestCostData.txt 2>/dev/null || true |
There was a problem hiding this comment.
新版本改为按用例名去重,但还有两个问题:
- 第 71-73 行注释说每个分片只记录了实际运行的用例,这与实际不符。
ci/utils.sh:787-789在测试前会把全量基线CTestCostData.txt复制到Testing/Temporary,所以每个分片上传的文件都包含全部用例,未在本分片运行的用例保留的是基线旧值。 lines[$1] = $0保留最后读到的记录,shard-*展开后shard-3最后读入,因此除 shard-3 实际运行的用例外,其它分片的真实耗时都会被基线旧值覆盖。另外---之后的失败用例名会被丢弃,最终只输出一个空的---。
建议各分片上传 CostData 时一并上传本分片的 ut_list,合并时每个用例只取其所属分片的记录,失败用例名合并去重后放在 --- 之后。
| # "Coverage collect" job merges all shard reports and does the diff/judge part. | ||
| if [ "${COVERAGE_SHARD_ONLY:-OFF}" == "ON" ]; then | ||
| echo "::group::Gen python full report (shard ${SHARD_INDEX})" | ||
| coverage combine $(ls python-coverage.data.*) || NO_PYTHON_COVERAGE_DATA=1 |
There was a problem hiding this comment.
gen_python_full_report 已移到公共文件,原问题中的 extract/remove 部分已消除。但分片分支第 188-190 行与普通路径第 208-214 行仍重复 coverage combine、coverage xml、coverage_python_coverage.py 三步,而且后续处理已经出现差异(分片分支用 if 判断 NO_PYTHON_COVERAGE_DATA,普通路径用 || true)。建议把这三步连同 gen_python_full_report 放进 coverage_common.sh 的同一个函数,两条路径共用。
PR Category
User Experience
PR Types
Improvements
Description
增加coverage test并发数降低耗时
是否引起精度变化
否