Skip to content

Reduce STU parsing and schema initialization overhead - #191

Open
Js41637 wants to merge 4 commits into
developfrom
perf/stu-optimizations
Open

Js41637 wants to merge 4 commits into
developfrom
perf/stu-optimizations

Conversation

@Js41637

@Js41637 Js41637 commented Oct 10, 2026

Copy link
Copy Markdown
Member

STU loading repeatedly performs reflection, boxes primitive array elements, and rebuilds inherited field metadata. This change reduces that work through three optimizations:

  • Bulk primitive-array reads: Read supported numeric arrays directly into typed storage instead of decoding and assigning each element individually. Reads use bounded chunks and handle partial stream reads. Custom readers and factories retain the existing decoding path.
  • Cached struct readers: Cache a reader delegate for each struct type, replacing repeated generic method construction and reflective invocation for scalar fields and array elements. The cache is thread-safe and preserves the existing exception wrapping.
  • Cached schema metadata: Enumerate assembly types once during initialization and reuse declared field attributes and inherited field ordering. Published attributes and arrays remain independently mutable, and custom attribute subclasses retain their reflection behavior.

Performance

Measured results for the implemented optimizations:

Measurement Before After Reduction
STU parsing time 2.689 s 1.950 s 27.5%
Asset opening and parsing 4.139 s 3.365 s 18.7%
Parser allocations 3.792 GB 2.376 GB 37.3%
Cold schema initialization 180.05 ms 108.90 ms 39.5%
Schema initialization allocations 70.84 MB 40.80 MB 42.4%

The parsing results measure primitive-array and struct-reader improvements together across 186,596 assets, using the median of six measured passes after warmup. Schema initialization was measured separately across three fresh-process runs. Allocation figures represent cumulative allocated bytes, not peak memory usage.

Read built-in primitive arrays into bounded spans to avoid per-element factory calls and boxing. Preserve scalar decoding for custom factories, field readers, binary readers, and unsupported byte order.
Cache a typed reader delegate for each struct type to remove repeated reflection lookup and invocation allocations during STU decoding. Keep reader exceptions wrapped in TargetInvocationException to preserve the existing failure contract.
Reuse assembly type discovery, declared field attributes, and inherited field ordering to reduce repeated reflection during STU manager initialization. Clone publicly exposed attributes and field arrays, and preserve fresh reflection for custom attribute subclasses.
Expand single-line conditionals, clean up whitespace and obsolete comments, and document array decoding, struct reader caching, and metadata ownership to make the optimizations easier to maintain without changing behavior.

Validation: Release build passed; all 126 parser regression cases and four metadata comparisons matched the baseline; git diff --check passed.
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