Wykorzystanie pamięci szeregowanie podzielonych tablic bajtów za pomocą protokołu Protobuf-net

W naszej aplikacji mamy pewne struktury danych, które między innymi zawierają podzieloną listę bajtów (obecnie wyświetlaną jakoList<byte[]>). Rozdzielamy bajty, ponieważ jeśli pozwolimy na umieszczenie tablic bajtów na stercie dużych obiektów, to z czasem cierpimy na fragmentację pamięci.

Zaczęliśmy również używać Protobuf-net do serializacji tych struktur, używając naszego własnego generowanego DLL serializacji.

Zauważyliśmy jednak, że Protobuf-net tworzy bardzo duże bufory w pamięci podczas serializacji. Spoglądając przez kod źródłowy, wydaje się, że być może nie jest w stanie opróżnić wewnętrznego bufora do końcaList<byte[]>&nbsp;struktura została napisana, ponieważ później musi zapisać całkowitą długość z przodu bufora.

To niestety unieważnia naszą pracę z dzieleniem bajtów w pierwszej kolejności i ostatecznie daje nam OutOfMemoryExceptions z powodu fragmentacji pamięci (wyjątek występuje w momencie, gdy Protobuf-net próbuje rozszerzyć bufor do ponad 84k, co oczywiście umieszcza go na LOH, a nasze ogólne wykorzystanie pamięci procesowej jest dość niskie).

Jeśli moja analiza działania Protobuf-net jest poprawna, czy istnieje sposób na rozwiązanie tego problemu?

Aktualizacja

Na podstawie odpowiedzi Marca oto, co próbowałem:

[ProtoContract]
[ProtoInclude(1, typeof(A), DataFormat = DataFormat.Group)]
public class ABase
{
}

[ProtoContract]
public class A : ABase
{
    [ProtoMember(1, DataFormat = DataFormat.Group)]
    public B B
    {
        get;
        set;
    }
}

[ProtoContract]
public class B
{
    [ProtoMember(1, DataFormat = DataFormat.Group)]
    public List<byte[]> Data
    {
        get;
        set;
    }
}

Następnie, aby go serializować:

var a = new A();
var b = new B();
a.B = b;
b.Data = new List<byte[]>
{
    Enumerable.Range(0, 1999).Select(v => (byte)v).ToArray(),
    Enumerable.Range(2000, 3999).Select(v => (byte)v).ToArray(),
};

var stream = new MemoryStream();
Serializer.Serialize(stream, a);

Jeśli jednak włożę punkt przerwaniaProtoWriter.WriteBytes()&nbsp;gdzie dzwoniDemandSpace()&nbsp;w kierunku dolnej części metody i wkrocz do niejDemandSpace(), Widzę, że bufor nie jest opróżniany, ponieważwriter.flushLock&nbsp;równa się1.

Jeśli utworzę inną klasę bazową dla ABase w ten sposób:

[ProtoContract]
[ProtoInclude(1, typeof(ABase), DataFormat = DataFormat.Group)]
public class ABaseBase
{
}

[ProtoContract]
[ProtoInclude(1, typeof(A), DataFormat = DataFormat.Group)]
public class ABase : ABaseBase
{
}

Następniewriter.flushLock&nbsp;równa się2&nbsp;wDemandSpace().

Zgaduję, że istnieje oczywisty krok, którego brakowało mi tutaj w przypadku typów pochodnych?