Skip to content

Commit 77995b7

Browse files
committed
Support benchmark smoke runs on small CI hosts
1 parent 2a3e698 commit 77995b7

3 files changed

Lines changed: 32 additions & 7 deletions

File tree

‎.github/workflows/asap-sketch-benchmark.yml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
- name: Test streaming window correctness
3434
run: cargo test --manifest-path asap-precompute-rs/Cargo.toml --release --features stream-benchmark --bin asap-stream-bench
3535
- name: Run persistent OTLP network benchmark
36-
run: ./benchmarks/run-nightly.sh
36+
run: ./benchmarks/run-nightly.sh --allow-shared-infrastructure
3737
- name: Verify streaming measurements
3838
run: |
3939
python3 - <<'PYCODE'
@@ -62,8 +62,10 @@ jobs:
6262
for path in root.glob("traffic-*-sps/window-*/*mbit/*/*/config.json"):
6363
config = json.loads(path.read_text())
6464
assigned = list(config["component_cores"].values())
65-
assert len(assigned) == 5 and len(set(assigned)) == 5
66-
assert set(config["generator_cores"]).isdisjoint(assigned)
65+
assert len(assigned) == 4 and len(set(assigned)) == 4
66+
assert config["placement"] in {"exclusive-capacity", "shared-infrastructure-smoke"}
67+
if config["placement"] == "exclusive-capacity":
68+
assert set(config["generator_cores"]).isdisjoint(assigned)
6769
assert (root / "throughput.svg").is_file()
6870
assert (root / "resources.svg").is_file()
6971
PYCODE

‎benchmarks/STREAMING.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ No component has a Docker memory limit. The exact mapping is recorded as
8282
`--traffic-rates 10000 25000 50000 100000 200000 300000 400000` controls offered traffic per source and
8383
`--window-points 16384 65536 262144` controls aggregation volume per source.
8484
Together they form the default two-dimensional ingestion-rate/window-size sweep.
85+
86+
`--allow-shared-infrastructure` exists only for correctness smoke tests on CI
87+
runners with fewer than nine CPUs. It keeps the four evaluated processors on
88+
distinct CPUs but allows generator and backend infrastructure to overlap them.
89+
The resulting `placement` is recorded as `shared-infrastructure-smoke`; those
90+
runs must not be used for throughput capacity or resource-efficiency claims.
8591
`--batch-size` independently controls the OTLP request size.
8692
Bandwidth shaping uses Linux `tc tbf` on each branch's **data** interface only
8793
(`NET_ADMIN` only on those containers), with a 32 KiB burst and 100 ms queue.

‎benchmarks/run-streaming.py‎

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,30 @@ def setup(self):
9898
# least one CPU available for it. Memory is intentionally uncapped for
9999
# every role; the harness reports actual RSS instead.
100100
required = self.generator_core_count + len(PROCESSOR_ROLES) + 1
101-
if len(cores) < required:
101+
shared_infrastructure = len(cores) < required and self.args.allow_shared_infrastructure
102+
if len(cores) < required and not shared_infrastructure:
102103
raise RuntimeError(
103104
f"dedicated placement needs {required} CPUs: {self.generator_core_count} "
104105
f"traffic-generator CPUs plus one CPU for each of {len(PROCESSOR_ROLES)} processors "
105106
"and at least one backend CPU; "
106107
f"only {len(cores)} are available"
107108
)
108-
generators = cores[:self.generator_core_count]
109-
component_cores = dict(zip(PROCESSOR_ROLES, cores[self.generator_core_count:self.generator_core_count + len(PROCESSOR_ROLES)]))
110-
backend_cores = cores[self.generator_core_count + len(PROCESSOR_ROLES):]
109+
if shared_infrastructure:
110+
if len(cores) < len(PROCESSOR_ROLES):
111+
raise RuntimeError(
112+
f"shared-infrastructure smoke placement still needs {len(PROCESSOR_ROLES)} CPUs "
113+
f"for distinct processor assignments; only {len(cores)} are available"
114+
)
115+
# Correctness smoke mode for small CI runners. The four evaluated
116+
# processors remain distinct, while generator/backend infrastructure
117+
# may overlap them. Results from this placement are not capacity data.
118+
generators = cores[:min(self.generator_core_count, len(cores))]
119+
component_cores = dict(zip(PROCESSOR_ROLES, cores[:len(PROCESSOR_ROLES)]))
120+
backend_cores = cores
121+
else:
122+
generators = cores[:self.generator_core_count]
123+
component_cores = dict(zip(PROCESSOR_ROLES, cores[self.generator_core_count:self.generator_core_count + len(PROCESSOR_ROLES)]))
124+
backend_cores = cores[self.generator_core_count + len(PROCESSOR_ROLES):]
111125
for suffix in ("data", "control"):
112126
network = self.prefix + "-" + suffix
113127
self.command("network", "create", "--internal", network)
@@ -191,6 +205,7 @@ def generator_ready():
191205
"warmup_seconds": self.args.warmup, "observation_seconds": self.observation_seconds,
192206
"generator_cores": generators, "component_cores": component_cores,
193207
"backend_cores": backend_cores,
208+
"placement": "shared-infrastructure-smoke" if shared_infrastructure else "exclusive-capacity",
194209
"measurement_clock": "CLOCK_MONOTONIC, shared host kernel", "max_source_skew_windows": 1024, "pdata_channel_capacity": 8, "exporter_max_in_flight": 1,
195210
"transport": "standard OTLP/HTTP protobuf, uncompressed, persistent connections",
196211
"data_interfaces": self.data_ifaces,
@@ -461,6 +476,8 @@ def main():
461476
help="target signals/s per source to sweep using OTAP's traffic_generator receiver")
462477
parser.add_argument("--generator-cores", type=int, default=4,
463478
help="OTAP traffic_generator pipeline workers per source; each measured processor gets one dedicated CPU and the backend gets all remaining CPUs")
479+
parser.add_argument("--allow-shared-infrastructure", action="store_true",
480+
help="CI correctness smoke mode: keep processors on distinct CPUs but allow generator/backend overlap; results are not capacity measurements")
464481
parser.add_argument("--profile-cpu", action="store_true", help="exclusive synchronous processor thread CPU scopes")
465482
parser.add_argument("--account-cpu", action="store_true", help="match CPU/input boundaries with warmup and final drains; implied by --profile-cpu")
466483
parser.add_argument("--perf-command", default="", help="optional host sampler, e.g. 'sudo -n perf'; records four worker processes")

0 commit comments

Comments
 (0)