Skip to content

Commit

Permalink
Removed allocation of display class objects
Browse files Browse the repository at this point in the history
  • Loading branch information
sakno committed Dec 18, 2022
1 parent d05cf51 commit 39b7492
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 268 deletions.
52 changes: 27 additions & 25 deletions src/DotNext.IO/IO/FileReader.Binary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,18 @@ public ValueTask<T> ReadAsync<T>(CancellationToken token = default)
}
else
{
result = ReadSlowAsync();
result = ReadSlowAsync<T>(token);
}

return result;
}

async ValueTask<T> ReadSlowAsync()
{
using var buffer = MemoryAllocator.Allocate<byte>(Unsafe.SizeOf<T>(), exactSize: true);
await ReadBlockAsync(buffer.Memory, token).ConfigureAwait(false);
return MemoryMarshal.Read<T>(buffer.Span);
}
private async ValueTask<T> ReadSlowAsync<T>(CancellationToken token)
where T : unmanaged
{
using var buffer = MemoryAllocator.Allocate<byte>(Unsafe.SizeOf<T>(), exactSize: true);
await ReadBlockAsync(buffer.Memory, token).ConfigureAwait(false);
return MemoryMarshal.Read<T>(buffer.Span);
}

private int Read7BitEncodedInt()
Expand Down Expand Up @@ -272,7 +273,7 @@ public ValueTask<T> ParseAsync<T>(CancellationToken token = default)
{
try
{
result = new(Parse());
result = new(ParseFast<T>());
}
catch (Exception e)
{
Expand All @@ -281,29 +282,30 @@ public ValueTask<T> ParseAsync<T>(CancellationToken token = default)
}
else
{
result = ParseSlowAsync();
result = ParseSlowAsync<T>(token);
}

return result;
}

T Parse()
{
Debug.Assert(BufferLength >= T.Size);
private T ParseFast<T>()
where T : notnull, IBinaryFormattable<T>
{
Debug.Assert(BufferLength >= T.Size);

var reader = new SpanReader<byte>(BufferSpan.Slice(0, T.Size));
var result = T.Parse(ref reader);
Consume(reader.ConsumedCount);
length -= reader.ConsumedCount;
return result;
}
var reader = new SpanReader<byte>(BufferSpan.Slice(0, T.Size));
var result = T.Parse(ref reader);
Consume(reader.ConsumedCount);
length -= reader.ConsumedCount;
return result;
}

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
async ValueTask<T> ParseSlowAsync()
{
using var buffer = MemoryAllocator.Allocate<byte>(T.Size, exactSize: true);
await ReadBlockAsync(buffer.Memory, token).ConfigureAwait(false);
return IBinaryFormattable<T>.Parse(buffer.Span);
}
private async ValueTask<T> ParseSlowAsync<T>(CancellationToken token)
where T : notnull, IBinaryFormattable<T>
{
using var buffer = MemoryAllocator.Allocate<byte>(T.Size, exactSize: true);
await ReadBlockAsync(buffer.Memory, token).ConfigureAwait(false);
return IBinaryFormattable<T>.Parse(buffer.Span);
}

/// <summary>
Expand Down
47 changes: 24 additions & 23 deletions src/DotNext.IO/IO/FileReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ public void Consume(int bytes)
/// <exception cref="ObjectDisposedException">The reader has been disposed.</exception>
/// <exception cref="InternalBufferOverflowException">Internal buffer has no free space.</exception>
/// <exception cref="OperationCanceledException">The operation has been canceled.</exception>
[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
public async ValueTask<bool> ReadAsync(CancellationToken token = default)
{
ThrowIfDisposed();
Expand Down Expand Up @@ -215,34 +216,34 @@ public ValueTask<int> ReadAsync(Memory<byte> output, CancellationToken token = d
return new(0);

return HasBufferedData || output.Length < buffer.Length
? ReadBufferedAsync()
: ReadDirectAsync();

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
async ValueTask<int> ReadDirectAsync()
{
var count = await RandomAccess.ReadAsync(handle, output, fileOffset, token).ConfigureAwait(false);
fileOffset += count;
return count;
}
? ReadBufferedAsync(output, token)
: ReadDirectAsync(output, token);
}

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
async ValueTask<int> ReadBufferedAsync()
{
var result = 0;
[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
private async ValueTask<int> ReadDirectAsync(Memory<byte> output, CancellationToken token)
{
var count = await RandomAccess.ReadAsync(handle, output, fileOffset, token).ConfigureAwait(false);
fileOffset += count;
return count;
}

for (int writtenCount; !output.IsEmpty; output = output.Slice(writtenCount))
{
if (!HasBufferedData && !await ReadAsync(token).ConfigureAwait(false))
break;
[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
private async ValueTask<int> ReadBufferedAsync(Memory<byte> output, CancellationToken token)
{
var result = 0;

BufferSpan.CopyTo(output.Span, out writtenCount);
result += writtenCount;
Consume(writtenCount);
}
for (int writtenCount; !output.IsEmpty; output = output.Slice(writtenCount))
{
if (!HasBufferedData && !await ReadAsync(token).ConfigureAwait(false))
break;

return result;
BufferSpan.CopyTo(output.Span, out writtenCount);
result += writtenCount;
Consume(writtenCount);
}

return result;
}

/// <summary>
Expand Down
42 changes: 22 additions & 20 deletions src/DotNext.IO/IO/FileWriter.Binary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,28 +50,30 @@ public ValueTask WriteAsync<T>(T value, CancellationToken token = default)
}
else if (buffer.Length >= Unsafe.SizeOf<T>())
{
result = WriteSmallValueAsync();
result = WriteSmallValueAsync(value, token);
}
else
{
result = WriteLargeValueAsync();
result = WriteLargeValueAsync(value, token);
}

return result;
}

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))]
async ValueTask WriteSmallValueAsync()
{
await FlushCoreAsync(token).ConfigureAwait(false);
Write(in value);
}
[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))]
private async ValueTask WriteSmallValueAsync<T>(T value, CancellationToken token)
where T : unmanaged
{
await FlushCoreAsync(token).ConfigureAwait(false);
Write(in value);
}

async ValueTask WriteLargeValueAsync()
{
// rare case, T is very large and doesn't fit the buffer
using var buffer = Span.AsReadOnlyBytes(in value).Copy();
await WriteAsync(buffer.Memory, token).ConfigureAwait(false);
}
async ValueTask WriteLargeValueAsync<T>(T value, CancellationToken token)
where T : unmanaged
{
// rare case, T is very large and doesn't fit the buffer
using var buffer = Span.AsReadOnlyBytes(in value).Copy();
await WriteAsync(buffer.Memory, token).ConfigureAwait(false);
}

private void Write7BitEncodedInt(int value)
Expand Down Expand Up @@ -332,16 +334,16 @@ ValueTask IAsyncBinaryWriter.WriteAsync<TArg>(Action<TArg, IBufferWriter<byte>>
}
else
{
result = WriteSlowAsync();
result = WriteSlowAsync(writer, arg, token);
}

return result;
}

async ValueTask WriteSlowAsync()
{
await FlushCoreAsync(token).ConfigureAwait(false);
writer(arg, this);
}
private async ValueTask WriteSlowAsync<TArg>(Action<TArg, IBufferWriter<byte>> writer, TArg arg, CancellationToken token)
{
await FlushCoreAsync(token).ConfigureAwait(false);
writer(arg, this);
}

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,23 +109,21 @@ protected sealed override async ValueTask ProposeAsync(IClusterConfiguration con

/// <inheritdoc />
protected sealed override ValueTask ApplyAsync(CancellationToken token)
=> proposed is null ? ValueTask.CompletedTask : ApplyProposedAsync(token);

private async ValueTask ApplyProposedAsync(CancellationToken token)
{
return proposed is null ? ValueTask.CompletedTask : ApplyProposedAsync();
await CompareAsync(activeCache, proposedCache, token).ConfigureAwait(false);

async ValueTask ApplyProposedAsync()
{
await CompareAsync(activeCache, proposedCache, token).ConfigureAwait(false);
active?.Dispose();
active = proposed;
activeCache = proposedCache;

active?.Dispose();
active = proposed;
activeCache = proposedCache;
proposed = null;
proposedCache = proposedCache.Clear();

proposed = null;
proposedCache = proposedCache.Clear();

Interlocked.MemoryBarrierProcessWide();
OnActivated();
}
Interlocked.MemoryBarrierProcessWide();
OnActivated();
}

private MemoryOwner<byte> Encode(IReadOnlyDictionary<ClusterMemberId, TAddress> configuration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,21 +158,19 @@ protected sealed override async ValueTask ProposeAsync(IClusterConfiguration con

/// <inheritdoc/>
protected sealed override ValueTask ApplyAsync(CancellationToken token = default)
{
return proposed.IsEmpty ? ValueTask.CompletedTask : ApplyProposedAsync();
=> proposed.IsEmpty ? ValueTask.CompletedTask : ApplyProposedAsync(token);

async ValueTask ApplyProposedAsync()
{
await proposed.CopyToAsync(active, token).ConfigureAwait(false);
await CompareAsync(activeCache, proposedCache, token).ConfigureAwait(false);
activeCache = proposedCache;
private async ValueTask ApplyProposedAsync(CancellationToken token)
{
await proposed.CopyToAsync(active, token).ConfigureAwait(false);
await CompareAsync(activeCache, proposedCache, token).ConfigureAwait(false);
activeCache = proposedCache;

proposed.Clear();
proposedCache = proposedCache.Clear();
proposed.Clear();
proposedCache = proposedCache.Clear();

Interlocked.MemoryBarrierProcessWide();
OnActivated();
}
Interlocked.MemoryBarrierProcessWide();
OnActivated();
}

/// <inheritdoc/>
Expand Down
Loading

0 comments on commit 39b7492

Please sign in to comment.