diff --git a/crates/bindings-csharp/Runtime/Internal/ITable.cs b/crates/bindings-csharp/Runtime/Internal/ITable.cs index ed48106ef44..4878de71762 100644 --- a/crates/bindings-csharp/Runtime/Internal/ITable.cs +++ b/crates/bindings-csharp/Runtime/Internal/ITable.cs @@ -1,5 +1,6 @@ namespace SpacetimeDB.Internal; +using System.Buffers; using SpacetimeDB.BSATN; internal abstract class RawTableIterBase @@ -7,8 +8,9 @@ internal abstract class RawTableIterBase { public sealed class Enumerator(FFI.RowIter handle) : IDisposable { - byte[] buffer = new byte[0x20_000]; - public byte[] Current { get; private set; } = []; + private const int InitialBufferSize = 1024; + private byte[]? buffer = ArrayPool.Shared.Rent(InitialBufferSize); + public ArraySegment Current { get; private set; } = ArraySegment.Empty; public bool MoveNext() { @@ -17,6 +19,11 @@ public bool MoveNext() return false; } + if (buffer is null) + { + return false; + } + uint buffer_len; while (true) { @@ -38,11 +45,10 @@ public bool MoveNext() { // Iterator advanced and may also be `EXHAUSTED`. // When `OK`, we'll need to advance the iterator in the next call to `MoveNext`. - // In both cases, copy over the row data to `Current` from the scratch `buffer`. + // In both cases, update `Current` to point at the valid range in the scratch `buffer`. case Errno.EXHAUSTED or Errno.OK: - Current = new byte[buffer_len]; - Array.Copy(buffer, 0, Current, 0, buffer_len); + Current = new ArraySegment(buffer, 0, (int)buffer_len); return buffer_len != 0; // Couldn't find the iterator, error! case Errno.NO_SUCH_ITER: @@ -51,7 +57,8 @@ public bool MoveNext() // Grow `buffer` and try again. // The `buffer_len` will have been updated with the necessary size. case Errno.BUFFER_TOO_SMALL: - buffer = new byte[buffer_len]; + ArrayPool.Shared.Return(buffer); + buffer = ArrayPool.Shared.Rent((int)buffer_len); continue; default: throw new UnknownException(ret); @@ -66,6 +73,12 @@ public void Dispose() FFI.row_iter_bsatn_close(handle); handle = FFI.RowIter.INVALID; } + + if (buffer is not null) + { + ArrayPool.Shared.Return(buffer); + buffer = null; + } } public void Reset() @@ -87,7 +100,13 @@ public IEnumerable Parse() { foreach (var chunk in this) { - using var stream = new MemoryStream(chunk); + using var stream = new MemoryStream( + chunk.Array!, + chunk.Offset, + chunk.Count, + writable: false, + publiclyVisible: true + ); using var reader = new BinaryReader(stream); while (stream.Position < stream.Length) {