Skip to content

perf(debug): bound the entity inspector's per-component code (labelle-engine#922) - #822

Merged
apotema merged 2 commits into
mainfrom
perf/debug-inspector-outline
Oct 31, 2026
Merged

apotema merged 2 commits into
mainfrom
perf/debug-inspector-outline

Conversation

@apotema

@apotema apotema commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Refs labelle-toolkit/labelle-engine#922 (labelle-toolkit/labelle-cli#528 WP2b). Draft. This is the inspector half; the startup and save-loader half is labelle-toolkit/labelle-engine#925, which is stacked on engine #921.

Why

In Flying Platform's ReleaseSafe WASM build, the debug plugin's drawEntityDetail (~165 KB) and drawEntityBrowser (~85 KB) were the 2nd- and 4th-largest functions. Both walk the whole component registry with inline for. That expands every component's code into the two functions: a runtime bufPrintZ of its name, membership checks, tag text, and the detail tree with every field's formatting.

Changes

  • test(debug) (first commit, on the unchanged code): pins the exact widget transcript of both windows against a mock game and a call-recording Gui. It covers:

    • Position first, then registry order with fields;
    • the ? label for an over-long name;
    • filters and the dirty flag, and the tag column;
    • Select/Deselect and a dead entity;
    • the 50-row cap.

    The plugin's test build has no labelle-core, so the position type is resolved lazily through PositionOf(Game). Only the tests declare DebugInspectorPosition; real games still get core.Position.

  • perf(debug):

    • Labels are now built at comptime, with the same ? fallback.
    • The browser's filter, membership and tag walks are runtime loops over comptime tables: labels, plus one noinline "has component" check per type.
    • Each component's detail tree is drawn by its own noinline drawComponentNode.

    The engine registry's names() returns a slice of a comptime var, so the names are copied into a constant first. The mock now reproduces that.

    The transcript tests pass unmodified, in Debug and ReleaseSafe.

Result

In FP, with engine#925, both functions are gone from the top list. They are now small enough to inline into drawGui, which is 26 KB. The before/after table for the whole of #922 is in labelle-toolkit/labelle-engine#925:

  • game compile (edit rebuild): 131 → 99 s
  • peak memory: 5.67 → 4.9 GiB
  • game.wasm: −394 KB

Tests

cd plugins/debug && zig build test: 15/15 pass, in Debug and ReleaseSafe. On main it is 12/12; the 3 new tests are the inspector tests. Nothing outside plugins/debug changed, so I did not run the assembler's own suite.

Follow-up

Flying Platform vendors this plugin as plugins/debug (a byte-identical copy apart from line endings). It needs re-vendoring once this merges. My FP measurement clone used this version locally; nothing was committed to FP.

Not validated

The inspector was not exercised in a browser or on desktop. Behaviour is covered only by the transcript tests.

https://claude.ai/code/session_01Hpt1haxcboZPznpG1KqDRS

Summary by CodeRabbit

  • Improvements
    • The inspector now uses a game-specific debug position type when available, with the standard position type as a fallback.
    • Component browsing and detail views handle long labels and display up to 50 rows.

…gine#922)

The entity browser and detail windows are instantiated over a game's
whole component registry. Before reshaping how that per-component code
is generated, drive both windows against a mock game and a
call-recording Gui and pin the exact transcript: Position first, every
registered component in registry order with its fields, the "?" label
for an over-long name, filters and the dirty flag, the component tag
column, Select/Deselect, dead-entity handling and the 50-row cap.

The plugin's test build has no labelle-core, so the position type is
resolved lazily through `PositionOf(Game)`: a game may name it with a
`DebugInspectorPosition` decl (only the tests do); every real game
still gets `core.Position`.

Claude-Session: https://claude.ai/code/session_01Hpt1haxcboZPznpG1KqDRS
…-engine#922)

`drawEntityDetail` and `drawEntityBrowser` walked the component registry
with `inline for` bodies, so every component's filter checkbox (with a
runtime bufPrintZ of its name), membership checks, tag text and detail
tree (with every field's formatting) was expanded into the two draw
functions. In Flying Platform's ReleaseSafe WASM build they were the
2nd- and 4th-largest functions: ~165 KB and ~85 KB.

- Component labels are built at comptime (same "?" fallback for a name
  that does not fit the 128-byte label buffer).
- The browser's filter, membership and tag walks are runtime loops over
  comptime tables: labels, and one noinline `has component` check per
  type.
- Each component's detail tree is drawn by its own noinline
  `drawComponentNode`, instantiated once per type.

The widgets drawn, their order, labels and the filter/dirty/selection
behaviour are unchanged: the transcript tests added in the previous
commit pass unmodified, in Debug and ReleaseSafe.

Claude-Session: https://claude.ai/code/session_01Hpt1haxcboZPznpG1KqDRS
@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Team
  • Run ID: b5fc327c-b009-48d1-9d5f-30cbfaf7ad36
Commits

Reviewing files that changed from the base of the PR and between 5ce90db and a81adda.

Files selected for processing: 1
  • plugins/debug/src/root.zig

Included review availability: This review used your included allowance. 1 included review remains after this review. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.

Walkthrough

The inspector now resolves Position per game, iterates component labels and membership checks at runtime, and renders component details through a bounded helper. New tests cover browser filtering and selection, detail output, and display limits.

Changes: Debug Inspector

Layer / File(s) Summary
Position resolution and component browser
plugins/debug/src/root.zig
The browser uses the game’s DebugInspectorPosition when available and otherwise uses core.Position. It iterates component labels and membership checks at runtime.
Component detail rendering and tests
plugins/debug/src/root.zig
The detail window uses the resolved Position type and renders each registered component through drawComponentNode. Tests cover detail output, browser filtering and selection, long labels, missing Position, stale selections, and the 50-row limit.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Merge Risk: Minimal · up to a81ad

No actionable merge-blocking issue was established. The inspector change is mergeable after normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the debug performance change and matches the main objective of reducing per-component code in the entity inspector.
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
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.
Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)

Finishing Touches
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

I’m a rabbit with a debug view,
I hop through labels, one by one.
I check each component in the list,
Then peek at fields beneath the sun.
Fifty rows, and then I’m done!

@apotema
apotema marked this pull request as ready for review October 31, 2026 02:56
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-31T02:57:20.245074Z a81adda Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@apotema apotema left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Codex, OpenAI LLM — review of a81addad9e9d0b765340bb0947dc4f84e7886ce8.

No correctness findings in the inspector outlining diff. The fixed UI labels, truncated-name fallback, runtime row dispatch, component ordering, filtering, 50-entity cap, selection, and dead-entity handling remain consistent with the old path. PositionOf(Game) retains the fallback while allowing the test game override.

Validation: local plugin zig build test -j2 --summary all passes all 15 Debug tests; current-head GitHub CI run 41111827084 is successful. I did not perform an interactive FP inspector smoke test or repeat the WASM memory benchmark.

Consumption note: FP vendors plugins/debug; a toolkit/assembler pin bump alone will not deliver this optimization to FP. Re-vendor that plugin as part of consumer adoption, as the PR description already notes.

@apotema
apotema merged commit 7d6b91b into main Oct 31, 2026
4 checks passed
apotema added a commit that referenced this pull request Oct 31, 2026
… inspector outlining (#826)

Version-only release of #824 (manifest-v2 optional `.lazy` on root build
deps; lazy-safe emsdk preflight, fixes #823) and #822 (debug entity
inspector outlining, labelle-engine#922), part of
labelle-toolkit/labelle-cli#528.

Claude-Session: https://claude.ai/code/session_01Hpt1haxcboZPznpG1KqDRS
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.

1 participant