Vectors - jamescourtney/FlatSharp GitHub Wiki

FlatBuffers supports vectors (lists) through the general syntax of:

table SomeTable
{
   some_vector : [ SomeType ];
}

FlatSharp supports the following types for Vectors:

  • IList<T> / IReadOnlyList<T>
  • Memory<byte> / ReadOnlyMemory<byte>
  • Indexed Vectors

This page attempts to provide some detail on when it is appropriate to choose each type of vector.

The general guidance, however, is to use IList and IReadOnlyList, which provide a balance between performance and the principle of least surprise.

However, there are always exceptions:

  • You need Key/Value lookups. In this case, refer to Indexed Vectors.
  • You need to map a chunk of the input buffer as raw bytes without copying (perhaps a nested flat buffer or a large vector). In this case, use a Memory<byte> vector. This will generally point to a location in the input buffer without any copies.

This discussion on the rest of the page is heavily related to the concept of Deserialization Modes. The reader is assumed to have digested the contents of that article before reading the rest of this one.

Lists

By virtue of interfaces, IList<T> and IReadOnlyList<T> give FlatSharp lots of flexibility to satisfy the requested deserialization option in a non-surprising way. FlatSharp provides an implementation of IList<T> that sits directly on top of an IInputBuffer and allows lazy index-based access.

Deserialization Mode Behavior Actual Type
Lazy Elements are instantiated on-demand. A new T() is created for each element accessed. FlatBufferVectorBase<A, B, C>
Progressive Items are allocated as they are accessed and cached. Uses a sparse array internally. FlatBufferProgressiveVector<A, B, C>
Greedy New Array allocated and recursively initialized at deserialization time. The elements of the array are greedily initialized. FlatSharp.Internal.ImmutableList<T>
GreedyMutable Same as Greedy. List<T>

Lists are great choices for nearly all scenarios, match developer expections about deserialization behavior, and are fast-enough for most cases. Unless the buffer contains binary vectors or small vectors that need very fast access, it is recommended to use lists.

Memory

FlatSharp exposes a final kind of vector: Memory<byte> and ReadOnlyMemory<byte>. These two are special because they allow returning a reference into the IInputBuffer used to deserialize the original object.

Deserialization Mode Behavior
Lazy A Memory<byte> is returned that points into the original IInputBuffer.
Progressive A Memory<byte> is returned that points into the original IInputBuffer.
Greedy A copy of the IInputBuffer segment containing the memory is performed. The copy is returned.
GreedyMutable A copy of the IInputBuffer segment containing the memory is performed. The copy is returned.
attribute "fs_serializer";

table Packet (fs_serializer:"Lazy") {
   source : string;
   destination : string;
   message_kind : string;

   // ubyte vectors are treated as Memory<byte> by default
   nested_flat_buffer : [ ubyte ];
}

table Payload (fs_serializer:"Lazy") {
   ...
}
byte[] message = ...;
var packet = Packet.Serializer.Parse<Packet>(message);
var payload = SomethingElse.Serializer.Parse(packet.NestedFlatBuffer); // this points into the original "message" array. No copies necessary!

When to consider Memory:

Your vector carries large binary payloads, such as files, compressed data, images, or nested FlatBuffers that you wish to avoid copying. Memory provides the ultimate in efficiency by pointing into the original buffer.

When to avoid Memory:

Because Memory<byte> is a pointer into the original input buffer, any modifications made will be written back to the original input buffer. This can be great for some scenarios, but may lead to erroneous behavior if the developer is unaware of this quirk. It is not dissimilar to the WriteThrough feature that FlatSharp offers.

Additionally, you will see a runtime exception when accessing a Memory<byte> vector when using a ReadOnlyMemoryInputBuffer. Consider a ReadOnlyMemory<byte> vector if you need to use ReadOnlyMemoryInputBuffer.

⚠️ **GitHub.com Fallback** ⚠️