From bbed1caf44605961bf9489d1b02de7b1f3cc9191 Mon Sep 17 00:00:00 2001 From: Loretta Date: Tue, 3 Mar 2026 13:53:58 +0100 Subject: [PATCH] Enable FastWire mode for binary string serialization Activate FastWire encoding for both serialization and deserialization, using UTF-16 and fixed-width lengths for strings. WireMode is now public and defaults to FastWire. Removes unused ObjectEnd marker, clarifying object end handling. This improves string (de)serialization speed at the cost of larger output. --- ...lizer.BinaryDeserializationContext.Read.cs | 18 ++++++------- ...serializer.BinaryDeserializationContext.cs | 4 +-- ...rySerializer.BinarySerializationContext.cs | 26 +++++++++---------- .../Binaries/AcBinarySerializer.cs | 12 ++++----- .../Binaries/AcBinarySerializerOptions.cs | 14 +++++----- .../Serializers/Binaries/BinaryTypeCode.cs | 2 +- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.Read.cs b/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.Read.cs index d9e10ef..14dcb6b 100644 --- a/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.Read.cs +++ b/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.Read.cs @@ -330,15 +330,15 @@ public static partial class AcBinaryDeserializer } // FastWire: length is char count, data is UTF-16 (2 bytes per char) - //if (FastWire) - //{ - // var byteLen = length * 2; - // EnsureAvailable(byteLen); - // var chars = MemoryMarshal.Cast(_buffer.AsSpan(_position, byteLen)); - // var value = new string(chars); - // _position += byteLen; - // return value; - //} + if (FastWire) + { + var byteLen = length * 2; + EnsureAvailable(byteLen); + var chars = MemoryMarshal.Cast(_buffer.AsSpan(_position, byteLen)); + var value = new string(chars); + _position += byteLen; + return value; + } EnsureAvailable(length); diff --git a/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.cs b/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.cs index 049480e..4e1c736 100644 --- a/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.cs +++ b/AyCode.Core/Serializers/Binaries/AcBinaryDeserializer.BinaryDeserializationContext.cs @@ -63,7 +63,7 @@ public static partial class AcBinaryDeserializer public bool HasMetadata; public bool IsMergeMode; public bool RemoveOrphanedItems; - //public bool FastWire; + public bool FastWire; // Options-derived properties public byte MinStringInternLength => Options.MinStringInternLength; @@ -139,7 +139,7 @@ public static partial class AcBinaryDeserializer HasMetadata = false; IsMergeMode = false; RemoveOrphanedItems = false; - //FastWire = Options.WireMode == WireMode.Fast; + FastWire = Options.WireMode == WireMode.Fast; ChainTracker = null; } diff --git a/AyCode.Core/Serializers/Binaries/AcBinarySerializer.BinarySerializationContext.cs b/AyCode.Core/Serializers/Binaries/AcBinarySerializer.BinarySerializationContext.cs index 576ebea..26ea2eb 100644 --- a/AyCode.Core/Serializers/Binaries/AcBinarySerializer.BinarySerializationContext.cs +++ b/AyCode.Core/Serializers/Binaries/AcBinarySerializer.BinarySerializationContext.cs @@ -242,7 +242,7 @@ public static partial class AcBinarySerializer /// Reference handling is safe because generated code inlines TryConsumeWritePlanEntry for IId types. /// public bool IsDirectObjectWrite => !UseMetadata; - //public bool FastWire { get; private set; } + public bool FastWire { get; private set; } public byte MinStringInternLength => Options.MinStringInternLength; public byte MaxStringInternLength => Options.MaxStringInternLength; public BinaryPropertyFilter? PropertyFilter => Options.PropertyFilter; @@ -281,7 +281,7 @@ public static partial class AcBinarySerializer HasPropertyFilter = Options.PropertyFilter != null; InternBit = 1 << (int)Options.UseStringInterning; HasStringInterning = Options.UseStringInterning != StringInterningMode.None; - //FastWire = Options.WireMode == WireMode.Fast; + FastWire = Options.WireMode == WireMode.Fast; } public override void Clear() @@ -630,17 +630,17 @@ public static partial class AcBinarySerializer public void WriteStringUtf8(string value) { - //if (FastWire) - //{ - // // UTF-16: char count (fixed uint) + raw char data (zero-encoding memcopy) - // var charLen = value.Length; - // var byteLen = charLen * 2; - // WriteRaw(charLen); - // EnsureCapacity(byteLen); - // MemoryMarshal.AsBytes(value.AsSpan()).CopyTo(_buffer.AsSpan(_position, byteLen)); - // _position += byteLen; - // return; - //} + if (FastWire) + { + // UTF-16: char count (VarUInt) + raw char data (zero-encoding memcopy) + var charLen = value.Length; + var byteLen = charLen * 2; + WriteVarUInt((uint)charLen); + EnsureCapacity(byteLen); + MemoryMarshal.AsBytes(value.AsSpan()).CopyTo(_buffer.AsSpan(_position, byteLen)); + _position += byteLen; + return; + } var charLength = value.Length; diff --git a/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs b/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs index c34167d..dc55d1c 100644 --- a/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs +++ b/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs @@ -1023,12 +1023,12 @@ public static partial class AcBinarySerializer } // FastWire: skip FixStr optimization (UTF-8 specific), write String marker + UTF-16 data - //if (context.FastWire) - //{ - // context.WriteByte(BinaryTypeCode.String); - // context.WriteStringUtf8(value); - // return; - //} + if (context.FastWire) + { + context.WriteByte(BinaryTypeCode.String); + context.WriteStringUtf8(value); + return; + } // Fast path for short strings: check length first (cheap), then ASCII // FixStr encodes type+length in single byte for strings <= 31 chars diff --git a/AyCode.Core/Serializers/Binaries/AcBinarySerializerOptions.cs b/AyCode.Core/Serializers/Binaries/AcBinarySerializerOptions.cs index 681e792..16d2b52 100644 --- a/AyCode.Core/Serializers/Binaries/AcBinarySerializerOptions.cs +++ b/AyCode.Core/Serializers/Binaries/AcBinarySerializerOptions.cs @@ -85,6 +85,13 @@ public sealed class AcBinarySerializerOptions : AcSerializerOptions public bool UseMetadata { get; set; } = false; public bool UseGeneratedCode { get; set; } = true; + /// + /// Wire encoding mode. + /// Compact: VarInt + UTF-8 (default, smaller output). + /// Fast: Fixed-width integers + UTF-16 (larger output, faster encode/decode). + /// + public WireMode WireMode { get; set; } = WireMode.Fast; + /// /// Controls how string interning is applied during serialization. /// None: No interning, all strings written inline. @@ -94,13 +101,6 @@ public sealed class AcBinarySerializerOptions : AcSerializerOptions /// public StringInterningMode UseStringInterning { get; set; } = StringInterningMode.Attribute; - /// - /// Wire encoding mode. - /// Compact: VarInt + UTF-8 (default, smaller output). - /// Fast: Fixed-width integers + UTF-16 (larger output, faster encode/decode). - /// - //public WireMode WireMode { get; set; } = WireMode.Compact; - /// /// When true, checks for duplicate property name hashes during serialization (UseMetadata mode). /// Throws exception if FNV-1a hash collision is detected between property names of the same type. diff --git a/AyCode.Core/Serializers/Binaries/BinaryTypeCode.cs b/AyCode.Core/Serializers/Binaries/BinaryTypeCode.cs index 7514f5c..a83c1be 100644 --- a/AyCode.Core/Serializers/Binaries/BinaryTypeCode.cs +++ b/AyCode.Core/Serializers/Binaries/BinaryTypeCode.cs @@ -44,7 +44,7 @@ internal static class BinaryTypeCode // Complex types (25-31) public const byte Object = 25; // Start of object (non-tracked OR first occurrence when ref tracking) - public const byte ObjectEnd = 26; // End of object marker + //public const byte ObjectEnd = 26; // UNUSED — property count is known at compile-time (SGen) or reflection-time (runtime), no end marker needed public const byte ObjectRef = 27; // Reference to previously serialized object (2+ occurrence) public const byte Array = 28; // Start of array/list public const byte Dictionary = 29; // Start of dictionary