From 92cd381392df32b04f3ef80af85f4564e5cc2892 Mon Sep 17 00:00:00 2001 From: Algent Date: Sat, 5 Sep 2026 11:34:58 +0200 Subject: [PATCH] docs: plan measured performance pass --- JAVA_MIGRATION.md | 45 +++++++++++++++++++++++++++++++++++++++ JAVA_MIGRATION_HANDOFF.md | 6 ++++++ JAVA_MIGRATION_PROFILE.md | 41 +++++++++++++++++++++++++++++++++++ docs/migration/HISTORY.md | 9 ++++++++ 4 files changed, 101 insertions(+) diff --git a/JAVA_MIGRATION.md b/JAVA_MIGRATION.md index 0450a4e..cf70e32 100644 --- a/JAVA_MIGRATION.md +++ b/JAVA_MIGRATION.md @@ -238,6 +238,10 @@ Execution order is **complete and document the Java API → migrate and release the target pack → retire FMP's Scala dependencies**. Work can overlap by capability, but the removal gate cannot be skipped. Phases 9 and 10 now drive the remaining work; Phase 8 is the final gated milestone. +After the Java API and representative extension workloads are stable, run the focused performance pass in Phase 4b. +It can overlap consumer migration and must not wait for final Scala removal. Attribute implementation gains and +consumer migration gains separately; performance work does not relax any compatibility or adoption gate. + Candidate mappings, with final names and mutability contracts to be decided from existing behavior: | Existing Scala-facing shape | Java-first equivalent | @@ -410,6 +414,47 @@ and improved throughput by 20.3% with an identical checksum. Exit condition: identified steady-state Scala allocation sites are removed with compatible results. +### Phase 4b — Measured performance pass + +Status: **planned.** Phase 4's focused historical results are complete; they do not establish current whole-pack +performance. Re-profile the corrected Java branch and representative consumer integrations, then improve the measured +costs. The goal is useful gains from both the port and adoption of its API, not a faster language label. + +Prioritize hot paths by CPU/allocation evidence and user impact, while also checking intermittent and retained costs: + +| Representative scenario | Costs to investigate | +| --- | --- | +| Typical and dense mixed multipart bases with ticking parts, ProjectRed wiring and redstone activity | Main-thread CPU, tick-time median/tails, allocation and GC pauses | +| Placement/replacement, occlusion previews and changing OpenComputers print shapes | Query/interaction latency, callback and snapshot costs, allocations | +| Chunk load/unload, old-world reconstruction, schematic/GuideNH previews and frame moves | Load/transition latency, NBT work, cache churn and peak/retained memory | +| Client views of ordinary and dense microblocks, including illuminated ProjectRed parts | Frame-time distributions, chunk rebuilds, render CPU and GPU limits | +| Description updates and multiplayer chunk watches | Serialization time, bytes/packets, burst allocation and tick-time spikes | +| Fresh startup, first trait combinations and repeated combinations | Startup/first-use latency, class generation, cache hit behavior and retained heap | + +These are coverage candidates, not assumed bottlenecks. Include a modest/common scene, a representative busy scene and +an explicitly labeled stress case. Reuse the existing Forge/JFR harness for attribution; add a workload only when it +represents an observed consumer path. Use actual client/pack runs to validate user-facing claims. + +- [ ] Capture a fresh baseline with exact FMP/consumer revisions, runtime, pack/config/world and repeatable actions; + record CPU, allocation and memory profiles before selecting targets. +- [ ] Rank candidates by measured cost and expected user impact, including worthwhile startup/memory improvements + outside steady-state hot paths. Set a measurable acceptance criterion before each edit. +- [ ] Compare unchanged consumers on baseline versus optimized FMP to isolate implementation gains. On the same FMP + artifact, compare a consumer's old calls with its migrated calls to isolate migration benefits and bridge overhead. + Include a compatible Scala/reference artifact as context where feasible; report non-comparable cases explicitly. +- [ ] Make one bounded improvement per commit, with characterization/regression checks and paired measurements. + Preserve ordering, snapshots, callback/override behavior, packets, NBT and generated-extension compatibility. Do not + remove Scala shells or weaken an API contract just to improve a benchmark. +- [ ] Publish absolute and relative before/after results, run variability, unchanged controls and regressions using + the [measurement protocol](JAVA_MIGRATION_PROFILE.md#broader-performance-pass-protocol-planned). Validate CPU wins + against allocation/GC, retained memory, startup and client/server tails rather than trading one cost silently for another. +- [ ] Repeat the representative pack scenarios after integrating the changes and relevant consumer migrations. + Retain only justified improvements; record below-noise results and rejected candidates without claiming a speedup. + +Exit condition: representative scenarios have repeatable before/after evidence, selected improvements meet their +declared criteria without unresolved correctness or material performance regressions, and consumer migration benefits +are separately demonstrated where present. There is no preset percentage target or promised whole-pack TPS gain. + ### Phase 5 — Convert built-in tile traits through the existing Java path - [x] Characterize the direct class shape, generated interface, super dispatch, behavior, and class caching of a diff --git a/JAVA_MIGRATION_HANDOFF.md b/JAVA_MIGRATION_HANDOFF.md index 099bea3..45217de 100644 --- a/JAVA_MIGRATION_HANDOFF.md +++ b/JAVA_MIGRATION_HANDOFF.md @@ -68,6 +68,12 @@ registry/generator/reflection replacements, extension examples and internal-boun patches, releases and pack adoption must precede final Scala removal and client/pack release validation; it is not a percentage of the whole migration. +A separate [Phase 4b performance pass](JAVA_MIGRATION.md#phase-4b--measured-performance-pass) is planned once the API +and representative extension workloads are stable, alongside consumer migration. Use fresh realistic profiles and +repeated paired runs; distinguish FMP implementation gains from migrated-consumer gains, covering hot paths plus +startup, transitions, rendering, network and memory costs. Follow the [measurement protocol](JAVA_MIGRATION_PROFILE.md#broader-performance-pass-protocol-planned). +The historical Phase 4 results do not replace that pass, and no new performance gain has been measured for this update. + Pause mechanical extraction of retained Scala shells unless it enables that API, fixes a demonstrated issue or has a measured benefit. `ScalaSignature.ClassSymbolRef.info` remains an optional bounded extraction, not the default next task. Keep case-class/product/serialization shapes and simple model accessors supported until their users are retired. diff --git a/JAVA_MIGRATION_PROFILE.md b/JAVA_MIGRATION_PROFILE.md index b6c8ac8..13a51f0 100644 --- a/JAVA_MIGRATION_PROFILE.md +++ b/JAVA_MIGRATION_PROFILE.md @@ -4,6 +4,47 @@ This is the reproducible pre-optimization baseline for Phase 4. It runs inside t server, using the same generated tiles as the functional suite. It is intentionally focused rather than a claim about whole-pack TPS. +The broader follow-up is planned in [Phase 4b](JAVA_MIGRATION.md#phase-4b--measured-performance-pass). The historical +numbers below remain scoped to their recorded workloads and revisions; no new performance result is claimed by +adding this plan. + +## Broader performance pass protocol (planned) + +Begin after the Java API/representative extension workloads are stable, alongside consumer migration and before +final Scala removal. A workload manifest must identify the world/seed or reproducible world snapshot, pack and mod +versions, FMP/consumer commits, hardware, exact JVM/flags/heap, view distance and graphics settings, part/tile/trait +counts, and the action sequence or replay command. Restore equivalent world state before each run. + +Use the pack's selected modern Java runtime for primary results; check the supported Java 8 artifact separately for +behavior and regressions. Hold the runtime and configuration fixed within every A/B comparison. Never attribute a +JVM, renderer, pack-version or hardware change to the Java port. + +Measure fresh-process startup and cold first-use/class generation separately from warmed steady-state play. For each +variant, start with at least five independent runs, alternate baseline/candidate order, use identical warm-up and +measurement windows, and extend runs/repetitions when results are noisy. Keep profiling overhead matched; confirm +end-to-end timing without profiling when overhead is material. Preserve raw reports and recordings under a named +ignored evidence directory rather than overwriting the only baseline. + +Report median and variability across runs. Derive p95/p99 tick or frame times from enough samples within each run, +not from five aggregate timings. Include absolute units and relative differences: CPU time, ms/tick, ms/frame, +allocation bytes per operation or second, GC pause time, peak/retained heap, cold latency and network bytes where +relevant. TPS alone can hide an improvement below the 50 ms tick budget. Separate CPU-bound and GPU-bound client +scenes, and do not turn a helper microbenchmark ratio into an FPS/TPS claim. + +Use two controlled comparisons: baseline versus optimized FMP with consumer code unchanged; then legacy versus +migrated consumer calls on the same FMP artifact, including adapters and any required snapshots. Where compatible, +also compare with the Scala/reference release on the same runtime and inputs. Compare equivalent results/world state, +packet/NBT fixtures and callback behavior; explicitly exclude scenarios whose behavior cannot be matched. + +Each accepted change records: hypothesis and targeted profile site; scenario/manifest and commands; before/after +commits; raw evidence location; absolute/relative measurements with variability; correctness checks; controls, +regressions and tradeoffs; and the acceptance decision. Define practical benefit above noise before editing. A +below-noise result or a bottleneck outside FMP is a valid finding, not a reason to invent more optimization work. + +Use the existing harness and local profiling tools first. Extend only the missing representative workloads, and keep +small microbenchmarks as attribution/regression aids alongside actual pack/client measurements. Update this document +with results when that pass runs; performance is not established by completing the API migration table. + ## Re-run The local server EULA must already contain `eula=true`. From PowerShell at the repository root: diff --git a/docs/migration/HISTORY.md b/docs/migration/HISTORY.md index 9c0a74b..657b2f2 100644 --- a/docs/migration/HISTORY.md +++ b/docs/migration/HISTORY.md @@ -1864,3 +1864,12 @@ differences belong in the [divergence ledger](../../JAVA_MIGRATION_DIVERGENCES.m retains all 386 member/type/reflection rows across 27 consumers. Reference checkouts are unchanged. Physical-client allocation/registration/rendering remain manual gates. Next API-table entry: the tile conversion result. Evidence: `run/migration-render-id-reference/`. + +### 2026-09-05 — Planned measured performance follow-up + +- Added Phase 4b after checking the completed focused Phase 4 work. It covers realistic consumer/pack hot paths and + broader startup, transition, client rendering, networking and memory costs, with repeated controlled comparisons. +- The protocol distinguishes changes inside FMP from the cost/benefit of migrating consumer calls on the same FMP + artifact, retains correctness/compatibility gates, and requires raw evidence, variability and reported regressions. + It can overlap consumer migration once representative API/extension workloads are stable. No new performance + measurements or speedup claims are introduced by this plan update.