ModernUO/Projects/Server/Serialization
Kamron Batman f7b835d7e9
perf(saves): 2.2x faster BufferWriter write path, single-pass short strings
Tier-1 disasm of a generated-style Serialize showed PGO's guarded
devirtualization already inlines every IGenericWriter.Write body (interface
vs concrete-typed callsites measured identical), so no API or generator
changes are needed. What remained as a real call per primitive write was the
Index property setter - too large to inline due to its range-check throw path,
plus per-write high-water tracking, an AsSpan bounds check, and a
BinaryPrimitives span check.

The write path now reserves capacity once (the existing grow-on-Flush check),
then does an unaligned store through a ref with a raw index increment - the
capacity check proves the store in-bounds, and the index only moves forward
between Seeks. The _bytesWritten high-water mark (used only by
SeekOrigin.End) folds at Seek/Resize instead of per write, which is
equivalent because writes are monotonic between seeks. The Index property
keeps its validating semantics for Seek and subclasses.

BufferWriter also gains class-level implementations of the hottest
IGenericWriter default interface methods (WriteEncodedInt, DateTime,
TimeSpan, Point2D/3D, Rectangle2D/3D, Map, Race): a DIM dispatches again on
`this` for every nested Write even at a devirtualized callsite, and the class
overloads keep the whole write inlined.

Strings (arbitrary UTF-16) previously walked every string twice
(GetByteCount then GetBytes) because the variable-width length prefix
precedes the bytes. Strings of 85 chars or fewer (any content, incl.
surrogate pairs - 85 * 3 = 255 bytes max) now encode once into a 256-byte
stack scratch, then write the prefix and copy. Byte output is identical.

Measured: 34.4 -> 15.7 ns/entity on a generated-style write mix (~20 writes,
58 bytes), 22.5 -> 11.8 ns per short-string write, and the end-to-end freeze
benchmark (10M entities / 1.7GB / 24 cores, dense profile) drops from ~99ms
to ~74-82ms. Combined with the earlier pipeline commits: ~740ms -> ~78ms.

New tests pin byte-level output and position semantics: primitive
little-endian layouts, Seek(End) high-water behavior, growth preservation,
span writes across growth, encoded-int formats, and string equivalence
across the scratch/two-pass boundary with mixed-width UTF-16 content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:38:46 -07:00
..
Attributes fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
AdhocPersistence.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
BinaryFileReader.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
BufferReader.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
BufferWriter.cs perf(saves): 2.2x faster BufferWriter write path, single-pass short strings 2026-07-16 22:38:46 -07:00
GenericEntityPersistence.cs perf(saves): workers iterate entity dictionaries directly; main thread joins the drain 2026-07-16 22:38:46 -07:00
GenericPersistence.cs perf(saves): chunked worker handoff, LPT blob scheduling, heap pre-sizing 2026-07-16 22:38:46 -07:00
IGenericReader.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
IGenericSerializable.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
IGenericWriter.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
ISerializable.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
ISerializableExtensions.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
MemoryMapFileWriter.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Persistence.cs perf(saves): chunked worker handoff, LPT blob scheduling, heap pre-sizing 2026-07-16 22:38:46 -07:00
SerializationChunkSource.cs perf(saves): workers iterate entity dictionaries directly; main thread joins the drain 2026-07-16 22:38:46 -07:00
SerializationExtensions.cs feat: Refactor Poison system, implement Darkglow & Parasitic effects (#2385) 2026-03-21 21:27:22 -07:00
SerializationThreadWorker.cs perf(saves): workers iterate entity dictionaries directly; main thread joins the drain 2026-07-16 22:38:46 -07:00
ShadowDictionaryEntries.cs perf(saves): workers iterate entity dictionaries directly; main thread joins the drain 2026-07-16 22:38:46 -07:00
UnmanagedDataReader.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00