Skip to content

[None][fix] Align perf launcher with pytest shard - #17134

Open
chienchunhung wants to merge 5 commits into
NVIDIA:mainfrom
chienchunhung:codex/perf-pytest-shard-alignment
Open

[None][fix] Align perf launcher with pytest shard#17134
chienchunhung wants to merge 5 commits into
NVIDIA:mainfrom
chienchunhung:codex/perf-pytest-shard-alignment

Conversation

@chienchunhung

@chienchunhung chienchunhung commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • make the multi-node perf launcher select the same duration-balanced test as pytest-split
  • use that selected test consistently for its YAML configuration and artifact output directory
  • add focused regression coverage using the GB300 Kimi/DeepSeek stage ordering and durations

Root cause

The launcher interpreted --split-group N as the Nth line in the test list. Pytest instead applies pytest-split's least_duration algorithm using .test_durations, so a shard can select a different test from the raw Nth line.

That allowed the launcher to configure servers and the output directory for one test while pytest executed another test. During the NVBUG#6481034 investigation, this caused the targeted Kimi shard to write and collect artifacts under a different test identity.

Fix

Parse the pytest-split options from the generated pytestCommand, load the same duration data, and mirror the installed pytest-split LeastDurationAlgorithm. The launcher now validates that its group matches pytest's group and requires one selected test for each multi-node perf shard. A contract unit test compares every selected group with the installed plugin across skewed, equal, missing, irrelevant, and empty duration data, so dependency upgrades fail visibly if the behavior changes.

This PR contains no transfer tracing, runtime product changes, KV-cache fraction changes, timeout changes, test configuration changes, or waiver changes.

Validation

  • pre-commit run --files jenkins/scripts/perf/submit.py tests/unittest/scripts/test_perf_submit.py
  • python -m py_compile jenkins/scripts/perf/submit.py tests/unittest/scripts/test_perf_submit.py
  • python -m pytest -q --confcutdir=tests/unittest/scripts tests/unittest/scripts/test_perf_submit.py -k ci_submit — 8 passed against unpinned pytest-split 0.11.0
  • PR [https://nvbugs/6481034][test] Trace Kimi gen-only KV transfer timeout #16918 targeted validation selected the intended Kimi shard and collected its dedicated artifacts after this alignment was applied

Related investigation: NVBUG#6481034 and #16918.

Dev Engineer Review

  • Added pytest-split duration-balanced shard selection in jenkins/scripts/perf/submit.py.
  • The implementation loads .test_durations, validates split-group consistency, and requires one selected test per shard.
  • The selected test line drives test-name parsing and artifact output paths.
  • No configuration files or test-list files were changed.
  • Validation included pre-commit checks, Python compilation, targeted pytest-split tests, and Kimi shard validation.

QA Engineer Review

  • Added tests for least-duration shard selection, installed pytest-split compatibility, invalid split and group values, test-list comments, split-group disagreement, and missing duration files.
  • No corresponding entries were added to tests/integration/test_lists/test-db/ or qa/.
  • Verdict: needs follow-up if CI test-list coverage is required.

@chienchunhung chienchunhung changed the title [NVBUG-6481034][fix] Align perf launcher with pytest shard [None][fix] Align perf launcher with pytest shard Jul 31, 2026
@chienchunhung

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63099 [ run ] triggered by Bot. Commit: 05880f6 Link to invocation

@chienchunhung

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@chienchunhung
chienchunhung marked this pull request as ready for review July 31, 2026 23:19
@chienchunhung
chienchunhung requested review from a team as code owners July 31, 2026 23:19
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The performance launcher uses pytest-split duration data to select one test for each split group. It validates split settings and reuses the selected test line for test-name and output-directory generation. Tests compare selection with pytest’s algorithm and cover invalid inputs.

Changes

Pytest-split test selection

Layer / File(s) Summary
Duration-balanced test selection
jenkins/scripts/perf/submit.py
The launcher parses pytest options, loads duration data, reproduces least-duration grouping, validates group consistency, and selects exactly one test line.
Launcher selection integration
jenkins/scripts/perf/submit.py
main reads the script prefix once, passes the selected line to test-name parsing, derives the output directory from that line, and updates CLI help.
Selection behavior validation
tests/unittest/scripts/test_perf_submit.py
Tests compare CI selection with LeastDurationAlgorithm and cover invalid split values, comments and blank lines, group mismatches, and missing duration files.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant main
  participant select_test_case_line
  participant pytestCommand
  participant durationFile
  participant testList
  main->>select_test_case_line: provide script prefix and split group
  select_test_case_line->>pytestCommand: parse split and duration options
  select_test_case_line->>durationFile: load test durations
  select_test_case_line->>testList: parse candidate tests
  select_test_case_line-->>main: return one selected test line
  main->>parse_test_case_name: reuse selected line
Loading

Possibly related PRs

Suggested reviewers: bowenfu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the repository format and clearly describes alignment of the performance launcher with pytest shard selection.
Description check ✅ Passed The description clearly explains the root cause, fix, scope, and validation, with detailed test coverage despite using different section headings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
jenkins/scripts/perf/submit.py (2)

77-86: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider sharing the pytestCommand line lookup.

_pytest_command_tokens and get_pytest_commands (Line 536) each locate the export pytestCommand= line with their own next(...) expression. Extract one helper that returns the line. Both call sites then stay in sync if the prefix format changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jenkins/scripts/perf/submit.py` around lines 77 - 86, Extract the shared
pytestCommand export-line lookup from _pytest_command_tokens and
get_pytest_commands into a helper that returns the matching line or an empty
value. Update both functions to use this helper, preserving their existing
parsing and fallback behavior.

211-228: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider removing the second selection path.

main always passes selected_line, so the split_group branch at Lines 221-226 is unused in the CI flow. Two selection paths for one concept can diverge after a later change. Make selected_line required, or have this fallback call select_test_case_line instead of re-implementing positional selection.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jenkins/scripts/perf/submit.py` around lines 211 - 228, The
parse_test_case_name selection logic duplicates positional test selection even
though main always supplies selected_line. Make selected_line required and
remove the test_list_path, split_group, and fallback branch, or delegate
fallback selection to select_test_case_line instead of indexing lines directly;
preserve the existing selected-line parsing behavior.
tests/unittest/scripts/test_perf_submit.py (1)

113-145: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test coverage summary

Changed test functions:

  1. test_ci_submit_selects_same_least_duration_shard_as_pytest_split (added) — verifies least-duration group selection and the --durations-path fallback to llm_src.
  2. test_ci_submit_rejects_split_group_disagreement (added) — verifies the --group consistency check.

Test list registration: these are unit tests under tests/unittest/scripts/, not integration tests, so no entry under tests/integration/test_lists/test-db/ or tests/integration/test_lists/qa/ is required. Confirm that tests/unittest/scripts/ is already collected by an existing L0 unit-test stage.

Verdict: sufficient for the primary fix, with these gaps worth closing:

  • Equal durations. With --splits 4 and four tests, every group receives one test, so the tie-break order at submit.py Line 155 is not exercised. Add a case with two identical durations.
  • len(selected) != 1. Add a case where one group receives two tests, and assert the "requires exactly one test" ValueError.
  • Missing --splits/--group. Add a case that asserts the positional fallback still returns lines[split_group - 1].

As per path instructions: "Always produce a test coverage summary, even if no issues are found."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/scripts/test_perf_submit.py` around lines 113 - 145, Extend
tests around select_test_case_line and
test_ci_submit_selects_same_least_duration_shard_as_pytest_split to cover
equal-duration tie-breaking, asserting the expected deterministic group
selection. Add a case where one group contains multiple tests and assert the
exact-one-test ValueError. Add a case without --splits or --group and verify
positional fallback returns lines[split_group - 1]. Confirm the existing L0
unit-test collection includes tests/unittest/scripts/.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@jenkins/scripts/perf/submit.py`:
- Around line 107-131: Update _load_pytest_split_durations so a missing
durations file is not silently converted to an empty dictionary: emit a clear
warning containing durations_path, or propagate an error when split_group > 0.
Preserve normal loading and validation for existing files, and ensure callers
can identify that duration-based selection is unavailable.
- Around line 134-165: Pin pytest-split to exactly version 0.10.0 in
requirements-dev.txt, preserving the existing dependency entry while adding the
explicit version constraint so CI uses the algorithm matched by
_select_least_duration_group.

---

Nitpick comments:
In `@jenkins/scripts/perf/submit.py`:
- Around line 77-86: Extract the shared pytestCommand export-line lookup from
_pytest_command_tokens and get_pytest_commands into a helper that returns the
matching line or an empty value. Update both functions to use this helper,
preserving their existing parsing and fallback behavior.
- Around line 211-228: The parse_test_case_name selection logic duplicates
positional test selection even though main always supplies selected_line. Make
selected_line required and remove the test_list_path, split_group, and fallback
branch, or delegate fallback selection to select_test_case_line instead of
indexing lines directly; preserve the existing selected-line parsing behavior.

In `@tests/unittest/scripts/test_perf_submit.py`:
- Around line 113-145: Extend tests around select_test_case_line and
test_ci_submit_selects_same_least_duration_shard_as_pytest_split to cover
equal-duration tie-breaking, asserting the expected deterministic group
selection. Add a case where one group contains multiple tests and assert the
exact-one-test ValueError. Add a case without --splits or --group and verify
positional fallback returns lines[split_group - 1]. Confirm the existing L0
unit-test collection includes tests/unittest/scripts/.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 272c70dc-8d52-4c8a-aac5-c830373da971

📥 Commits

Reviewing files that changed from the base of the PR and between 376d219 and 7a2e0ec.

📒 Files selected for processing (2)
  • jenkins/scripts/perf/submit.py
  • tests/unittest/scripts/test_perf_submit.py

Comment thread jenkins/scripts/perf/submit.py
Comment thread jenkins/scripts/perf/submit.py
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63099 [ run ] completed with state FAILURE. Commit: 05880f6
/LLM/main/L0_MergeRequest_PR pipeline #51190 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@chienchunhung
chienchunhung requested a review from a team as a code owner August 2, 2026 01:27
@chienchunhung

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63248 [ run ] triggered by Bot. Commit: c018511 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63248 [ run ] completed with state DISABLED
Pipeline is freezed and top-1 instance is under maintenance. For urgent request, contact Yiteng Niu

Link to invocation

Signed-off-by: Chien-Chun Hung <2679986+chienchunhung@users.noreply.github.com>
Signed-off-by: Chien-Chun Hung <2679986+chienchunhung@users.noreply.github.com>
Signed-off-by: Chien-Chun Hung <2679986+chienchunhung@users.noreply.github.com>
@chienchunhung
chienchunhung force-pushed the codex/perf-pytest-shard-alignment branch from c018511 to 63f2737 Compare August 3, 2026 17:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
jenkins/scripts/perf/submit.py (2)

213-230: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider removing the duplicate selection path in parse_test_case_name.

parse_test_case_name now holds a second selection mechanism. main always passes selected_line, so the else branch and the split_group bounds check are unreachable in production. That branch duplicates the index-based fallback and the bounds check of select_test_case_line, and it can drift from the duration-balanced selection.

If no caller needs the legacy path, require selected_line and drop test_list_path and split_group. Keep the change small if the unit tests still use the legacy signature.

♻️ Proposed simplification
-def parse_test_case_name(test_list_path, llm_src, split_group=0, selected_line=None):
-    """Parse the selected line of the test list.
+def parse_test_case_name(llm_src, selected_line):
+    """Parse the selected test-list line.
 
     Returns (config_yaml_path, server_name, benchmark_mode, runtime_mode).
     See the module docstring for the supported test name shapes.
     """
-    if selected_line is not None:
-        line = selected_line
-    else:
-        lines = _read_test_list_lines(test_list_path)
-        if split_group > 0:
-            if split_group > len(lines):
-                raise ValueError(
-                    f"split_group {split_group} exceeds number of tests in test list ({len(lines)})"
-                )
-            line = lines[split_group - 1]
-        else:
-            line = lines[0]
+    line = selected_line

Update the call in main accordingly:

config_yaml, server_name, benchmark_mode, runtime_mode = parse_test_case_name(
    args.llm_src,
    selected_test_line,
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jenkins/scripts/perf/submit.py` around lines 213 - 230, Remove the
unreachable legacy selection path from parse_test_case_name by requiring
selected_line and dropping test_list_path and split_group from its signature,
then update main to pass only args.llm_src and selected_test_line. If unit tests
still depend on the legacy signature, preserve compatibility there while keeping
production selection delegated to select_test_case_line.

136-167: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Pin pytest-split to 0.10.0. requirements-dev.txt currently leaves it unversioned, so a dependency upgrade can change shard assignment. unittest/scripts is already included in the l0_a10 CI test list.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jenkins/scripts/perf/submit.py` around lines 136 - 167, The dependency
configuration must pin pytest-split to version 0.10.0 so shard assignment
remains stable across upgrades. Update the pytest-split entry in
requirements-dev.txt, preserving the existing unittest/scripts CI coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@jenkins/scripts/perf/submit.py`:
- Around line 69-74: Update _read_test_list_lines to exclude lines whose
stripped content is a comment beginning with “#”, matching parse_test_list_lines
behavior before validating and returning the test list. Preserve filtering of
blank lines and the existing empty-list ValueError.

In `@tests/unittest/scripts/test_perf_submit.py`:
- Around line 33-38: The added functions in _FakePytestItem and the test cases
lack complete type annotations. Add -> None to _FakePytestItem.__init__ and
every added test function, and annotate each fixture parameter with its precise
fixture-provided type.
- Around line 157-183: Extend
test_ci_submit_selector_matches_installed_pytest_split to cover invalid selector
boundaries by asserting _select_least_duration_group rejects splits=0, group=0,
and group values greater than splits. Use the test’s existing lines and
durations, and verify the expected validation exception for each case.
- Around line 18-23: Pin the pytest-split dependency to version 0.10.0 in
requirements-dev.txt, ensuring CI resolves that exact version rather than
relying on the attribution entry or an unbounded dependency.
- Around line 122-223: Add focused tests for _select_least_duration_group
covering splits less than 1, group less than 1, and group greater than splits,
asserting each raises the expected validation error. Keep these cases direct
against the helper so they do not rely on select_test_case_line or get masked by
split-group disagreement handling.

---

Nitpick comments:
In `@jenkins/scripts/perf/submit.py`:
- Around line 213-230: Remove the unreachable legacy selection path from
parse_test_case_name by requiring selected_line and dropping test_list_path and
split_group from its signature, then update main to pass only args.llm_src and
selected_test_line. If unit tests still depend on the legacy signature, preserve
compatibility there while keeping production selection delegated to
select_test_case_line.
- Around line 136-167: The dependency configuration must pin pytest-split to
version 0.10.0 so shard assignment remains stable across upgrades. Update the
pytest-split entry in requirements-dev.txt, preserving the existing
unittest/scripts CI coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9fddf316-e66e-449e-979b-caa10896fd55

📥 Commits

Reviewing files that changed from the base of the PR and between c018511 and 63f2737.

📒 Files selected for processing (2)
  • jenkins/scripts/perf/submit.py
  • tests/unittest/scripts/test_perf_submit.py

Comment thread jenkins/scripts/perf/submit.py
Comment thread tests/unittest/scripts/test_perf_submit.py
Comment thread tests/unittest/scripts/test_perf_submit.py
Comment thread tests/unittest/scripts/test_perf_submit.py Outdated
Comment thread tests/unittest/scripts/test_perf_submit.py Outdated

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

Signed-off-by: Chien-Chun Hung <2679986+chienchunhung@users.noreply.github.com>

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63517 [ run ] triggered by Bot. Commit: 9429527 Link to invocation

Signed-off-by: Chien-Chun Hung <2679986+chienchunhung@users.noreply.github.com>

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63523 [ run ] triggered by Bot. Commit: 79f24c6 Link to invocation

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
jenkins/scripts/perf/submit.py (1)

174-186: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Reject partial pytest-split configuration.

When only one of --splits or --group is present, raise an error. Use positional selection only when both options are absent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jenkins/scripts/perf/submit.py` around lines 174 - 186, Update
select_test_case_line so it raises a ValueError when exactly one of
splits_option or group_option is present; only use positional selection when
both --splits and --group are absent, while preserving the existing behavior
when both are provided.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@jenkins/scripts/perf/submit.py`:
- Around line 174-186: Update select_test_case_line so it raises a ValueError
when exactly one of splits_option or group_option is present; only use
positional selection when both --splits and --group are absent, while preserving
the existing behavior when both are provided.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: dd219d68-ffa4-455e-8ad6-6059591a6beb

📥 Commits

Reviewing files that changed from the base of the PR and between 9429527 and 79f24c6.

📒 Files selected for processing (1)
  • jenkins/scripts/perf/submit.py

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63517 [ run ] completed with state ABORTED. Commit: 9429527

Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63526 [ run ] triggered by Bot. Commit: 79f24c6 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63523 [ run ] completed with state ABORTED. Commit: 79f24c6

Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63526 [ run ] completed with state SUCCESS. Commit: 79f24c6
/LLM/main/L0_MergeRequest_PR pipeline #51492 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants