Perf. opt.

This commit is contained in:
Christian Köllner 2020-02-17 21:23:44 +01:00
parent 37d642c249
commit 686dfeba52
2 changed files with 40 additions and 21 deletions

View File

@ -7,7 +7,7 @@ using System.Text;
namespace Capnp namespace Capnp
{ {
/// <summary> /// <summary>
/// ListDeserializer specialization for List(Int*), List(UInt*), List(Float*), and List(Enum). /// ListDeserializer specialization for unmanaged primitive types (including enum).
/// </summary> /// </summary>
/// <typeparam name="T">List element type</typeparam> /// <typeparam name="T">List element type</typeparam>
public class ListOfPrimitivesDeserializer<T>: ListDeserializer, IReadOnlyList<T> public class ListOfPrimitivesDeserializer<T>: ListDeserializer, IReadOnlyList<T>
@ -84,7 +84,10 @@ namespace Capnp
/// </summary> /// </summary>
public override ListKind Kind => _kind; public override ListKind Kind => _kind;
ReadOnlySpan<T> Data => MemoryMarshal.Cast<ulong, T>(State.CurrentSegment.Slice(State.Offset)).Slice(0, Count); /// <summary>
/// Retrieves the underlying memory span of this object
/// </summary>
public ReadOnlySpan<T> Span => MemoryMarshal.Cast<ulong, T>(State.CurrentSegment.Slice(State.Offset)).Slice(0, Count);
/// <summary> /// <summary>
/// Returns the element at given index. /// Returns the element at given index.
@ -92,7 +95,7 @@ namespace Capnp
/// <param name="index">Element index</param> /// <param name="index">Element index</param>
/// <returns>Element value</returns> /// <returns>Element value</returns>
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of range.</exception> /// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of range.</exception>
public T this[int index] => Data[index]; public T this[int index] => Span[index];
ListOfPrimitivesDeserializer<U> PrimitiveCast<U>() where U: unmanaged ListOfPrimitivesDeserializer<U> PrimitiveCast<U>() where U: unmanaged
{ {
@ -202,7 +205,7 @@ namespace Capnp
/// <exception cref="NotSupportedException">Element size is different from 1 byte.</exception> /// <exception cref="NotSupportedException">Element size is different from 1 byte.</exception>
public override string CastText() public override string CastText()
{ {
var utf8Bytes = PrimitiveCast<byte>().Data; var utf8Bytes = PrimitiveCast<byte>().Span;
if (utf8Bytes.Length == 0) return string.Empty; if (utf8Bytes.Length == 0) return string.Empty;
var utf8GytesNoZterm = utf8Bytes.Slice(0, utf8Bytes.Length - 1); var utf8GytesNoZterm = utf8Bytes.Slice(0, utf8Bytes.Length - 1);
return Encoding.UTF8.GetString(utf8GytesNoZterm.ToArray()); return Encoding.UTF8.GetString(utf8GytesNoZterm.ToArray());

View File

@ -6,13 +6,13 @@ using System.Runtime.InteropServices;
namespace Capnp namespace Capnp
{ {
/// <summary> /// <summary>
/// SerializerState specialization for List(Int*), List(UInt*), List(Float*), and List(Enum). /// SerializerState specialization for unmanaged primitive types (including enum).
/// </summary> /// </summary>
/// <typeparam name="T">List element type, must be primitive. Static constructor will throw if the type does not work.</typeparam> /// <typeparam name="T">List element type, must be primitive. Static constructor will throw if the type does not work.</typeparam>
public class ListOfPrimitivesSerializer<T> : public class ListOfPrimitivesSerializer<T> :
SerializerState, SerializerState,
IReadOnlyList<T> IReadOnlyList<T>
where T : struct where T : unmanaged
{ {
static readonly int ElementSize; static readonly int ElementSize;
@ -28,7 +28,10 @@ namespace Capnp
} }
} }
Span<T> Data => MemoryMarshal.Cast<ulong, T>(RawData); /// <summary>
/// Retrieves the underlying memory span of the represented items.
/// </summary>
public Span<T> Span => MemoryMarshal.Cast<ulong, T>(RawData);
/// <summary> /// <summary>
/// Gets or sets the value at given index. /// Gets or sets the value at given index.
@ -37,8 +40,8 @@ namespace Capnp
/// <returns>Element value</returns> /// <returns>Element value</returns>
public T this[int index] public T this[int index]
{ {
get => Data[index]; get => Span[index];
set => Data[index] = value; set => Span[index] = value;
} }
/// <summary> /// <summary>
@ -78,25 +81,38 @@ namespace Capnp
Init(items.Count); Init(items.Count);
if (items is T[] array) switch (items)
{
array.CopyTo(Data);
}
else
{ {
case T[] array:
array.CopyTo(Span);
break;
case ArraySegment<T> segment:
segment.AsSpan().CopyTo(Span);
break;
case ListOfPrimitivesDeserializer<T> deser:
deser.Span.CopyTo(Span);
break;
case ListOfPrimitivesSerializer<T> ser:
ser.Span.CopyTo(Span);
break;
default:
for (int i = 0; i < items.Count; i++) for (int i = 0; i < items.Count; i++)
{ {
this[i] = items[i]; this[i] = items[i];
} }
break;
} }
} }
/// <summary> /// <summary>
/// Implements <see cref="IEnumerable{T}"/>. /// Implements <see cref="IEnumerable{T}"/>.
/// </summary> /// </summary>
/// <returns></returns> public IEnumerator<T> GetEnumerator() => (IEnumerator<T>)Span.ToArray().GetEnumerator();
public IEnumerator<T> GetEnumerator() => (IEnumerator<T>)Data.ToArray().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Data.ToArray().GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => Span.ToArray().GetEnumerator();
} }
} }