Skip to content

perf lab: freeze the canonical IL2CPP profile and add a shipping-fidelity player #506

Description

Part of #500.

Question

Can every published result prove its effective IL2CPP configuration, and does a minimal stripped consumer preserve supported behavior without relying on test assemblies or accidental AOT roots?

Mechanism

Build settings, stripping roots, symbols, native toolchains, and cached products change generic sharing, code layout, first-touch work, binary size, and throughput. The current test player is needed for discovery, but it is not a shipping-size or stripping oracle. The canonical profile now pins OptimizeSpeed; generated configuration logs and configured, prebuild, and postbuild evidence record the effective mode. Remaining provenance and campaign factors are tracked below.

Contract

Maintain two separate profiles:

  • Canonical verdict player: pinned Windows x64 Standalone IL2CPP Release, .NET Standard 2.1, with the test infrastructure required by the benchmark.
  • Shipping-fidelity player: a minimal consumer with no test assemblies, production-compatible stripping, and explicit AOT roots.

Never substitute one profile's result for the other. Preserve Unity 2021.3 support, the public API, all message kinds, private and nested message support, untyped dispatch, zero-allocation warm dispatch, and current ordering, mutation, reset, reentrancy, exception, diagnostics, and reclamation behavior.

Factors and workloads

  • Unity 2021.3 and the current pinned Unity line.
  • Clean and incremental builds as separate factors.
  • Test player versus shipping-fidelity player.
  • Every supported non-Disabled stripping level, including Minimal, Low, Medium, and High where present.
  • Class and readonly-struct messages; public, private, and nested types.
  • Typed and untyped dispatch.
  • 1, 16, 256, and 1,000 closed message shapes.
  • Cold startup, first registration, first dispatch, warm dispatch, trim, player size, and build time.

Record architecture, backend, API compatibility, IL2CPP compiler configuration and code-generation mode, stripping, exceptions, stack traces, Development/debug/profiler/deep-profile flags, assertions, incremental GC, test-assembly inclusion, editor/compiler/linker versions, native flags, symbols, and cache state.

Primary response

Exact conformance against a versioned machine-readable profile identified by a SHA-256 hash.

Independent unit

One clean IL2CPP build and its resulting player. Repeated launches of one player are nested observations.

Effect threshold

Profile acceptance is exact: no missing, ambiguous, or mismatched required settings, and complete shipping-player behavioral coverage. A rate or latency difference beyond 3%, or player-size difference beyond 1%, prevents treating the two harnesses as interchangeable until explained.

RED proof

  • Toggle each pinned setting and prove conformance fails closed.
  • Include test assemblies in the shipping player and prove validation rejects it.
  • Remove an AOT root and prove a private, nested, or untyped shipping scenario fails.
  • Reuse incremental output where a clean build is required and prove provenance validation fails.

GREEN suites

Pass focused profile-schema tests, generated-host tests, shipping-player smoke tests, typed and untyped scenarios, public-surface checks, allocation coverage, and Standalone IL2CPP runs on Unity 2021.3 and the current line.

Stop rule

Do not publish size, stripping, cold-start, or AOT-root claims if the effective profile cannot be reconstructed or the shipping player relies on test assemblies. Do not compare binaries whose profile hashes differ outside the preregistered factor.

Immutable evidence

Retain source/tree/profile/player hashes, package lock, BuildReport, effective settings, editor and toolchain versions, clean-build declaration, generated C++ and symbol indexes, player size, logs, and shipping smoke result. Store large sealed bundles as immutable GitHub prereleases using the campaign evidence schema.

Dependencies

Implementation can start immediately. Evidence acceptance depends on #508. This task blocks confirmatory claims in #501 through #505.

Completion checklist

  • Add and validate the canonical profile specification.
  • Pin and log effective IL2CPP code generation.
  • Add the minimal shipping-fidelity player.
  • Prove setting drift and accidental test inclusion fail closed.
  • Prove stripping/AOT behavior for every supported message shape.
  • Run clean builds on Unity 2021.3 and the current line.
  • Retain content-addressed build and result evidence.
  • Link the completed protocol from perf: calibrate the IL2CPP measurement system and attribute dispatch cost #500 and PLAN.md.

Profile version integrity in PR #552

PR #552, source 3e67087da13cf3d191a739d4342d204141de24c5, binds every configuration, build-options, and runtime evidence file to the exact Unity version requested by the runner. Previously, a non-empty version from another editor passed validation if its settings and profile hash matched. A red test demonstrated acceptance of 2021.3.45f1 evidence for a requested 6000.3.16f1 run.

The validator now requires ExpectedUnityVersion for evidence, and all seven runner call sites pass it. The three evidence kinds reject version, case, and whitespace drift and missing expectations. An AST guard protects every caller. The focused PowerShell suite and all 1,269 script tests pass locally. No editor version, native build setting, test filter, or benchmark window changes.

All PR checks pass at the same source: CI, four-version Unity matrix, IL2CPP performance, and devcontainer. The internal and comparison IL2CPP artifacts (10006223200, 10006503574) verify against archive SHA-256 199e3f71df0a0755271e7ea152daad35050d4be63fb4feec35816e0f02d10a62 and 7850d00239c51634948190215a33e04555be2403b804f57fd8c18f50ce5acba0. The production validator accepts all ten actual configuration/build/runtime evidence files with expected editor 6000.5.2f1 and canonical profile hash e1e525d1a80eb4dbd8e547853224e3175187e1050f014423116d4bb6f20a4ac2. These remain ordinary expiring CI artifacts. This completes the version-binding defect; full profile/toolchain/cache provenance, stripping coverage, and durable campaign evidence remain open.

Build cache provenance in PR #554

PR #554, source 5afd1aabc2470d8bcf721f66a9a9f28a10d2e818, records build-options evidence schema 2. The generated editor observes Library, Bee, Il2cppBuildCache, and player-output directory state immediately before the build. Final BuildReport options determine whether the player used CleanBuildCache. A warm Library therefore cannot be mistaken for an incremental player build, or a clean player option for a fresh project.

The validator rejects absent or contradictory provenance, stale player output, and incremental evidence under the reviewed clean profile. Both test-player and shipping-player paths share the observer. Profile hashes, Unity settings, cache reuse, test filters, and build counts remain unchanged. The added work is four bounded directory probes per build.

The old validator accepted missing provenance in the red fixture. The new profile suite tests the actual generated C# observer with both LF and CRLF source. Profile, shipping, generated-host, and all 1,273 script tests pass locally. Independent implementation review is clear. The internal IL2CPP job passes at this source with all 202 prior outcomes unchanged. Artifact 10023665143 matches GitHub archive SHA-256 bc544bad4e379cfbbff45979ab171c29e11e1d92a5f7e13e021443fcd022fa6a. The current production validator accepts all five actual profile files for Unity 6000.5.2f1. Build-options schema 2 records clean, populated Library and Bee, missing Il2cppBuildCache, and empty player output. The canonical profile hash remains e1e525d1a80eb4dbd8e547853224e3175187e1050f014423116d4bb6f20a4ac2. This artifact contains text evidence; binary hashes do not prove retained native payloads. The complete Unity matrix and both IL2CPP performance jobs now pass. Comparison artifact 10024960291 matches archive SHA-256 8ce8d18bbcfb60947dbb978fc74c8935acb79633075acfc6c06b708899541aea. Independent review verifies all ten actual profile stages across the two performance players with the current validator and unchanged canonical/CPU profiles. Both schema-2 observations agree. Shipping was skipped in the ordinary correctness jobs, so this does not establish new shipping-player acceptance. An actual preregistered incremental experiment, native-output retention, and independent remote restoration remain open.

Checklist evidence audit

The four checked mechanisms are implemented in the canonical profile, generated runner, shipping player, and profile/shipping validation tests. The current profile pins OptimizeSpeed, including Unity 2021 compatibility. Retained native configured and postbuild evidence from artifact 10006223200 records that mode for Unity 6000.5.2f1 and canonical hash e1e525d1a80eb4dbd8e547853224e3175187e1050f014423116d4bb6f20a4ac2; its retained verification hashes were independently recomputed. Current-source script CI passes on Windows, macOS, and Linux, including per-setting drift and accidental test-inclusion rejection. These completed mechanisms do not establish every stripping/message-shape factor, complete native/toolchain provenance, or durable retention. Those unchecked acceptance requirements remain open.

Native build-input retention in PR #555

PR #555, source fc3927cf63f7061b01b8808cf3aa2a6b1fdcc930, adds bounded capture of the actual build-log-selected Bee player graph and input JSON. Cold generator and backend identities must agree. Cached backend-only builds retain the matching JSON companions. The binary DAG is hashed. Log-referenced response files are retained as scanned text.

The source manifest binds original file hashes to the profile, requested editor, and build log. The existing final artifact scan records retained-byte hashes in a separate acceptance manifest. It removes reachable stale acceptance on inventory failure, validates every group before publication, and rolls back acceptance files after a write failure. Missing, ambiguous, empty, linked, oversized, and unsafe inputs fail closed. Capture runs inside existing profiled builds; it adds no Unity launch or timing window.

All 421 redactor tests and the profile suite pass locally. Negative fixtures reproduce stale-manifest failures before the fix. A six-log audit covers actual historical cold and cached build selection; historical input bytes were absent, so it does not prove successful native capture. Independent review is clear. The final native performance run is pending.

The retained response scope is explicitly build-log-references-only. Actual CI capture acceptance, transitive response closure, native executable versions and payload retention, the full stripping matrix, and independent immutable restoration remain open.

Native acceptance investigation

The earlier PR-source internal job 101828680328 passes all 202 tests and captures the logged Bee DAG. Final artifact validation rejects that DAG with the generic encoded-data/format-control warning and correctly blocks upload. License return and lock cleanup pass. The exact Windows rejection category is still unknown.

Two real local macOS Bee files pass structural inspection and safe redaction. They do not reproduce the Windows failure. A reviewed diagnostic change adds only fixed reason codes and byte size, with no acceptance-rule relaxation or exposure of offending values. All 1,298 script tests pass. This native artifact rejection must be resolved before the retention increment is accepted.

Resolution: format-control neutralization (PR #555, commits caca299 and 56143fc)

The diagnostic head named the category: Playereb61d75c.dag.json was refused with scalar-format-control, so a decoded JSON scalar held a literal Unicode format-control character. After literal scalars were made visible, the next run still refused with unsafe-structured-data, which narrowed to two remaining sources: a structured scalar beginning with a byte-order mark that the offset-0 carve-out preserved, and escape text that the serialized-shadow decoder resolves back into an invisible character.

Redaction now rewrites the whole class into visible [cf:xxxx] markers: literal format-control characters and lone surrogates, JSON \uXXXX escape runs with valid surrogate pairs preserved verbatim, and XML numeric entity chains, each counted as scalar-format-control. The byte-order-mark carve-out now applies only at document level. Encoded-Cf shadows, control-character keys, and structural defects still refuse, so no acceptance rule was relaxed. Two vector rows moved from refusal to exact-byte acceptance and their raw sources also block immutable sealing. The JS budget history entry 087 records the reviewed raise to 24060.

CI acceptance at 56143fc3 (run 34160405988): all 46 checks pass. The internal perf leg redacted the exact previously rejected file (Playereb61d75c.dag.json: scalar-format-control) and uploaded perf-6000.5.2f1-standalone-internal.zip (198,665 bytes); the comparisons leg and the performance aggregate gate pass. Local verification: npm 1298/1298, validate:all, spelling, and the budget gate. Timing against the merged-main baseline keeps editor Unity execution within noise (126-146s versus 126-150s); the perf redaction phase grows about 10 seconds per perf job from scanning the newly retained graph and input files.

Native upload is unblocked; actual retained-artifact identity checks, transitive response closure, the stripping matrix, and independent immutable restoration remain open.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions