Skip to content

Compress runtime-class hierarchy with UTF-16 prefixes and narrow buckets - #2648

Open
Manodasan Wignarajah (manodasanW) wants to merge 1 commit into
staging/3.0from
manodasanw/hierarchy-utf16-prefix-narrow
Open

Manodasan Wignarajah (manodasanW) wants to merge 1 commit into
staging/3.0from
manodasanw/hierarchy-utf16-prefix-narrow

Conversation

@manodasanW

Copy link
Copy Markdown
Member

Summary

Reduce runtime-class hierarchy lookup size using shared UTF-16 namespace prefixes and conditional 16-bit bucket offsets. Preserve every hierarchy entry, existing lookup semantics and allocation-free base-name spans.

Motivation

Fully qualified class names repeat the same namespaces throughout the hierarchy table. Sharing those prefixes reduces readonly data.

Changes

  • WindowsRuntimeTypeHierarchyBuilder.cs: emit each namespace prefix once and store a prefix offset plus class-name suffix in each key. Use 16-bit bucket offsets when the complete key payload fits safely alongside the reserved empty-bucket sentinel; otherwise retain 32-bit offsets.
  • WindowsRuntimeTypeHierarchy.cs: compare prefix and suffix directly against input slices using ordinal UTF-16 comparisons. Use the generated bucket accessor to hide the selected offset width.

Full-name hashing, bucket counts, collision chains and contiguous UTF-16 base values remain unchanged. No names are reconstructed or allocated during lookup.

Before and after example

Previously, each key stored the complete class name, repeating its namespace:

Before — keys:
  [33, baseOffsetA, "Microsoft.UI.Xaml.Controls.Button"]
  [35, baseOffsetB, "Microsoft.UI.Xaml.Controls.CheckBox"]

The new layout stores that namespace once:

After — shared prefixes:
  P0 -> [27, "Microsoft.UI.Xaml.Controls."]

After — keys:
  [33, baseOffsetA, P0, "Button"]
  [35, baseOffsetB, P0, "CheckBox"]

This is an illustrative layout: lengths count UTF-16 characters, P0 represents a byte offset into the prefix table, and the base-value offsets are unchanged. Matching compares the namespace and suffix separately against the original input.

For ContosoCamera, prefix sharing reduces the key payload from 97,272 to 46,916 bytes, enabling narrow buckets. The same 1,526 bucket entries then occupy 3,052 bytes instead of 6,104 bytes. Larger catalogs automatically retain 32-bit entries.

Measurements

ContosoCamera was republished unchanged using matching configurations and tools. Size measurements include all hierarchy payloads and retained lookup helpers.

Measurement Before After
Complete hierarchy table 120,330 B 68,790 B
Lookup and incremental helper code 732 B 982 B
Final native executable 6,118,912 B 6,067,712 B
Uncached mixed lookup benchmark 99.37 ns/op 100.14 ns/op
Cached marshalling-info benchmark 47.75 ns/op 48.15 ns/op
Warmed hierarchy lookup allocations 0 B/op 0 B/op

This reduces hierarchy data by 42.8% and the native executable by 50 KiB. Native AOT timings are warmed harness measurements on Windows x64 with .NET 10.0.14, not application startup measurements.

Validation

  • Release builds with existing code-style checks.
  • Native AOT verification of all immediate bases and complete ancestor sequences for the 949-entry application snapshot and a 1,214-entry synthetic catalog, exercising both narrow and wide formats.
  • Unknown names, collision misses, near-matches, ordinal case sensitivity, empty namespaces, Unicode, concurrent reads and allocation-free spans.
  • Six exact boundary/rejection cases on CoreCLR, covering key-payload width selection and existing key/value limits.
  • Native COM fixture verification that a trimmed exact Button projection still resolves to the surviving DependencyObject wrapper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

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