perf: zero-allocation hot path on the proxy send path + docs sweep
Eliminate per-field / per-recipient managed-string allocations a reviewer
measured on the per-client send path (2 allocs/transmission), and make the
SetFor path allocation-free, with the safety proven by RE rather than assumed.
- Name interning: field/serializer names are stable engine char*; intern by
pointer (NativeUtil.ResolveName) so the hot encode/send paths allocate the
string once per distinct name, then reuse it. 0 per-transmission allocs.
- single internal max length (no maxLen-mismatch cache poisoning),
- never cache an empty/transient result,
- cache cleared on every level activation (IGameListener.OnServerActivate)
so a map-rebuild can't resolve a stale name from a reused address.
- PerClientDispatch.Record reuses the stored override array in place when the
recipient count is unchanged -> 0 allocs steady-state on the SetFor path.
Safe: Record (pack) and TryResolve (per-client send) never run concurrently.
Proven by RE of BOTH libengine2.so and engine2.dll: PackEntities is a
blocking parallel-for (results consumed inline after the dispatch joins) and
the per-client send is a synchronous loop (no thread dispatch), all in one
per-tick SendClientMessages call. See docs/ENCODE_CALLGRAPH_RE.md.
- Docs sweep: README + docs/ updated to the IProxyManager once-per-field model;
purged removed gamedata keys (EncodeField/SendClientMessages/SerializerSingleton)
and the abandoned force-resend approach; added the EncodeEntity capture hook to
FINDING_SIGNATURES.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> P
Prefix committed
0dc2a5b3ece0b78317bcfe122b3b700d77f9a3b4
Parent: d50339a