Benchmark Family Plugin Seam Future State¶
Related TODOs: arch-ssb-family-plugin-seam-pilot, benchmark-api-and-core-boundary-cleanup
Composition prerequisite: Core Kernel and Runtime Composition Boundary.
The plugin seam must use the selected core-kernel boundary; it must not create
benchbox.runtime or a second generic execution helper.
Decision¶
Benchmark family logic should move behind an explicit family-plugin seam before
any broad benchbox/core split. The seam is a design boundary first, not a
mechanical package move: public wrappers and the CLI keep their current user
contracts while internal family implementations converge on a shared interface.
Current Surface Classification¶
Surface |
Tier |
Current role |
|---|---|---|
Top-level wrappers such as |
|
User-facing convenience facades with direct tests. |
|
|
Public base for wrappers and orchestration helpers. |
|
|
Programmatic adapter execution hook used by CLI-adjacent tools and MCP. |
|
|
Registry-backed runtime loader for core orchestration. |
|
|
Internal compatibility module with no remaining production implementation consumers. |
Benchmark registry metadata |
|
Source of truth for benchmark identity, discovery, public/internal surface, and class-name mappings. |
Target Seam¶
A benchmark family plugin owns:
benchmark metadata fields needed for discovery;
the core benchmark class and default constructor policy;
data generation and manifest behavior for its family;
query catalog, query IDs, streams or maintenance phases when relevant;
optional DataFrame query implementations for the same family;
family-specific scale validation beyond registry defaults;
result metadata extensions that are explicitly shared through the result schema policy.
The shared runtime owns:
platform adapter execution;
result bundle construction and schema-version policy;
validation mode selection and cross-platform comparison;
lifecycle phase orchestration;
registry publication and public/internal surface filtering.
Interface Shape¶
The first interface should be small and registry-backed:
Method or field |
Purpose |
|---|---|
|
Stable registry key. |
|
Class used by the internal loader. |
|
Optional top-level wrapper facade class. |
|
Public or internal discovery visibility. |
|
Scale validation and default constructor policy. |
|
Construct a family instance without CLI imports. |
|
Declare supported generate/load/execute/maintenance phases. |
|
Family-owned result fields that are accepted by schema policy. |
This interface is piloted on SSB only. SSB is support_status: stable,
declares scale 0.01 (about 1-5 minutes, synthetic data), has
supports_streams: false, and already has
make ssb-cross-surface-equivalence-report. JoinOrder cannot produce a cheap
before/after measurement (canonical scale 1.0, licensing, no CI path). TPC-DS
streams and compliance would obscure the seam. TPC-H is runnable at 0.01 but
has supports_streams: true.
BenchmarkFamilyPlugin lives in benchbox.core.benchmark_registry. The
registry module’s FAMILY_PLUGIN_IMPORTS map points at the family object.
The catalog YAML cannot grow a new top-level key without a schema change, so
the pilot map stays next to the registry loader. The internal loader calls
plugin.create(...) when a row exists and keeps the heuristic constructor
path for every other family. SSB’s public wrapper facade is unchanged.
Extension-cost measurement (SSB-like family)¶
The metric is semantic decisions, repeated code, tests, and time. File count is not the success measure.
Before the seam¶
Adding another SSB-like family (simple OLAP, no streams, optional DataFrame) required:
Cost |
Current path |
|---|---|
Identity decisions |
|
Construction decisions |
public vs core class name, lazy vs eager export, constructor kwargs, whether the loader |
Repeated code |
wrapper method proxy; loader kwargs dict; importlib class-name heuristic |
Required tests |
wrapper facade proxy, schema/generator, contract-count update, DataFrame/cross-surface if enabled |
Contributor time |
about one focused day after the query/schema work exists, mostly deciding constructor and loader special cases |
After the SSB pilot¶
The same hypothetical next family still owns its package, wrapper facade, and registry identity. The seam removes the loader-heuristic decisions:
Cost |
After SSB plugin |
|---|---|
Identity decisions |
Unchanged registry metadata |
Construction decisions |
Implement |
Repeated code |
Wrapper facade remains (non-goal to remove). Constructor policy lives in |
Required tests |
Existing wrapper/schema tests plus the plugin contract. Contract counts stay unchanged when no new family is added |
Contributor time |
Same package and facade work; constructor/loader policy drops to the four plugin methods and one YAML row |
SSB itself is the first row: FAMILY_PLUGIN_IMPORTS["ssb"] resolves
benchbox.core.ssb.family:SSBFamily. No other family is on the seam.
Non-Goals¶
Removing top-level wrapper facades.
Making
benchbox.core.benchmark_loaderpublic.Creating a third benchmark base class.
Moving all benchmark directories in one PR.
Changing result bundle shape as part of the seam definition.
Migration Gates¶
Keep wrapper facade tests green, or add a compatibility registry row plus a migration path.
Keep registry, public discovery, top-level facade, and loader counts under a focused drift test.
Keep core API files free of concrete platform adapter imports.
Migrate
datavaultandtpcds_obtoffbenchbox.core.base_benchmark.BaseBenchmarkbefore removing that class.Land one pilot family through the seam before any package-level split.
Rejected Alternatives¶
Alternative |
Reason rejected |
|---|---|
Remove wrapper facades now |
Existing tests assert wrapper behavior and users have documented imports. |
Promote the loader as public API |
The loader has constructor heuristics and internal fallback behavior that should not become an external contract. |
Add a new base class |
This would increase base-class ambiguity instead of resolving it. |
Mechanically split |
File movement without a dependency-direction boundary would only relocate drift. |