Skip to content

Commit 4904d14

Browse files
committed
ci: 计时表只留每平台最重的 10 个,加测试不再需要动它
这张表之前列出每个成员,于是每加一个测试它就过期一次 —— 而这次撑爆分片的 正是"表里没有的成员按中位数计价":mysql-connector-cpp 实测 881s,被当成 60s。 但打包决策其实只由重的那几个做出。linux 上 top10 占总量的 69%,其余 57 个平 均 86s、中位 24s。把它们从表里拿掉,最慢分片一分钟都不动: 完整表 67 行,4 片 74 / 64 / 63 / 63 最慢 74 分 top10 表,4 片 74 / 73 / 60 / 58 最慢 74 分 ## 兜底价必须是固定常数,不能再取中位数 直接缩表会当场炸:表里只剩 10 个重的,中位数就变成"第 5 重的那个",在 linux 上是 875s,于是 57 个小成员每个都按 875s 计价 —— top10 表 + 中位数兜底 90 / 48 / 81 / 46 最慢 90 分 ← 正好撞 job 上限 改成固定 90s(未计时成员的实测均值 86s 取整)。这个值不吃调参:兜底价从 30s 到 300s,最慢分片始终在 72–84 分之间,全都在 90 以下。这种不敏感正是"表可以 长期不动"的依据。 ## shards_for 也得跟着改,否则片数会掉回去 它原本直接把表里的行加起来当工作量。表一缩,linux 总量从 15891s 读成 10965s → 3 片,而 3 片在这张表下最慢 107 分,直接超时。 给 plan_shards 加一个 `<platform> 0 0` 模式返回总量,shards_for 改调它。这样 "有哪些成员"和"未计时的算多少钱"只有一份定义,而不是 yaml 和 lua 各一份等着 漂移。估算精度:linux 16095s vs 实测 15891s,+1.3%。macOS / windows 的成员比 默认价便宜,总量偏高 —— 两者本来就顶着 cap 2,而且偏多分片是安全方向。 ## timings job 同步产出 top10 否则下次刷新又胖回 197 行。 端到端复核:总量 16095s → 4 片,四片覆盖 67/67,最慢 74 分。
1 parent 35f95c7 commit 4904d14

3 files changed

Lines changed: 124 additions & 226 deletions

File tree

.github/workflows/validate.yml

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -478,20 +478,25 @@ jobs:
478478
# `libmysqlclient` (329s) landed on shard 0 next to grpc-codegen
479479
# exactly that way and pushed it past the cap, and the stale table
480480
# then hid the overflow by under-counting the total.
481+
# `plan_shards.lua <platform> 0 0` reports the platform's total cost.
482+
#
483+
# This used to sum the timing table's rows inline, which was the same
484+
# answer only while the table listed every member. It now lists just
485+
# the heavy ones, so summing rows measures a fraction of the work:
486+
# 10965s instead of 16095s on linux, i.e. 3 shards where 4 are
487+
# needed, i.e. a slowest shard of 107 minutes against a 90-minute
488+
# cap. Asking plan_shards keeps ONE definition of both "which members
489+
# are there" and "what does an untimed one cost".
490+
#
491+
# The estimate is tuned on linux (16095s vs 15891s measured, +1.3%).
492+
# macOS and windows members are cheaper on average than the default,
493+
# so their totals come out high — harmless here because both are
494+
# already at their cap, and erring toward more shards is the safe
495+
# direction. Revisit if either cap moves.
481496
shards_for() { # platform cap -> shard count
482-
local secs
483-
secs=$(XPLAT="$1" lua5.4 -e '
484-
local plat = os.getenv("XPLAT")
485-
local sel, all = {}, (os.getenv("MEMBERS") == "__ALL__")
486-
if not all then
487-
for m in (os.getenv("MEMBERS") or ""):gmatch("%S+") do sel[m] = true end
488-
end
489-
local total = 0
490-
for line in io.lines("tests/member-timings.tsv") do
491-
local p, m, s = line:match("^(%S+)\t(%S+)\t(%d+)$")
492-
if p == plat and m and (all or sel[m]) then total = total + tonumber(s) end
493-
end
494-
print(total)')
497+
local secs sel=""
498+
[ "$MEMBERS" = "__ALL__" ] || sel="$MEMBERS"
499+
secs=$(lua5.4 tests/plan_shards.lua "$1" 0 0 $sel)
495500
local n=$(( secs / 4200 + 1 ))
496501
[ "$n" -gt "$2" ] && n="$2"
497502
echo "$1 work: ${secs}s (measured) -> $n shard(s)" >&2
@@ -983,25 +988,37 @@ jobs:
983988
# silently absorb a one-off slow runner. Refresh it deliberately —
984989
# download this artifact and replace tests/member-timings.tsv when
985990
# the numbers have actually moved.
991+
# Top 10 per platform, not every member.
992+
#
993+
# plan_shards prices anything absent at a fixed default, and the
994+
# packing decisions are made by the heavy members anyway — on linux
995+
# the top 10 of 67 are 69% of the total, and dropping the other 57
996+
# moves the slowest shard by 0 minutes. A table that lists everyone
997+
# goes stale the moment someone adds a test; one that lists ten only
998+
# goes stale when the heavy set actually changes. That is the whole
999+
# point: adding a member must not require touching this file.
9861000
{
987-
echo "# <platform>\t<member>\t<seconds> — from run ${{ github.run_id }}"
988-
echo "# refresh: download the member-timings artifact and replace this file"
1001+
echo "# <platform>\t<member>\t<seconds> — the HEAVY members only, top 10"
1002+
echo "# per platform, from run ${{ github.run_id }}. Everything else is"
1003+
echo "# priced at plan_shards.lua's fixed default; adding a test does NOT"
1004+
echo "# require touching this file. Refresh when a member becomes heavy"
1005+
echo "# enough to enter the top 10, or one of these numbers moves."
1006+
# ONLY the default-toolchain leg feeds this table. The llvm leg
1007+
# runs the SAME members again, so globbing every leg would put two
1008+
# rows per (platform, member) into the file — `sort -u` keeps both,
1009+
# since the seconds differ. Both legs are planned from these
1010+
# numbers, so the default leg is the right single baseline.
1011+
#
1012+
# Then: heaviest first, keep 10. `sort -u` before that so a member
1013+
# reported by two shards cannot occupy two of the ten slots.
9891014
for plat in linux macos windows; do
990-
# ONLY the default-toolchain leg feeds this table. The llvm leg
991-
# runs the SAME members again, so globbing every leg would put
992-
# two rows per (platform, member) into the file — `sort -u`
993-
# keeps both, since the seconds differ — and shards_for sums
994-
# every matching row. Linux work would read as roughly double
995-
# and its shard count would be permanently pinned at the cap.
996-
# Both legs are planned from these numbers, so the default leg
997-
# is the right single baseline.
9981015
for f in timings/timings-$plat-default-*/timings.tsv; do
9991016
[ -f "$f" ] || continue
10001017
awk -F'\t' -v p="$plat" '{ printf "%s\t%s\t%s\n", p, $2, $1 }' "$f"
1001-
done
1018+
done | sort -u | sort -t"$(printf '\t')" -k3,3nr | head -10
10021019
done
1003-
} | sort -u > member-timings.tsv
1004-
echo "wrote member-timings.tsv ($(grep -vc '^#' member-timings.tsv) rows)"
1020+
} > member-timings.tsv
1021+
echo "wrote member-timings.tsv ($(grep -vc '^#' member-timings.tsv) rows, top 10/platform)"
10051022
10061023
- name: Upload the timing table for the next run's sharding
10071024
if: always() && hashFiles('member-timings.tsv') != ''

tests/member-timings.tsv

Lines changed: 28 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -1,203 +1,43 @@
1-
# <platform>\t<member>\t<seconds> — from run 31260545520
2-
# refresh: download the member-timings artifact and replace this file
3-
# libmysqlclient / mysql-connector-cpp: measured from run 31266814148's
4-
# linux default 0/3 step durations — that shard was cancelled at the 90m
5-
# cap so its timings artifact never uploaded, and these two are exactly
6-
# the members whose absence caused the overflow. Chicken-and-egg broken by hand, once.
7-
linux abseil 96
8-
linux archive 28
9-
linux asio-module 15
10-
linux asio-ssl 175
11-
linux boost-ext.ut 4
12-
linux build-mcpp 1
13-
linux c-ares 5
14-
linux catch2 59
15-
linux catch2-main 57
16-
linux catch2-v2 14
17-
linux catch2-v2-main 15
18-
linux cjson 19
19-
linux cli11 8
20-
linux cmdline 6
21-
linux core 78
22-
linux curl 264
23-
linux eigen 24
24-
linux eui-neo 43
25-
linux eui-neo-app-main 48
26-
linux eui-neo-markdown 144
27-
linux eui-neo-sdl2 591
28-
linux eui-neo-vulkan 143
29-
linux eui-neo-window 143
30-
linux ffmpeg 296
31-
linux ffmpeg-module 277
32-
linux fmtlib.fmt 4
33-
linux freetype 11
34-
linux glad 3
35-
linux godot-cpp 564
36-
linux godot-cpp-module 627
37-
linux godot-cpp-module-v10 568
38-
linux godot-cpp-v10 504
1+
# <platform>\t<member>\t<seconds> — the HEAVY members only, top 10 per
2+
# platform. Everything else is priced at plan_shards.lua's fixed default;
3+
# on linux the 57 members not listed here average 86s and are 31% of the
4+
# total, and listing them changes the slowest shard by 0 minutes.
5+
#
6+
# So: adding a test does NOT require touching this file. Refresh it when
7+
# a member becomes heavy enough to enter the top 10, or when one of these
8+
# numbers moves materially — download the member-timings artifact from a
9+
# full run and keep the top 10 per platform.
10+
#
11+
# Sources: run 31260545520; libmysqlclient / mysql-connector-cpp measured
12+
# from run 31266814148's linux default 0/3 step durations, whose shard was
13+
# cancelled at the 90m cap before its timings artifact could upload.
3914
linux grpc-codegen 3463
4015
linux grpc-module 1771
41-
linux gui-stack 128
42-
linux imgui 7
43-
linux imgui-module 106
44-
linux imgui-window 7
45-
linux libmysqlclient 329
46-
linux libpng 7
47-
linux llamacpp 132
48-
linux llamacpp-metal 21
49-
linux llmapi 19
50-
linux magic_enum 4
51-
linux marzer.tomlplusplus 7
52-
linux md4c 23
16+
linux protobuf-protoc 885
5317
linux mysql-connector-cpp 881
54-
linux nlohmann.json 10
55-
linux openblas 0
56-
linux opencv-module 649
5718
linux opencv-module-dnn 875
5819
linux opencv-module-unifont 655
59-
linux openssl 166
60-
linux protobuf 175
61-
linux protobuf-gzip 267
62-
linux protobuf-protoc 885
63-
linux protobuf-upb 179
64-
linux re2 16
65-
linux sdl2 108
66-
linux spdlog 9
67-
linux spdlog-compiled 13
68-
linux tinyhttps 11
69-
linux tray 2
70-
linux vulkan 76
71-
linux websocket 20
72-
linux websocket-features 26
73-
linux yyjson 10
74-
macos abseil 48
75-
macos archive 21
76-
macos asio-module 10
77-
macos asio-ssl 65
78-
macos boost-ext.ut 4
79-
macos build-mcpp 3
80-
macos c-ares 5
81-
macos catch2 24
82-
macos catch2-main 27
83-
macos catch2-v2 7
84-
macos catch2-v2-main 9
85-
macos cjson 3
86-
macos cli11 5
87-
macos cmdline 4
88-
macos core 44
89-
macos curl 66
90-
macos eigen 8
91-
macos eui-neo 47
92-
macos eui-neo-app-main 49
93-
macos eui-neo-markdown 64
94-
macos eui-neo-sdl2 138
95-
macos eui-neo-vulkan 59
96-
macos eui-neo-window 48
97-
macos ffmpeg 43
98-
macos ffmpeg-module 107
99-
macos fmtlib.fmt 3
100-
macos freetype 10
101-
macos glad 5
102-
macos godot-cpp 5
103-
macos godot-cpp-module 276
104-
macos godot-cpp-module-v10 195
105-
macos godot-cpp-v10 206
20+
linux opencv-module 649
21+
linux godot-cpp-module 627
22+
linux eui-neo-sdl2 591
23+
linux godot-cpp-module-v10 568
10624
macos grpc-codegen 1156
10725
macos grpc-module 719
108-
macos gui-stack 25
109-
macos imgui 4
110-
macos imgui-module 21
111-
macos imgui-window 0
112-
macos libpng 6
113-
macos llamacpp 63
114-
macos llamacpp-metal 71
115-
macos llmapi 16
116-
macos magic_enum 4
117-
macos marzer.tomlplusplus 6
118-
macos md4c 3
119-
macos nlohmann.json 8
120-
macos openblas 0
121-
macos opencv-module 223
12226
macos opencv-module-dnn 325
123-
macos opencv-module-unifont 164
124-
macos openssl 83
125-
macos protobuf 71
126-
macos protobuf-gzip 97
12727
macos protobuf-protoc 314
128-
macos protobuf-upb 66
129-
macos re2 8
130-
macos sdl2 23
131-
macos spdlog 4
132-
macos spdlog-compiled 6
133-
macos tinyhttps 14
134-
macos tray 3
135-
macos vulkan 8
136-
macos websocket 10
137-
macos websocket-features 11
138-
macos yyjson 5
139-
windows abseil 103
140-
windows archive 62
141-
windows asio-module 15
142-
windows asio-ssl 0
143-
windows boost-ext.ut 4
144-
windows build-mcpp 4
145-
windows c-ares 16
146-
windows catch2 74
147-
windows catch2-main 69
148-
windows catch2-v2 10
149-
windows catch2-v2-main 11
150-
windows cjson 3
151-
windows cli11 8
152-
windows cmdline 5
153-
windows core 100
154-
windows curl 27
155-
windows eigen 12
156-
windows eui-neo 75
157-
windows eui-neo-app-main 88
158-
windows eui-neo-markdown 86
159-
windows eui-neo-sdl2 123
160-
windows eui-neo-vulkan 86
161-
windows eui-neo-window 83
162-
windows ffmpeg 693
163-
windows ffmpeg-module 526
164-
windows fmtlib.fmt 6
165-
windows freetype 13
166-
windows glad 4
167-
windows godot-cpp 7
28+
macos godot-cpp-module 276
29+
macos opencv-module 223
30+
macos godot-cpp-v10 206
31+
macos godot-cpp-module-v10 195
32+
macos opencv-module-unifont 164
33+
macos eui-neo-sdl2 138
34+
windows opencv-module 868
35+
windows opencv-module-dnn 828
16836
windows godot-cpp-module 707
37+
windows ffmpeg 693
16938
windows godot-cpp-module-v10 657
17039
windows godot-cpp-v10 655
171-
windows grpc-codegen 10
172-
windows grpc-module 0
173-
windows gui-stack 19
174-
windows imgui 6
175-
windows imgui-module 24
176-
windows imgui-window 0
177-
windows libpng 10
178-
windows llamacpp 126
179-
windows llamacpp-metal 1
180-
windows llmapi 16
181-
windows magic_enum 4
182-
windows marzer.tomlplusplus 7
183-
windows md4c 3
184-
windows nlohmann.json 10
185-
windows openblas 10
186-
windows opencv-module 868
187-
windows opencv-module-dnn 828
188-
windows opencv-module-unifont 7
189-
windows openssl 1
190-
windows protobuf 139
40+
windows ffmpeg-module 526
19141
windows protobuf-gzip 238
19242
windows protobuf-protoc 152
19343
windows protobuf-upb 151
194-
windows re2 17
195-
windows sdl2 47
196-
windows spdlog 22
197-
windows spdlog-compiled 12
198-
windows tinyhttps 16
199-
windows tray 2
200-
windows vulkan 5
201-
windows websocket 25
202-
windows websocket-features 29
203-
windows yyjson 4

0 commit comments

Comments
 (0)