В последнее время я работаю с System.Buffers
и, в частности, с классом * 1002. *
У меня есть структура примитивов, определенная следующим образом:
[StructLayout(LayoutKind.Sequential,Pack =1,CharSet=CharSet.Unicode)]
public partial struct MessageHeader
{
public MessageVersion Version;
...
И я могу Передайте это назад и вперед по сети без каких-либо проблем, и я использую для этого System.IO.Pipelines
.
Преобразование ReadOnlySequence<byte>
обратно в структуру вызвало некоторые головные боли.
Я начал с этим:
private void ExtractMessageHeaderOld(ReadOnlySequence<byte> ros, out MessageHeader messageHeader)
{
var x = ros.ToArray<byte>();
ReadOnlySpan<MessageHeader> mhSpan = MemoryMarshal.Cast<byte, MessageHeader>(x);
messageHeader = mhSpan[0];
}
, который создал тысячи маленьких байтовых [] массивов в течение жизни сервера (что само по себе не является проблемой), но со всем остальным система пытается Это немного увеличивает давление на G C.
Так что я перешел к использованию:
private void ExtractMessageHeader(ReadOnlySequence<byte> ros, out MessageHeader messageHeader, ref byte[] workingSpace)
{
var i = 0;
foreach (var rom in ros)
foreach (var b in rom.Span)
{
workingSpace[i] = b;
i++;
}
ReadOnlySpan<MessageHeader> mhSpan = MemoryMarshal.Cast<byte, MessageHeader>(workingSpace);
messageHeader = mhSpan[0];
}
Это не делает никаких выделений памяти, но я просто чувствую как будто должен быть лучший способ.
Циклы foreach
и MemoryMarshal.Cast()
в messageHeader[1]
, так что я могу извлечь элемент 0, это что-то вроде хака, на который я случайно наткнулся, читая источник.
Я не могу найти API для чистого извлечения содержимое ReadOnlySequence<bytes>
в messageHeader
, и пока то, что у меня есть, работает, я просто чувствую, что оно должно существовать ...
Редактировать 1:
Я только что наткнулся на BuffersExtensions.CopyTo<T>(ReadOnlySequence<T>, Span<T>)
, который может заменить петли foreach на.
ros.CopyTo(workingSpace);