Skip to content

Commit 0500fa4

Browse files
committed
ci: split dns benchmark suites with overlay harness
1 parent 731be6d commit 0500fa4

File tree

3 files changed

+215
-23
lines changed

3 files changed

+215
-23
lines changed

.github/workflows/dns-benchmark-compare.yml

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -76,27 +76,87 @@ jobs:
7676
BASE_REF="${{ github.event.inputs.base_ref }}"
7777
HEAD_REF="${{ github.event.inputs.head_ref }}"
7878
fi
79-
set +e
80-
./scripts/ci/dns-benchmark-compare.sh "$BASE_REF" "$HEAD_REF" 2>&1 | tee bench-artifacts/run.log
81-
status=${PIPESTATUS[0]}
82-
set -e
83-
if [[ $status -ne 0 && ! -f bench-artifacts/report.md ]]; then
84-
{
85-
echo "## DNS Benchmark Compare"
86-
echo
87-
echo "- Status: failed"
88-
echo "- Exit code: \`$status\`"
89-
echo "- Base ref: \`$BASE_REF\`"
90-
echo "- Head ref: \`$HEAD_REF\`"
91-
echo
92-
echo "### Failure Log (tail)"
93-
echo
94-
echo '```text'
95-
tail -n 200 bench-artifacts/run.log || true
96-
echo '```'
97-
} > bench-artifacts/report.md
98-
fi
99-
exit $status
79+
overall=0
80+
run_suite() {
81+
suite="$1"
82+
pkg="$2"
83+
filter="$3"
84+
exclude_files="${4:-}"
85+
suite_dir="bench-artifacts/${suite}"
86+
mkdir -p "$suite_dir"
87+
set +e
88+
BENCH_PACKAGE="$pkg" \
89+
BENCH_FILTER="$filter" \
90+
BENCH_OVERLAY_DIR="$PWD/scripts/ci/benchmarks" \
91+
BENCH_EXCLUDE_TEST_FILES="$exclude_files" \
92+
ARTIFACT_DIR="$PWD/$suite_dir" \
93+
./scripts/ci/dns-benchmark-compare.sh "$BASE_REF" "$HEAD_REF" \
94+
2>&1 | tee "$suite_dir/run.log"
95+
status=${PIPESTATUS[0]}
96+
set -e
97+
if [[ $status -ne 0 && ! -f "$suite_dir/report.md" ]]; then
98+
{
99+
echo "## DNS Benchmark Compare (${suite})"
100+
echo
101+
echo "- Status: failed"
102+
echo "- Exit code: \`$status\`"
103+
echo "- Base ref: \`$BASE_REF\`"
104+
echo "- Head ref: \`$HEAD_REF\`"
105+
echo "- Package: \`$pkg\`"
106+
echo
107+
echo "### Failure Log (tail)"
108+
echo
109+
echo '```text'
110+
tail -n 200 "$suite_dir/run.log" || true
111+
echo '```'
112+
} > "$suite_dir/report.md"
113+
fi
114+
echo "$status" > "$suite_dir/status.txt"
115+
if [[ $status -ne 0 ]]; then
116+
overall=1
117+
fi
118+
}
119+
120+
run_suite "control_dns" \
121+
"./control" \
122+
"^Benchmark(AsyncCache|SingleflightOverhead|HighQpsScenario|RealisticDnsQuery|DnsController_Singleflight|PipelinedConn_Concurrent|PipelinedConn_Sequential)$" \
123+
"control/tcp_test.go,control/tcp_splice_bench_test.go"
124+
125+
run_suite "component_dns" \
126+
"./component/dns" \
127+
"^BenchmarkUpstreamResolver_GetUpstream_(Serial|Parallel)$"
128+
129+
{
130+
echo "## DNS Benchmark Compare"
131+
echo
132+
echo "- Base ref: \`$BASE_REF\`"
133+
echo "- Head ref: \`$HEAD_REF\`"
134+
echo
135+
echo "### Suite Status"
136+
echo
137+
control_status="$(cat bench-artifacts/control_dns/status.txt 2>/dev/null || echo 1)"
138+
comp_status="$(cat bench-artifacts/component_dns/status.txt 2>/dev/null || echo 1)"
139+
echo "- control_dns: $([[ \"$control_status\" == \"0\" ]] && echo 'success' || echo 'failed')"
140+
echo "- component_dns: $([[ \"$comp_status\" == \"0\" ]] && echo 'success' || echo 'failed')"
141+
echo
142+
echo "### control_dns"
143+
echo
144+
if [[ -f bench-artifacts/control_dns/report.md ]]; then
145+
cat bench-artifacts/control_dns/report.md
146+
else
147+
echo "_No report generated_"
148+
fi
149+
echo
150+
echo "### component_dns"
151+
echo
152+
if [[ -f bench-artifacts/component_dns/report.md ]]; then
153+
cat bench-artifacts/component_dns/report.md
154+
else
155+
echo "_No report generated_"
156+
fi
157+
} > bench-artifacts/report.md
158+
159+
exit $overall
100160
101161
- name: Upload Benchmark Artifacts
102162
if: always()
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package dns
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
"unsafe"
7+
)
8+
9+
var benchUpstreamSink *Upstream
10+
11+
func setField(field reflect.Value, value reflect.Value) {
12+
reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Set(value)
13+
}
14+
15+
func setBoolField(field reflect.Value, value bool) {
16+
reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().SetBool(value)
17+
}
18+
19+
func benchmarkInitializedResolver(b *testing.B) *UpstreamResolver {
20+
r := &UpstreamResolver{}
21+
up := &Upstream{}
22+
rv := reflect.ValueOf(r).Elem()
23+
24+
// Legacy layout (mutex + init flag).
25+
if initField := rv.FieldByName("init"); initField.IsValid() {
26+
upField := rv.FieldByName("upstream")
27+
if !upField.IsValid() {
28+
b.Fatalf("legacy upstream field missing")
29+
}
30+
setField(upField, reflect.ValueOf(up))
31+
setBoolField(initField, true)
32+
return r
33+
}
34+
35+
// New layout (atomic state pointer).
36+
stateField := rv.FieldByName("state")
37+
if !stateField.IsValid() {
38+
b.Fatalf("unsupported UpstreamResolver layout")
39+
}
40+
store := stateField.Addr().MethodByName("Store")
41+
if !store.IsValid() || store.Type().NumIn() != 1 {
42+
b.Fatalf("state.Store method unavailable")
43+
}
44+
statePtrType := store.Type().In(0) // *upstreamState
45+
state := reflect.New(statePtrType.Elem())
46+
stateUpstreamField := state.Elem().FieldByName("upstream")
47+
if !stateUpstreamField.IsValid() {
48+
b.Fatalf("upstreamState.upstream field missing")
49+
}
50+
setField(stateUpstreamField, reflect.ValueOf(up))
51+
store.Call([]reflect.Value{state})
52+
return r
53+
}
54+
55+
func BenchmarkUpstreamResolver_GetUpstream_Serial(b *testing.B) {
56+
r := benchmarkInitializedResolver(b)
57+
b.ResetTimer()
58+
for i := 0; i < b.N; i++ {
59+
u, err := r.GetUpstream()
60+
if err != nil {
61+
b.Fatalf("GetUpstream failed: %v", err)
62+
}
63+
benchUpstreamSink = u
64+
}
65+
}
66+
67+
func BenchmarkUpstreamResolver_GetUpstream_Parallel(b *testing.B) {
68+
r := benchmarkInitializedResolver(b)
69+
b.ResetTimer()
70+
b.RunParallel(func(pb *testing.PB) {
71+
for pb.Next() {
72+
u, err := r.GetUpstream()
73+
if err != nil {
74+
b.Fatalf("GetUpstream failed: %v", err)
75+
}
76+
benchUpstreamSink = u
77+
}
78+
})
79+
}

scripts/ci/dns-benchmark-compare.sh

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ BENCH_FILTER="${BENCH_FILTER:-^Benchmark(AsyncCache|SingleflightOverhead|HighQps
3030
BENCH_COUNT="${BENCH_COUNT:-3}"
3131
BENCH_TIME="${BENCH_TIME:-200ms}"
3232
ARTIFACT_DIR="${ARTIFACT_DIR:-bench-artifacts}"
33+
BENCH_OVERLAY_DIR="${BENCH_OVERLAY_DIR:-}"
34+
BENCH_EXCLUDE_TEST_FILES="${BENCH_EXCLUDE_TEST_FILES:-}"
3335
KEEP_WORKTREES="${KEEP_WORKTREES:-0}"
3436
WORKTREE_ROOT="${WORKTREE_ROOT:-$(mktemp -d -t dae-dns-bench-XXXXXX)}"
3537

@@ -89,7 +91,48 @@ prepare_tree() {
8991
export BPF_STRIP_FLAG="${BPF_STRIP_FLAG:--no-strip}"
9092
export BPF_CFLAGS="${BPF_CFLAGS:--O2 -Wall -Werror -DMAX_MATCH_SET_LEN=1024}"
9193
export BPF_TARGET="${BPF_TARGET:-bpfel}"
92-
go generate ./control/control.go >/dev/null
94+
if [[ "$BENCH_PACKAGE" == "./control"* || "$BENCH_PACKAGE" == "control"* ]]; then
95+
go generate ./control/control.go >/dev/null
96+
fi
97+
)
98+
}
99+
100+
apply_overlay() {
101+
local wt="$1"
102+
if [[ -z "$BENCH_OVERLAY_DIR" ]]; then
103+
return 0
104+
fi
105+
local overlay_abs="$BENCH_OVERLAY_DIR"
106+
if [[ ! -d "$overlay_abs" ]]; then
107+
die "overlay dir does not exist: $overlay_abs"
108+
fi
109+
while IFS= read -r src; do
110+
local rel="${src#$overlay_abs/}"
111+
local dst="$wt/$rel"
112+
mkdir -p "$(dirname "$dst")"
113+
cp "$src" "$dst"
114+
done < <(find "$overlay_abs" -type f | sort)
115+
}
116+
117+
exclude_test_files() {
118+
local wt="$1"
119+
if [[ -z "$BENCH_EXCLUDE_TEST_FILES" ]]; then
120+
return 0
121+
fi
122+
IFS=',' read -r -a patterns <<<"$BENCH_EXCLUDE_TEST_FILES"
123+
(
124+
cd "$wt"
125+
shopt -s nullglob
126+
: > .bench_excluded_files
127+
for raw in "${patterns[@]}"; do
128+
pat="$(echo "$raw" | xargs)"
129+
[[ -z "$pat" ]] && continue
130+
for f in $pat; do
131+
[[ -f "$f" ]] || continue
132+
mv "$f" "${f}.bench_disabled"
133+
echo "$f" >> .bench_excluded_files
134+
done
135+
done
93136
)
94137
}
95138

@@ -132,12 +175,16 @@ run_benchmarks() {
132175
-benchmem \
133176
-count "$BENCH_COUNT" \
134177
-benchtime "$BENCH_TIME" \
135-
| tee "$REPO_ROOT/$output_file"
178+
| tee "$output_file"
136179
)
137180
}
138181

139182
prepare_tree "$BASE_WT"
140183
prepare_tree "$HEAD_WT"
184+
apply_overlay "$BASE_WT"
185+
apply_overlay "$HEAD_WT"
186+
exclude_test_files "$BASE_WT"
187+
exclude_test_files "$HEAD_WT"
141188

142189
BASE_LIST="$ARTIFACT_DIR/base_benchmarks.txt"
143190
HEAD_LIST="$ARTIFACT_DIR/head_benchmarks.txt"
@@ -177,6 +224,12 @@ REPORT_MD="$ARTIFACT_DIR/report.md"
177224
echo "- Benchmark filter: \`$BENCH_FILTER\`"
178225
echo "- Benchmark count: \`$BENCH_COUNT\`"
179226
echo "- Benchmark time: \`$BENCH_TIME\`"
227+
if [[ -n "$BENCH_OVERLAY_DIR" ]]; then
228+
echo "- Overlay dir: \`$BENCH_OVERLAY_DIR\`"
229+
fi
230+
if [[ -n "$BENCH_EXCLUDE_TEST_FILES" ]]; then
231+
echo "- Excluded test files: \`$BENCH_EXCLUDE_TEST_FILES\`"
232+
fi
180233
echo
181234
echo "### Common Benchmarks"
182235
echo

0 commit comments

Comments
 (0)