Repository navigation
perf: keep rarely declared command metadata out of every command's table - #1472
Conversation
CommandMeta was about 600 bytes per command, and a derived CLI emits one
for every subcommand and every flattened `Args` type, nearly all of it
empty. Deprecation, hidden aliases, help prose and examples, layout
settings, outputs, exit codes and the other spec-only fields now live in
a CommandExtra behind `CommandMeta::extra`. Derived tables build each
command's extras as a constant and `CommandExtra::shared` swaps an empty
one for the single NO_COMMAND_EXTRA static, so a command that declares
none of these costs a pointer.
Code that reads a moved field goes through `extra`
(`meta.extra.after_long_help`), and hand-written tables set them inside
`extra: &CommandExtra { .. }`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 1 remains after this review. 📝 WalkthroughWalkthroughThe pull request moves extended command metadata from ChangesCommand metadata restructuring
Priority: ⚪ Not assessed Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Refactor Suggested reviewers: Merge Risk: ⚪ Minimal · up to No actionable merge-blocking issue is established; the PR is ready to merge after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
<!-- entire-trail-link-start --> https://entire.io/gh/jdx/usage/trails/16 <!-- entire-trail-link-end --> ### 🐛 Bug Fixes - **(help)** colour only the structure the renderer writes by [@jdx](https://github.com/jdx) in [#1480](#1480) ### ⚡ Performance - shrink the help and completion code usage-rs adds to a binary by [@jdx](https://github.com/jdx) in [#1469](#1469) - keep rarely declared flag metadata out of every flag's table by [@jdx](https://github.com/jdx) in [#1470](#1470) - write help rows through one renderer for both help pages by [@jdx](https://github.com/jdx) in [#1471](#1471) - collect coloured-help structure while the page is written by [@jdx](https://github.com/jdx) in [#1476](#1476) - shrink the per-CLI code the derive generates for binding by [@jdx](https://github.com/jdx) in [#1477](#1477) - shrink the parse-error renderer usage-rs adds to a binary by [@jdx](https://github.com/jdx) in [#1478](#1478) - shrink the shell-completion code a derived CLI carries by [@jdx](https://github.com/jdx) in [#1475](#1475) - keep rarely declared command metadata out of every command's table by [@jdx](https://github.com/jdx) in [#1472](#1472) - shrink the command and metadata tables a derive emits by [@jdx](https://github.com/jdx) in [#1474](#1474) ### 🔍 Other Changes - **(ci)** comment on a discussion when the PR implementing it merges by [@jdx](https://github.com/jdx) in [#1460](#1460) ### 📦️ Dependency Updates - update jdx/packslip action to v1.2.0 by [@renovate[bot]](https://github.com/renovate[bot]) in [#1466](#1466) - update zizmorcore/zizmor-action action to v0.6.4 by [@renovate[bot]](https://github.com/renovate[bot]) in [#1465](#1465) - update module github.com/urfave/cli/v3 to v3.12.0 by [@renovate[bot]](https://github.com/renovate[bot]) in [#1467](#1467) - update aube to v2.3.0 by [@jdx](https://github.com/jdx) in [#1473](#1473)
Instruction countsThe comparison never ran — an earlier step failed.
|
https://entire.io/gh/jdx/usage/trails/24
oxc is moving oxlint and oxfmt from bpaf to usage-rs (oxc-project/oxc#26027), and reviewers weigh how much binary size usage-rs adds. Much of that is static metadata. Each
CommandMetawas about 600 bytes. A derived CLI emits one for every subcommand and every flattenedArgstype, so oxlint has about 11. Nearly every field in them was empty.This applies the #1470
FlagMeta→FlagExtrasplit to commands.CommandMetakeeps only what nearly every command sets:cmd,about,long_about,hide,args_override_self,flags,args,subcommands,groups,flatten_groups. Everything else is now in aCommandExtrabehindCommandMeta::extra. That covers deprecation, hidden aliases, heading and display order, surface/available_if, effect, mount, restart token, clause, subcommand settings,next_line_help/flatten_help, term widths, before/after help, examples, headings, outputs,select, and exit codes.Derived tables build each command's extras as a constant.
CommandExtra::sharedthen replaces an empty one with the singleNO_COMMAND_EXTRAstatic, so a command that declares none of these costs one pointer.shareddestructures every field without.., so a field added later and missed in the emptiness check is a compile error, not a silently dropped declaration. A test pins the sharing.Size
How this was measured: oxc's PR branch was patched to use this usage branch and built with oxc's release profile (opt-level 3, fat LTO, 1 codegen unit) on linux x86_64. The numbers are the summed allocated sections of the stripped binaries. Most of the saving is in
.data.rel.ro(−4,128 B oxlint, −1,824 B oxfmt). Help, error, spec and completion output from both binaries was compared byte-for-byte against the #1470 build, and all 30 cases were identical.ArgMetawas left alone. oxlint and oxfmt each have one positional, so splitting it would save a few hundred bytes at most.Migration
Code that reads or builds
CommandMetadirectly has to go throughextrafor the moved fields. Derived CLIs need no changes.Validation
cargo test --workspace --all-featurespasses (2,801 tests, no snapshot changes), andcargo clippy --workspace --all-targets --all-features -- -D warningsis clean.🤖 Generated with Claude Code
Note
Low Risk
Layout/API refactor across help, completion, and spec emission with broad test coverage; runtime CLI behavior should be unchanged if all
extrapaths were migrated consistently.Overview
Introduces
CommandExtraand moves rarely set command metadata (deprecation, hidden aliases, clause/restart tokens, help layout, examples, outputs, effects, etc.) offCommandMetabehindmeta.extra, mirroring the existingFlagExtrapattern.CommandMetakeeps the common parse/help surface (flags,args,subcommands,hide, …) so each static table is smaller; derived CLIs callCommandExtra::sharedto point empty extras at a singleNO_COMMAND_EXTRAstatic.All readers/writers are updated to use
extra.*: shell completion, help rendering and usage lines,Spec::to_kdl, conformance KDL→tables building, usage-dynamic collision checks, and derive codegen (root/subcommand/enum variant metadata). Hand-builtCommandMetain tests and fixtures nest moved fields underCommandExtra { .. }.Breaking for direct
CommandMetausers only: field access becomesmeta.extra.after_help(etc.); behavior and emitted help/spec/completions are intended to stay the same.Reviewed by Cursor Bugbot for commit a2f8dbb. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit