Skip to content

Commit 6342f9e

Browse files
committed
Trim sweep-enabled concurrency to min instead of max
For PRs labeled `sweep-enabled`, `--trim-conc` now collapses each parallelism config to its lowest concurrency point instead of its highest. Validation runs that only need a smoke point are cheaper at the bottom of the curve and free up shared-cluster time for full-sweep work elsewhere. Updated the conflicting-labels error in `run-sweep.yml` and the matching paragraphs in `AGENTS.md` so the operator-facing wording matches the new behavior.
1 parent bb00055 commit 6342f9e

3 files changed

Lines changed: 9 additions & 9 deletions

File tree

.github/workflows/run-sweep.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
contains(github.event.pull_request.labels.*.name, 'sweep-enabled') &&
8989
contains(github.event.pull_request.labels.*.name, 'full-sweep-enabled')
9090
run: |
91-
echo "::error::PR has both 'sweep-enabled' and 'full-sweep-enabled' labels. Remove one — 'full-sweep-enabled' runs the full intermediate concurrency sweep; 'sweep-enabled' trims to max(conc) per parallelism config."
91+
echo "::error::PR has both 'sweep-enabled' and 'full-sweep-enabled' labels. Remove one — 'full-sweep-enabled' runs the full intermediate concurrency sweep; 'sweep-enabled' trims to min(conc) per parallelism config."
9292
exit 1
9393
9494
- name: Checkout code

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ Git: conventional commit messages. `[skip-sweep]` in commit message skips benchm
6161

6262
PRs do not run the sweep automatically - `run-sweep.yml` is gated on a label. Pick exactly one; setting both is rejected by the workflow's `setup` job.
6363

64-
- `sweep-enabled` - runs the sweep with `--trim-conc` (each parallelism config reduced to its single highest concurrency). Default for most PRs.
64+
- `sweep-enabled` - runs the sweep with `--trim-conc` (each parallelism config reduced to its single lowest concurrency). Default for most PRs.
6565
- `full-sweep-enabled` - runs the full intermediate concurrency sweep, identical to push-to-main. Use when intermediate points matter (e.g. a recipe change shifts the throughput/latency curve, not just its endpoints).
6666

6767
**The sweep does not trigger while the PR has merge conflicts.** Even with `sweep-enabled` / `full-sweep-enabled` applied, the `run-sweep.yml` workflow will not start until the PR cleanly merges into main — a stale claude/* or update-* branch with a `perf-changelog.yaml` conflict (the common case) will sit in NO_SWEEP / NO_SUCCESS until rebased. Resolution recipe is documented in `KLAUD_DEBUG.md §1.1`: `git merge origin/main`, then `git checkout origin/main -- perf-changelog.yaml`, then re-append the PR's own changelog entry at the tail. Don't 3-way merge `perf-changelog.yaml`; whitespace edits silently re-trigger the deletion check.
6868

69-
Push-to-main always runs the full untrimmed sweep unless `[skip-sweep]` is in the commit message. Trim logic lives in `trim_conc()` in `utils/process_changelog.py`: single-node entries are grouped by every non-`conc` field and only the highest-`conc` entry per group is kept; multi-node entries have their `conc` list collapsed to `[max(conc)]`.
69+
Push-to-main always runs the full untrimmed sweep unless `[skip-sweep]` is in the commit message. Trim logic lives in `trim_conc()` in `utils/process_changelog.py`: single-node entries are grouped by every non-`conc` field and only the lowest-`conc` entry per group is kept; multi-node entries have their `conc` list collapsed to `[min(conc)]`.
7070

7171
## Common Tasks
7272

utils/process_changelog.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,22 @@ def get_added_lines(base_ref: str, head_ref: str, filepath: str) -> str:
4242

4343

4444
def trim_conc(entries: list[dict]) -> list[dict]:
45-
"""Trim each parallelism config's concurrency sweep to its highest point.
45+
"""Trim each parallelism config's concurrency sweep to its lowest point.
4646
4747
Non-full-sweep PRs only need a single concurrency point per parallelism
4848
config to validate a change runs end-to-end, so the shared cluster stays
4949
clear. Push-to-main and ``full-sweep-enabled`` PRs skip this reduction.
5050
51-
The retained value is the maximum configured concurrency — independent of
51+
The retained value is the minimum configured concurrency — independent of
5252
the source ordering of ``conc-list`` / ``conc-start``.
5353
5454
Input comes from ``json.loads(subprocess.stdout)`` so ``conc`` is always
5555
``int`` (single-node) or ``list`` (multi-node); other single-node fields
5656
are hashable scalars.
5757
5858
- Single-node entries: group by every other field and keep only the entry
59-
with the highest ``conc`` per group.
60-
- Multi-node entries: trim the ``conc`` list in place to ``[max(conc)]``.
59+
with the lowest ``conc`` per group.
60+
- Multi-node entries: trim the ``conc`` list in place to ``[min(conc)]``.
6161
"""
6262
groups: dict[tuple, list[int]] = {}
6363
out: list[dict] = []
@@ -66,7 +66,7 @@ def trim_conc(entries: list[dict]) -> list[dict]:
6666
if entry.get("prefill") is not None:
6767
conc = entry.get("conc")
6868
if isinstance(conc, list) and len(conc) > 1:
69-
entry = {**entry, "conc": [max(conc)]}
69+
entry = {**entry, "conc": [min(conc)]}
7070
out.append(entry)
7171
continue
7272

@@ -77,7 +77,7 @@ def trim_conc(entries: list[dict]) -> list[dict]:
7777
drop: set[int] = set()
7878
for idxs in groups.values():
7979
if len(idxs) > 1:
80-
keep = max(idxs, key=lambda i: out[i]["conc"])
80+
keep = min(idxs, key=lambda i: out[i]["conc"])
8181
drop.update(i for i in idxs if i != keep)
8282
return [e for i, e in enumerate(out) if i not in drop]
8383

0 commit comments

Comments
 (0)