From c9911a9b537c76633c54f6d9f0d49318756cc58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JasonXuDeveloper=20-=20=E5=82=91?= Date: Mon, 11 Nov 2024 17:09:13 +1100 Subject: [PATCH] release v2.1.9 ## Nino.Serialization v2.1.9 - [Optimization] Faster deserialization --- src/Nino.Core/Reader.cs | 32 +++++++++---------- .../EmbedTypeDeserializerGenerator.cs | 10 +++--- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/Nino.Core/Reader.cs b/src/Nino.Core/Reader.cs index 9bb7812..030b3cf 100644 --- a/src/Nino.Core/Reader.cs +++ b/src/Nino.Core/Reader.cs @@ -17,7 +17,7 @@ public Reader(Span buffer) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Read(out T value) where T : unmanaged { - value = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(_data)); + value = Unsafe.ReadUnaligned(ref _data[0]); _data = _data.Slice(Unsafe.SizeOf()); } @@ -52,13 +52,12 @@ public void Read(out T[] ret) where T : unmanaged Read(out int length); GetBytes(length * Unsafe.SizeOf(), out var bytes); #if NET5_0_OR_GREATER - ret = bytes.Length > 2048 ? GC.AllocateUninitializedArray(length) : new T[length]; - Span span = ret; - Span byteSpan = MemoryMarshal.Cast(span); - Unsafe.CopyBlockUnaligned(ref byteSpan[0], ref bytes[0], (uint)bytes.Length); + ret = bytes.Length <= 2048 ? new T[length] : GC.AllocateUninitializedArray(length); #else - ret = MemoryMarshal.Cast(bytes).ToArray(); + ret = new T[length]; #endif + ref byte first = ref Unsafe.As(ref ret[0]); + Unsafe.CopyBlockUnaligned(ref first, ref bytes[0], (uint)bytes.Length); return; default: throw new InvalidOperationException($"Invalid type id {typeId}"); @@ -101,19 +100,17 @@ public void Read(out List ret) where T : unmanaged case TypeCollector.CollectionTypeId: Read(out int length); GetBytes(length * Unsafe.SizeOf(), out var bytes); - ret = new List(length); -#if NET5_0_OR_GREATER + ret = new List(); ref var lst = ref Unsafe.As, TypeCollector.ListView>(ref ret); lst._size = length; - Span byteSpan = MemoryMarshal.Cast(lst._items); - Unsafe.CopyBlockUnaligned(ref byteSpan[0], ref bytes[0], (uint)bytes.Length); +#if NET5_0_OR_GREATER + var arr = bytes.Length <= 2048 ? new T[length] : GC.AllocateUninitializedArray(length); #else - ReadOnlySpan span = MemoryMarshal.Cast(bytes); - for (int i = 0; i < length; i++) - { - ret.Add(span[i]); - } + var arr = new T[length]; #endif + ref byte first = ref Unsafe.As(ref arr[0]); + Unsafe.CopyBlockUnaligned(ref first, ref bytes[0], (uint)bytes.Length); + lst._items = arr; return; default: @@ -207,7 +204,10 @@ public void Read(out string ret) Read(out int length); GetBytes(length * sizeof(char), out var bytes); #if NET5_0_OR_GREATER - ret = new string(MemoryMarshal.Cast(bytes)); + ret = new string( + MemoryMarshal.CreateReadOnlySpan( + ref Unsafe.As(ref bytes[0]), + length)); #else ret = MemoryMarshal.Cast(bytes).ToString(); #endif diff --git a/src/Nino.Generator/EmbedTypeDeserializerGenerator.cs b/src/Nino.Generator/EmbedTypeDeserializerGenerator.cs index 443e6f3..ce986a8 100644 --- a/src/Nino.Generator/EmbedTypeDeserializerGenerator.cs +++ b/src/Nino.Generator/EmbedTypeDeserializerGenerator.cs @@ -256,7 +256,7 @@ bool IsTypeParameter(ITypeSymbol typeSymbol) { var elemType = ((IArrayTypeSymbol)type).ElementType.ToDisplayString(); if (addedElemType.Add(elemType)) - sb.AppendLine(GenerateArrayCollectionSerialization( + sb.AppendLine(GenerateArraySerialization( ((IArrayTypeSymbol)type).ElementType.GetDeserializePrefix(), elemType, " ")); sb.GenerateClassDeserializeMethods(typeFullName); @@ -268,7 +268,7 @@ bool IsTypeParameter(ITypeSymbol typeSymbol) { var elemType = s.TypeArguments[0].ToDisplayString(); if (addedElemType.Add(elemType)) - sb.AppendLine(GenerateArrayCollectionSerialization(s.TypeArguments[0].GetDeserializePrefix(), + sb.AppendLine(GenerateArraySerialization(s.TypeArguments[0].GetDeserializePrefix(), elemType, " ")); if (type.TypeKind != TypeKind.Interface) @@ -323,7 +323,7 @@ public static partial class Deserializer context.AddSource("NinoDeserializerExtension.Ext.g.cs", code); } - private static string GenerateArrayCollectionSerialization(string prefix, string elemType, string indent) + private static string GenerateArraySerialization(string prefix, string elemType, string indent) { var creationDecl = elemType.EndsWith("[]") ? elemType.Insert(elemType.IndexOf("[]", StringComparison.Ordinal), "[length]") @@ -342,9 +342,11 @@ public static void Deserialize(out {{elemType}}[] value, ref Reader reader) case TypeCollector.CollectionTypeId: reader.Read(out int length); value = new {{creationDecl}}; + var span = value.AsSpan(); for (int i = 0; i < length; i++) { - {{prefix}}(out value[i], ref reader); + {{prefix}}(out {{elemType}} val, ref reader); + span[i] = val; } break; default: