Refactor string read logic; remove UseGeneratedCode option

Refactored EmitReadString to use a switch for O(1) dispatch of string wire formats, improving performance and clarity. Updated comments to document the new approach and its benefits. Removed the UseGeneratedCode property from AcBinarySerializerOptions.
This commit is contained in:
Loretta 2026-03-01 07:22:13 +01:00
parent 7902922195
commit 0ff40a6777
2 changed files with 33 additions and 17 deletions

View File

@ -2020,6 +2020,11 @@ public class AcBinarySourceGenerator : IIncrementalGenerator
/// <summary> /// <summary>
/// Emits inline string read from type code. Handles all string wire formats. /// Emits inline string read from type code. Handles all string wire formats.
/// FixStr (range 34-65) is checked first as hot path for short strings.
/// Remaining codes use switch for O(1) JIT jump-table dispatch:
/// String=16, StringInterned=17, StringEmpty=18, StringInternFirst=19, Null=0.
/// This eliminates the sequential if-else chain that penalized StringInterned
/// (the hot path for repeated interned strings) with 4 comparisons.
/// </summary> /// </summary>
private static void EmitReadString(StringBuilder sb, string a, string tc, string i) private static void EmitReadString(StringBuilder sb, string a, string tc, string i)
{ {
@ -2029,24 +2034,36 @@ public class AcBinarySourceGenerator : IIncrementalGenerator
sb.AppendLine($"{i} var flen = BinaryTypeCode.DecodeFixStrLength({tc});"); sb.AppendLine($"{i} var flen = BinaryTypeCode.DecodeFixStrLength({tc});");
sb.AppendLine($"{i} {a} = flen == 0 ? string.Empty : context.ReadStringUtf8(flen);"); sb.AppendLine($"{i} {a} = flen == 0 ? string.Empty : context.ReadStringUtf8(flen);");
sb.AppendLine($"{i}}}"); sb.AppendLine($"{i}}}");
sb.AppendLine($"{i}else if ({tc} == BinaryTypeCode.String)"); // Switch gives O(1) dispatch via JIT jump table for codes 0, 16-19.
// StringInterned (17) is the hot path for repeated interned strings — no longer buried at 4th else-if.
sb.AppendLine($"{i}else switch ({tc})");
sb.AppendLine($"{i}{{"); sb.AppendLine($"{i}{{");
sb.AppendLine($"{i} var slen = (int)context.ReadVarUInt();"); sb.AppendLine($"{i} case BinaryTypeCode.StringInterned:");
sb.AppendLine($"{i} {a} = slen == 0 ? string.Empty : context.ReadStringUtf8(slen);"); sb.AppendLine($"{i} {a} = context.GetInternedString((int)context.ReadVarUInt());");
sb.AppendLine($"{i} break;");
sb.AppendLine($"{i} case BinaryTypeCode.String:");
sb.AppendLine($"{i} {{");
sb.AppendLine($"{i} var slen = (int)context.ReadVarUInt();");
sb.AppendLine($"{i} {a} = slen == 0 ? string.Empty : context.ReadStringUtf8(slen);");
sb.AppendLine($"{i} break;");
sb.AppendLine($"{i} }}");
sb.AppendLine($"{i} case BinaryTypeCode.StringInternFirst:");
sb.AppendLine($"{i} {{");
sb.AppendLine($"{i} context.DisableStringCaching();");
sb.AppendLine($"{i} var sci = (int)context.ReadVarUInt();");
sb.AppendLine($"{i} var slen2 = (int)context.ReadVarUInt();");
sb.AppendLine($"{i} var sv = slen2 == 0 ? string.Empty : context.ReadStringUtf8(slen2);");
sb.AppendLine($"{i} context.RegisterInternedValueAt(sci, sv);");
sb.AppendLine($"{i} {a} = sv;");
sb.AppendLine($"{i} break;");
sb.AppendLine($"{i} }}");
sb.AppendLine($"{i} case BinaryTypeCode.Null:");
sb.AppendLine($"{i} {a} = null;");
sb.AppendLine($"{i} break;");
sb.AppendLine($"{i} case BinaryTypeCode.StringEmpty:");
sb.AppendLine($"{i} {a} = string.Empty;");
sb.AppendLine($"{i} break;");
sb.AppendLine($"{i}}}"); sb.AppendLine($"{i}}}");
sb.AppendLine($"{i}else if ({tc} == BinaryTypeCode.StringInternFirst)");
sb.AppendLine($"{i}{{");
sb.AppendLine($"{i} context.DisableStringCaching();");
sb.AppendLine($"{i} var sci = (int)context.ReadVarUInt();");
sb.AppendLine($"{i} var slen2 = (int)context.ReadVarUInt();");
sb.AppendLine($"{i} var sv = slen2 == 0 ? string.Empty : context.ReadStringUtf8(slen2);");
sb.AppendLine($"{i} context.RegisterInternedValueAt(sci, sv);");
sb.AppendLine($"{i} {a} = sv;");
sb.AppendLine($"{i}}}");
sb.AppendLine($"{i}else if ({tc} == BinaryTypeCode.StringInterned)");
sb.AppendLine($"{i} {a} = context.GetInternedString((int)context.ReadVarUInt());");
sb.AppendLine($"{i}else if ({tc} == BinaryTypeCode.Null) {a} = null;");
sb.AppendLine($"{i}else if ({tc} == BinaryTypeCode.StringEmpty) {a} = string.Empty;");
} }
/// <summary> /// <summary>

View File

@ -83,7 +83,6 @@ public sealed class AcBinarySerializerOptions : AcSerializerOptions
/// Default: false (no overhead) /// Default: false (no overhead)
/// </summary> /// </summary>
public bool UseMetadata { get; set; } = false; public bool UseMetadata { get; set; } = false;
public bool UseGeneratedCode { get; set; } = true; public bool UseGeneratedCode { get; set; } = true;
/// <summary> /// <summary>