feat: per-test engine payload sizes (SSZ + snappy + BAL)#236
Merged
Conversation
Contributor
Author
|
The failure in CI is at So CI can never pass IIUC? |
e231a70 to
0791af1
Compare
Member
Yes, fixing it here: #237 . I'll update this branch once it's on master. |
Brings in ethpandaops#237 (fix CI for PRs from forks) so this PR's checks run against the updated workflow.
Replaces the three flat scalars (payload_size_bytes, payload_size_bytes_snappy, bal_size_bytes) on SuiteTest with a single nested payload_sizes container keyed by step (setup/test/cleanup), each holding aligned per-newPayload arrays. This lets multi-block tests be inspected block-by-block instead of collapsing into one sum, and makes room for non-test steps that happen to contain newPayloads. Field names match what the bytes actually are: ssz_full (full SSZ- encoded ExecutionPayload with BAL inline), ssz_bal (just the SSZ-encoded BlockAccessList sub-field), ssz_full_snappy (snappy of ssz_full), json_full (canonical JSON of the same ExecutionPayload), json_bal (BAL hex string length as it appears in JSON, no quotes). The two JSON fields are new — they let you compare SSZ vs JSON wire size for the same content. UI side: page-level PayloadSizesSection keeps showing one row per test by summing the test-step ssz_* arrays into totals. The test-details modal gets a new per-step table with one row per newPayload (#1, #2, ...) and a totals row when n>1, with BAL/Snappy/JSON-BAL annotated by % of their container. This is a breaking change to summary.json — old summaries parse (payload_sizes is omitempty), but the previous scalar fields are gone.
Tests-tab table on the suite-details page gains a segmented view-mode switcher (General / Payload sizes (SSZ) / Payload sizes (JSON)) so the existing Steps column can swap out for payload-size data. The standalone PayloadSizesSection table goes away — the chart stays as the at-a-glance overview, and per-test totals now live inline in the main table. Sort: every payload column (including #, sorting by original index) acts as a sortable header. Direction cycles desc → asc → off. Sort column + direction persist in the URL via psort / psortDir, alongside testView, so a link reproduces the table state exactly. JSON mode columns: JSON, JSON BAL, BAL %. SSZ mode keeps the existing five columns. Sort state survives mode switches; a column not visible in the current mode just doesn't show an active arrow but still applies under the hood until the user re-sorts. PayloadSortCol + isPayloadSortCol moved to a sibling payloadSort.ts so TestFilesList.tsx exports only the component (keeps Fast Refresh happy).
…oltip - Always shown (drop the chevron collapse). - Vertical bars with Test # on the X axis (categorical, formatted as #N) and bytes on the Y axis. Replaces the long-test-name horizontal axis that was unreadable for thousands of tests. - Order toggle: Test # (default, monotonic X axis) or Size (descending). Local state — the URL doesn't need it. - Tooltip matches the run-detail resource-usage charts: bold `Test #N`, decomposed name below in muted small text (respects the global useNameDisplayMode preference), one row per series with the series color dot + formatted bytes. `extraCssText` + `confine` prevent overflow. - Dark-mode theming: textColor/axisLineColor/splitLineColor pattern copied from ResourceUsageCharts so legends, axis labels, and data- zoom controls aren't grey-on-grey. Local useDarkMode hook watches the <html> class so the chart re-themes live.
Clicking any column in the bar chart on the suite-details page now
opens the same modal that table-row clicks open. SuiteDetailPage wires
PayloadSizesSection.onTestClick to the existing handleDetailChange, so
the URL gets the same ?detail=<N> param and TestFilesList's modal
takes over from there.
The handler hooks the lower-level Zrender canvas (instead of ECharts'
default bar-only click) and converts the cursor pixel back to an
X-axis category via convertFromPixel, so clicks in the gaps above
short bars or between stacked segments resolve to the column the user
"meant" rather than getting eaten. containPixel('grid', ...) gates out
clicks on the legend, axis labels, and data-zoom slider.
categories / indexToName moved to useMemo above the new effect to keep
all hooks unconditionally called.
Adds a single search bar at the top of the Tests tab that drives every downstream section (FacetPanel, TestHeatmap, OpcodeHeatmap, PayloadSizesSection, the tests table). Sticky to the viewport on scroll, using the same Tailwind pattern and FilterInput component as the run-detail page. Lives above FacetPanel. Now that one search box covers everything, the inline ones in TestHeatmap, OpcodeHeatmap, and the tests-tab TestFilesList are gone: - TestHeatmap: input + regex toggle removed outright (suite-only caller); chip-click on test names still toggles terms in the global query via onSearchChange. - OpcodeHeatmap: passed the existing hideSearchInput prop. - TestFilesList: new hideSearchInput prop; tests-tab passes it, pre-run-steps tab (no global bar) keeps its inline input. PayloadSizesSection becomes fully controlled: its internal query state and inline filter input are removed, replaced by a searchQuery prop driven by the page's ?q= param. The "N of M matching" count stays next to the order toggle when the search is active.
Previously capped the initial dataZoom window to ~200 bars, which hid most of the dataset on first paint and made the slider mandatory. Show all bars by default; the slider is still there for narrowing in.
Adds cursor-pointer to the chart Order toggle (Test # / Size) and the tests-table view-mode toggle (General / Payload sizes (SSZ) / Payload sizes (JSON)) so it's visually clear they're clickable.
Moves the Non-BAL / BAL / Snappy legend below the data-zoom slider instead of stacking it above the chart. Reworks the grid + slider geometry so the bottom strip reads cleanly: X-axis labels → small gap → slider → small gap → legend. Chart height bumped to 400 to fit the extra row.
Adds a psOrder search param ('index' default | 'size') so a link
reproduces the chart's bar order along with testView and psort/psortDir.
SuiteDetailPage threads psOrder through every URL-preserving handler
(pagination, detail-open, opcode-sort, test-view, payload-sort) so
those interactions don't drop it. PayloadSizesSection's order toggle
is now a controlled/uncontrolled prop pair, falling back to local
state when no parent callback is wired.
…-detail UX cleanup PayloadSizesSection gets an Encoding toggle (SSZ default | JSON) next to the Order toggle. SSZ keeps the existing Non-BAL + BAL stacked + Snappy layout; JSON drops Snappy (no compressed JSON variant) and shows Non-BAL + BAL stacked in the same palette so the BAL share reads identically across encodings. The size sort, the max-payload-size header annotation, the legend, and the chart series all swap with the active encoding via a fullOf(r) helper. Persisted in the URL as psEncoding (default 'ssz' stays clean). Threaded through every URL-preserving handler in SuiteDetailPage (pagination, detail-open, opcode-sort, test-view, payload-sort, ps-order) so flipping any of those doesn't reset the encoding. Also in this batch (suite-details Tests tab): - Drop the collapsible OpcodeHeatmapSection wrapper. <OpcodeHeatmap /> now renders inline like on the run-detail page; outer card and internal padding restored so it doesn't look unwrapped. - File content in the test-details modal: min-w-0 on every flex ancestor of the <pre>, max-h-[60vh] + overflow-auto on the pre. Fixes a Chrome bug where long single-line JSON-RPC payloads blew up the flex column and made the content disappear off-screen.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
executionPayloadbyte sizes once per suite (suite-level invariant — identical across all clients): SSZ-encoded length, snappy-compressed length, and inlineBlockAccessList(BAL) length. NewSuiteTestfields land insummary.jsonwithomitempty, so existing suites parse unchanged.SuiteDetailPage: ECharts horizontal bar chart (Non-BAL + BAL stacked → uncompressed total, plus a separate Snappy bar), single search input that filters chart + table together, sortable + paginated table beneath. Default sort: uncompressed desc.enginev1(github.com/OffchainLabs/prysm/v6, pinned to a commit on thebalbranch) for SSZ marshaling — same encoder Prysm uses on mainnet — so the numbers reflect what a CL would actually gossip. Backfill happens automatically on the next run that hits an existing suite (MergePayloadSizesmirrors themergeOpcodeDatapattern atpkg/executor/suite.go); a one-shot CLI for legacy suites is intentionally out of scope here.Test plan
EestToPrysmPayloadacross V1 Bellatrix → V6 Gloas (10 tests inpkg/eest/)ExtractNewPayloadLines/ComputePayloadSizes/MergePayloadSizesunit tests (10 tests inpkg/executor/)CreateSuiteOutputtest: new-suite path writes the three fields; merge path backfills them on a second runsummary.jsonwithout the new fields)gofmt -lclean,go vetcleantsc --noEmitclean; UIvite buildsucceedsgpgmesystem library on the build host, pre-existing setup; not specific to this PR)Notes for reviewers
ExecutionPayloadElectrapayload type (Electra-specific data travels in the separateexecutionRequestsengine API param, not inside the payload). Comment documents the rationale.SlotNumberfield present oneest.ExecutionPayloadis not forwarded to Prysm because Prysm's currentExecutionPayloadGloasstruct does not define that field. Documented inline.docker/podman/podman-checkpoint-restoreCI jobs are expected to fail on fork PRs:action.yaml:69hard-codesgit clone https://github.com/ethpandaops/benchmarkoor.gitand then checks out the PR head SHA, which only exists on the fork. This is a pre-existing workflow limitation, not a regression from this PR.