Skip to content

Commit bb11b29

Browse files
committed
docs: split performance reports by CI run and localize output
1 parent afc5bbf commit bb11b29

6 files changed

Lines changed: 624 additions & 760 deletions

File tree

‎.github/scripts/run-performance-matrix.sh‎

Lines changed: 89 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ RPC_PORT_START=19090
1111
RPC_PORT_END=19120
1212
BASE_PAYLOAD_BYTES="1024"
1313
NACOS_ADDRESS="127.0.0.1:8848"
14+
REPORT_RUN_TIME_UTC="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
1415

1516
rm -rf "$MATRIX_DIR"
1617
mkdir -p "$MATRIX_DIR" "$LOG_DIR"
1718

1819
if ! command -v tc >/dev/null 2>&1; then
19-
echo "Linux tc is required for network emulation." >&2
20+
echo "性能矩阵需要 Linux tc 命令。" >&2
2021
exit 1
2122
fi
2223

@@ -26,8 +27,8 @@ cleanup() {
2627
}
2728
trap cleanup EXIT
2829

29-
# Resolve and compile everything before tc is applied so dependency downloads never pollute network scenarios.
30-
# JaCoCo is intentionally disabled in this performance job; coverage remains in the unit-test job.
30+
# 在应用 tc 前完成依赖解析与编译,避免下载依赖污染网络场景。
31+
# 性能 job 显式关闭 JaCoCo;覆盖率仍由单元测试 job 负责。
3132
mvn -B -ntp test-compile \
3233
-pl rpc-consumer -am \
3334
-DskipTests \
@@ -57,7 +58,7 @@ run_scenario() {
5758
scenario_index=$((scenario_index + 1))
5859
local rpc_port=$((RPC_PORT_START + scenario_index))
5960
if (( rpc_port > RPC_PORT_END )); then
60-
echo "Scenario count exceeded reserved tc RPC port range ${RPC_PORT_START}-${RPC_PORT_END}." >&2
61+
echo "性能场景数量超过预留 RPC 端口范围 ${RPC_PORT_START}-${RPC_PORT_END}。" >&2
6162
exit 1
6263
fi
6364

@@ -67,7 +68,7 @@ run_scenario() {
6768
output=$(printf "%s/%02d-%s.md" "$MATRIX_DIR" "$scenario_index" "$scenario")
6869
log="$LOG_DIR/$scenario.log"
6970

70-
echo "::group::Performance scenario: $scenario (RPC port $rpc_port)"
71+
echo "::group::性能场景: $scenario (RPC 端口 $rpc_port)"
7172
set +e
7273
mvn -B -ntp test \
7374
-pl rpc-consumer -am \
@@ -95,31 +96,47 @@ run_scenario() {
9596

9697
local summary="$SNAPSHOT_DIR/summary.md"
9798
if [[ "$status" -eq 0 && ! -s "$summary" ]]; then
98-
echo "Scenario $scenario completed without producing $summary" >&2
99+
echo "场景 $scenario 已完成,但没有生成 $summary" >&2
99100
status=2
100101
fi
101102

102103
{
103-
echo "### \`$scenario\`"
104+
echo "### 场景:\`$scenario\`"
104105
echo
105-
echo "- Status: $([[ "$status" -eq 0 ]] && echo 'PASS' || echo 'FAIL')"
106-
echo "- Matrix dimension: \`$category\`"
107-
echo "- Registry / Protocol / Serializer: \`$registry / $protocol / $serializer\`"
108-
echo "- Request payload: \`${payload_bytes} bytes\`"
109-
echo "- RPC port: \`$rpc_port\`"
110-
echo "- Network profile: \`$network\`"
111-
echo "- Strict success requirement: \`$require_all_success\`"
106+
echo "- 状态:$([[ "$status" -eq 0 ]] && echo '通过' || echo '失败')"
107+
echo "- 矩阵维度:\`$category\`"
108+
echo "- 注册中心 / 协议 / 序列化器:\`$registry / $protocol / $serializer\`"
109+
echo "- 请求载荷:\`${payload_bytes} bytes\`"
110+
echo "- RPC 端口:\`$rpc_port\`"
111+
echo "- 网络环境:\`$network\`"
112+
echo "- 是否要求全部请求成功:\`$require_all_success\`"
112113
echo
113114

114115
if [[ "$status" -eq 0 ]]; then
115116
sed \
116117
-e '1{/^# RPC CI Performance Snapshot$/d;}' \
117118
-e '/^> Observational snapshot only\./d' \
118-
-e '/^Raw attempt samples are available/d' \
119-
-e 's/^## Framework metrics$/#### Framework metrics/' \
119+
-e 's/^- Commit:/- 提交:/' \
120+
-e 's/^- Protocol:/- 协议:/' \
121+
-e 's/^- Serializer:/- 序列化器:/' \
122+
-e 's/^- Registry:/- 注册中心:/' \
123+
-e 's/^- RPC port:/- RPC 端口:/' \
124+
-e 's/^- Request payload:/- 请求载荷:/' \
125+
-e 's/^- Require all requests to succeed:/- 是否要求全部请求成功:/' \
126+
-e 's/^- Java:/- Java:/' \
127+
-e 's/^- CPU visible to JVM:/- JVM 可见 CPU:/' \
128+
-e 's#^| Phase | Attempts | Success | Failed | Success % | Concurrency | Attempt req/s | Success req/s | Avg ms | P50 ms | P95 ms | P99 ms | Max ms |#| 阶段 | 尝试数 | 成功 | 失败 | 成功率 % | 并发度 | 尝试吞吐 req/s | 成功吞吐 req/s | 平均 ms | P50 ms | P95 ms | P99 ms | 最大 ms |#' \
129+
-e 's/^| sequential |/| 顺序调用 |/' \
130+
-e 's/^| concurrent |/| 并发调用 |/' \
131+
-e 's/^## Framework metrics$/#### 框架指标/' \
132+
-e 's#^| Phase | Side | Total | Success | Failed | Timeout | Active | Metric avg ms | Metric max ms |#| 阶段 | 侧别 | 总请求 | 成功 | 失败 | 超时 | 活跃 | 指标平均 ms | 指标最大 ms |#' \
133+
-e 's/| CLIENT |/| 客户端 |/' \
134+
-e 's/| SERVER |/| 服务端 |/' \
135+
-e 's/^Latency percentiles include successful RPCs only\. Low sample counts do not establish a reliable tail-latency SLA\.$/延迟分位数仅统计成功 RPC;样本量较小时不能据此得出可靠的尾延迟 SLA。/' \
136+
-e 's/^Nacos visibility polling and warmup are excluded from timing\. In lossy profiles, server observation intervals may include late requests\.$/Nacos 可见性轮询和预热阶段不计入性能计时;在丢包网络下,服务端观察窗口可能包含晚到请求。/' \
120137
"$summary"
121138
else
122-
echo '> Scenario failed. The tail of its Maven log is included below so unsupported or broken modes remain visible.'
139+
echo '> 该场景执行失败。下面保留 Maven 日志尾部,便于继续诊断不支持或异常的模式。'
123140
echo
124141
echo '```text'
125142
tail -n 60 "$log"
@@ -129,9 +146,9 @@ run_scenario() {
129146

130147
if [[ "$status" -ne 0 ]]; then
131148
scenario_failures=$((scenario_failures + 1))
132-
echo "Scenario $scenario FAILED; continuing so the rest of the matrix still runs." >&2
149+
echo "场景 $scenario 失败;继续执行剩余矩阵。" >&2
133150
else
134-
echo "Scenario $scenario passed."
151+
echo "场景 $scenario 通过。"
135152
fi
136153
}
137154

@@ -150,14 +167,14 @@ start_nacos() {
150167

151168
for _ in $(seq 1 60); do
152169
if curl -fsS "http://127.0.0.1:8848/nacos/v1/console/health/readiness" >/dev/null; then
153-
echo "Nacos is ready."
170+
echo "Nacos 已就绪。"
154171
return
155172
fi
156173
sleep 2
157174
done
158175

159176
docker logs rpc-perf-nacos || true
160-
echo "Nacos did not become ready in time." >&2
177+
echo "Nacos 未能在规定时间内就绪。" >&2
161178
exit 1
162179
}
163180

@@ -168,9 +185,8 @@ reset_network() {
168185
shape_rpc_ports() {
169186
reset_network
170187

171-
# Every scenario gets a unique RPC endpoint in a reserved local port range. This prevents a previous Nacos
172-
# ephemeral instance shutdown from racing a new JVM that re-registers the exact same ip:port identity.
173-
# Only this reserved RPC data-plane range is shaped; Nacos 8848/9848/9849 stays untouched.
188+
# 每个场景使用独立 RPC 端口,避免上一个 Nacos 临时实例退出时与新 JVM 复用同一 ip:port 产生竞态。
189+
# 仅塑形预留 RPC 数据面端口;Nacos 8848/9848/9849 不受影响。
174190
sudo tc qdisc add dev lo root handle 1: prio bands 3
175191
sudo tc qdisc add dev lo parent 1:1 handle 10: netem "$@"
176192

@@ -191,84 +207,96 @@ apply_lan_profile() {
191207

192208
start_nacos
193209

194-
# Production-like baseline: gRPC + Nacos + Protobuf + synthetic LAN conditions.
195-
# On loopback, request and response packets are both shaped, so the configured one-way delay roughly doubles
196-
# into added request/response RTT before framework processing time is included.
210+
# 生产型基线:gRPC + Nacos + Protobuf + 合成内网条件。
197211
apply_lan_profile
198-
run_scenario "baseline" "baseline-grpc-protobuf-nacos-lan" \
199-
"nacos" "grpc" "protobuf" "tc LAN: 1ms +/-0.2ms one-way, ~2ms added RTT, 1gbit" \
212+
run_scenario "基线" "baseline-grpc-protobuf-nacos-lan" \
213+
"nacos" "grpc" "protobuf" "tc 内网:单向 1ms ±0.2ms,约增加 2ms RTT,1gbit" \
200214
"$BASE_PAYLOAD_BYTES" 20 40 120 8 8000 10000 true
201215

202-
# Payload matrix: keep the production baseline stack and LAN network profile fixed.
216+
# Payload 矩阵:其余条件固定为生产基线。
203217
for payload in 64 16384 262144; do
204-
run_scenario "payload" "payload-${payload}b" \
205-
"nacos" "grpc" "protobuf" "tc LAN: 1ms +/-0.2ms one-way, ~2ms added RTT, 1gbit" \
218+
run_scenario "请求载荷" "payload-${payload}b" \
219+
"nacos" "grpc" "protobuf" "tc 内网:单向 1ms ±0.2ms,约增加 2ms RTT,1gbit" \
206220
"$payload" 10 20 60 4 10000 12000 true
207221
done
208222

209-
# Serializer matrix: gRPC + Nacos + LAN remain fixed; Protobuf is represented by the baseline.
223+
# 序列化矩阵:gRPC + Nacos + 内网固定;Protobuf 由基线代表。
210224
for serializer in kryo java json; do
211-
run_scenario "serializer" "serializer-${serializer}" \
212-
"nacos" "grpc" "$serializer" "tc LAN: 1ms +/-0.2ms one-way, ~2ms added RTT, 1gbit" \
225+
run_scenario "序列化器" "serializer-${serializer}" \
226+
"nacos" "grpc" "$serializer" "tc 内网:单向 1ms ±0.2ms,约增加 2ms RTT,1gbit" \
213227
"$BASE_PAYLOAD_BYTES" 10 20 60 4 8000 10000 true
214228
done
215229

216-
# Registry matrix: Nacos is represented by the baseline; Local is retained only as a comparison control.
217-
run_scenario "registry" "registry-local-control" \
218-
"local" "grpc" "protobuf" "tc LAN: 1ms +/-0.2ms one-way, ~2ms added RTT, 1gbit" \
230+
# 注册中心矩阵:Nacos 由基线代表;Local 仅作对照。
231+
run_scenario "注册中心" "registry-local-control" \
232+
"local" "grpc" "protobuf" "tc 内网:单向 1ms ±0.2ms,约增加 2ms RTT,1gbit" \
219233
"$BASE_PAYLOAD_BYTES" 10 20 60 4 8000 10000 true
220234

221-
# Network matrix: gRPC + Nacos + Protobuf + 1 KiB payload remain fixed.
235+
# 网络矩阵:固定 gRPC + Nacos + Protobuf + 1 KiB。
222236
shape_rpc_ports delay 3ms 1ms distribution normal rate 500mbit
223-
run_scenario "network" "network-cross-az" \
224-
"nacos" "grpc" "protobuf" "tc cross-AZ/private: 3ms +/-1ms one-way, ~6ms added RTT, 500mbit" \
237+
run_scenario "网络" "network-cross-az" \
238+
"nacos" "grpc" "protobuf" "tc 跨 AZ/私网:单向 3ms ±1ms,约增加 6ms RTT,500mbit" \
225239
"$BASE_PAYLOAD_BYTES" 10 20 60 4 10000 12000 true
226240

227241
shape_rpc_ports delay 25ms 5ms distribution normal loss 0.05% rate 100mbit
228-
run_scenario "network" "network-public-internet" \
229-
"nacos" "grpc" "protobuf" "tc public internet: 25ms +/-5ms one-way, ~50ms added RTT, 0.05% loss, 100mbit" \
242+
run_scenario "网络" "network-public-internet" \
243+
"nacos" "grpc" "protobuf" "tc 普通公网:单向 25ms ±5ms,约增加 50ms RTT,丢包 0.05%,100mbit" \
230244
"$BASE_PAYLOAD_BYTES" 10 20 60 4 12000 14000 false
231245

232246
shape_rpc_ports delay 60ms 10ms distribution normal loss 0.1% rate 50mbit
233-
run_scenario "network" "network-cross-region" \
234-
"nacos" "grpc" "protobuf" "tc cross-region: 60ms +/-10ms one-way, ~120ms added RTT, 0.1% loss, 50mbit" \
247+
run_scenario "网络" "network-cross-region" \
248+
"nacos" "grpc" "protobuf" "tc 跨地域公网:单向 60ms ±10ms,约增加 120ms RTT,丢包 0.1%,50mbit" \
235249
"$BASE_PAYLOAD_BYTES" 8 16 48 4 15000 17000 false
236250

237251
shape_rpc_ports delay 120ms 40ms distribution normal loss 1% rate 5mbit
238-
run_scenario "network" "network-weak-mobile" \
239-
"nacos" "grpc" "protobuf" "tc weak/mobile: 120ms +/-40ms one-way, ~240ms added RTT, 1% loss, 5mbit" \
252+
run_scenario "网络" "network-weak-mobile" \
253+
"nacos" "grpc" "protobuf" "tc 弱网/移动网络:单向 120ms ±40ms,约增加 240ms RTT,丢包 1%,5mbit" \
240254
"$BASE_PAYLOAD_BYTES" 6 12 36 3 20000 22000 false
241255

242-
# Protocol matrix runs last so a currently broken protocol cannot hide the baseline/network/serializer data.
256+
# 协议矩阵放在最后,避免单个异常协议遮住其它维度数据。
243257
apply_lan_profile
244258
for protocol in netty http http2; do
245-
run_scenario "protocol" "protocol-${protocol}" \
246-
"nacos" "$protocol" "protobuf" "tc LAN: 1ms +/-0.2ms one-way, ~2ms added RTT, 1gbit" \
259+
run_scenario "协议" "protocol-${protocol}" \
260+
"nacos" "$protocol" "protobuf" "tc 内网:单向 1ms ±0.2ms,约增加 2ms RTT,1gbit" \
247261
"$BASE_PAYLOAD_BYTES" 10 20 60 4 10000 12000 true
248262
done
249263

250264
reset_network
251265

252266
MATRIX_FILE="$MATRIX_DIR/matrix.md"
267+
SHORT_SHA="${GITHUB_SHA:-local}"
268+
SHORT_SHA="${SHORT_SHA:0:7}"
269+
REPORT_DATE_UTC="${REPORT_RUN_TIME_UTC:0:10}"
270+
REPORT_CLOCK_UTC="${REPORT_RUN_TIME_UTC:11:8}"
271+
REPORT_CLOCK_UTC="${REPORT_CLOCK_UTC//:/-}"
272+
REPORT_RELATIVE_PATH="docs/performance/${REPORT_DATE_UTC}/${REPORT_DATE_UTC}_${REPORT_CLOCK_UTC}Z_${SHORT_SHA}.md"
273+
253274
{
254-
echo "## CI Matrix — $(date -u '+%Y-%m-%d %H:%M:%S UTC') — \`${GITHUB_SHA:-local}\`"
275+
echo "# RPC CI 性能矩阵报告"
255276
echo
256-
echo "- Runner: \`${RUNNER_OS:-local} ${RUNNER_ARCH:-unknown}\`"
257-
echo "- Java: \`$(java -version 2>&1 | head -n 1 | tr -d '"')\`"
258-
echo "- CPU visible: \`$(nproc)\`"
259-
echo "- Baseline: \`gRPC + Nacos + Protobuf + 1 KiB + tc LAN\`"
260-
echo "- Strategy: orthogonal matrix around the production-like baseline; Local Registry is a control only"
261-
echo "- Network simulation: Linux \`tc netem\` on \`lo\`, filtered to reserved RPC ports \`$((RPC_PORT_START + 1))-$RPC_PORT_END\` only"
262-
echo "- Nacos isolation: every scenario gets a unique RPC ip:port instance identity"
263-
echo "- Coverage instrumentation: disabled for performance scenarios"
264-
echo "- Scenario failures: \`$scenario_failures\`"
277+
echo "- 运行时间(UTC):\`$REPORT_RUN_TIME_UTC\`"
278+
echo "- 提交:\`${GITHUB_SHA:-local}\`"
279+
echo "- Runner:\`${RUNNER_OS:-local} ${RUNNER_ARCH:-unknown}\`"
280+
echo "- Java:\`$(java -version 2>&1 | head -n 1 | tr -d '"')\`"
281+
echo "- 可用 CPU:\`$(nproc)\`"
282+
echo "- 生产基线:\`gRPC + Nacos + Protobuf + 1 KiB + tc 内网\`"
283+
echo "- 测试策略:围绕生产基线做正交矩阵,一次只改变一个主要变量;Local Registry 仅作对照"
284+
echo "- 网络模拟:Linux \`tc netem\` 作用于 \`lo\`,仅过滤预留 RPC 端口 \`$((RPC_PORT_START + 1))-$RPC_PORT_END\`"
285+
echo "- Nacos 隔离:每个场景使用独立 RPC ip:port 实例身份"
286+
echo "- 覆盖率插桩:性能场景关闭 JaCoCo"
287+
echo "- 失败场景数:\`$scenario_failures\`"
265288
echo
266289
cat "$MATRIX_DIR"/[0-9][0-9]-*.md
267290
} > "$MATRIX_FILE"
268291

292+
cat > "$MATRIX_DIR/report-meta.env" <<EOF
293+
REPORT_RELATIVE_PATH=$REPORT_RELATIVE_PATH
294+
REPORT_RUN_TIME_UTC=$REPORT_RUN_TIME_UTC
295+
EOF
296+
269297
cat "$MATRIX_FILE"
270298

271299
if [[ "$scenario_failures" -ne 0 ]]; then
272-
echo "$scenario_failures performance scenario(s) failed; matrix data was still generated for diagnosis." >&2
300+
echo "$scenario_failures 个性能场景失败;诊断数据已完整生成。" >&2
273301
exit 1
274302
fi

‎.github/workflows/ci.yml‎

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches: [ main ]
66
paths-ignore:
77
- 'docs/PERFORMANCE.md'
8+
- 'docs/performance/**'
89
pull_request:
910
branches: [ main ]
1011

@@ -97,6 +98,8 @@ jobs:
9798
timeout-minutes: 35
9899
outputs:
99100
performance_markdown: ${{ steps.performance-record.outputs.markdown }}
101+
report_path: ${{ steps.performance-record.outputs.report_path }}
102+
report_time_utc: ${{ steps.performance-record.outputs.report_time_utc }}
100103
steps:
101104
- name: Checkout code
102105
uses: actions/checkout@v7
@@ -121,10 +124,22 @@ jobs:
121124
shell: bash
122125
run: |
123126
matrix='rpc-consumer/target/performance-matrix/matrix.md'
127+
meta='rpc-consumer/target/performance-matrix/report-meta.env'
124128
if [[ ! -s "$matrix" ]]; then
125-
echo 'Performance matrix file was not produced.' >&2
129+
echo '没有生成性能矩阵报告。' >&2
126130
exit 1
127131
fi
132+
if [[ ! -s "$meta" ]]; then
133+
echo '没有生成性能报告元数据。' >&2
134+
exit 1
135+
fi
136+
source "$meta"
137+
case "$REPORT_RELATIVE_PATH" in
138+
docs/performance/*.md) ;;
139+
*) echo "非法性能报告路径: $REPORT_RELATIVE_PATH" >&2; exit 1 ;;
140+
esac
141+
echo "report_path=$REPORT_RELATIVE_PATH" >> "$GITHUB_OUTPUT"
142+
echo "report_time_utc=$REPORT_RUN_TIME_UTC" >> "$GITHUB_OUTPUT"
128143
delimiter="RPC_PERFORMANCE_${GITHUB_RUN_ID}_${GITHUB_RUN_ATTEMPT}"
129144
{
130145
echo "markdown<<${delimiter}"
@@ -165,30 +180,39 @@ jobs:
165180
with:
166181
ref: main
167182
fetch-depth: 0
168-
- name: Append performance matrix
183+
- name: Write standalone performance report
169184
shell: bash
170185
env:
171186
PERFORMANCE_MARKDOWN: ${{ needs.performance-matrix.outputs.performance_markdown }}
187+
REPORT_PATH: ${{ needs.performance-matrix.outputs.report_path }}
188+
REPORT_TIME_UTC: ${{ needs.performance-matrix.outputs.report_time_utc }}
172189
run: |
173190
test -n "$PERFORMANCE_MARKDOWN"
191+
test -n "$REPORT_PATH"
192+
test -n "$REPORT_TIME_UTC"
193+
case "$REPORT_PATH" in
194+
docs/performance/*.md) ;;
195+
*) echo "非法性能报告路径: $REPORT_PATH" >&2; exit 1 ;;
196+
esac
174197
git pull --ff-only origin main
175-
mkdir -p docs
176-
test -f docs/PERFORMANCE.md
177-
{
178-
echo
179-
echo '---'
180-
echo
181-
printf '%s\n' "$PERFORMANCE_MARKDOWN"
182-
} >> docs/PERFORMANCE.md
183-
- name: Commit performance history
198+
mkdir -p "$(dirname "$REPORT_PATH")"
199+
if [[ -e "$REPORT_PATH" ]]; then
200+
echo "性能报告已存在,不允许覆盖: $REPORT_PATH" >&2
201+
exit 1
202+
fi
203+
printf '%s\n' "$PERFORMANCE_MARKDOWN" > "$REPORT_PATH"
204+
echo "已生成独立性能报告: $REPORT_PATH"
205+
- name: Commit performance report
184206
shell: bash
207+
env:
208+
REPORT_PATH: ${{ needs.performance-matrix.outputs.report_path }}
185209
run: |
186210
git config user.name 'github-actions[bot]'
187211
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
188-
git add docs/PERFORMANCE.md
212+
git add "$REPORT_PATH"
189213
if git diff --cached --quiet; then
190-
echo "No performance history change."
214+
echo "没有新的性能报告。"
191215
exit 0
192216
fi
193-
git commit -m 'docs: record RPC performance matrix [skip ci]'
217+
git commit -m 'docs: 记录 RPC 性能测试报告 [skip ci]'
194218
git push origin HEAD:main

0 commit comments

Comments
 (0)