Browse Source

Optimize Write(Span)

pull/1316/head
James Jackson-South 6 years ago
parent
commit
cd32a603d5
  1. 36
      src/ImageSharp/IO/ChunkedMemoryStream.cs

36
src/ImageSharp/IO/ChunkedMemoryStream.cs

@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.IO
if (value < 0) if (value < 0)
{ {
throw new ArgumentOutOfRangeException(nameof(value)); ThrowArgumentOutOfRange(nameof(value));
} }
// Back up current position in case new position is out of range // Back up current position in case new position is out of range
@ -167,12 +167,13 @@ namespace SixLabors.ImageSharp.IO
// Position is out of range // Position is out of range
this.readChunk = backupReadChunk; this.readChunk = backupReadChunk;
this.readOffset = backupReadOffset; this.readOffset = backupReadOffset;
throw new ArgumentOutOfRangeException(nameof(value)); ThrowArgumentOutOfRange(nameof(value));
} }
} }
} }
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override long Seek(long offset, SeekOrigin origin) public override long Seek(long offset, SeekOrigin origin)
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
@ -231,6 +232,7 @@ namespace SixLabors.ImageSharp.IO
} }
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int Read(byte[] buffer, int offset, int count) public override int Read(byte[] buffer, int offset, int count)
{ {
Guard.NotNull(buffer, nameof(buffer)); Guard.NotNull(buffer, nameof(buffer));
@ -243,6 +245,7 @@ namespace SixLabors.ImageSharp.IO
#if SUPPORTS_SPAN_STREAM #if SUPPORTS_SPAN_STREAM
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int Read(Span<byte> buffer) => this.ReadImpl(buffer); public override int Read(Span<byte> buffer) => this.ReadImpl(buffer);
#endif #endif
@ -303,6 +306,7 @@ namespace SixLabors.ImageSharp.IO
} }
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int ReadByte() public override int ReadByte()
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
@ -342,7 +346,17 @@ namespace SixLabors.ImageSharp.IO
} }
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Write(byte[] buffer, int offset, int count) public override void Write(byte[] buffer, int offset, int count)
=> this.WriteImpl(buffer.AsSpan().Slice(offset, count));
#if SUPPORTS_SPAN_STREAM
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Write(ReadOnlySpan<byte> buffer) => this.WriteImpl(buffer);
#endif
private void WriteImpl(ReadOnlySpan<byte> buffer)
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
@ -353,9 +367,10 @@ namespace SixLabors.ImageSharp.IO
this.writeOffset = 0; this.writeOffset = 0;
} }
byte[] chunkBuffer = this.writeChunk.Buffer.Array; Span<byte> chunkBuffer = this.writeChunk.Buffer.GetSpan();
int chunkSize = this.writeChunk.Length; int chunkSize = this.writeChunk.Length;
int count = buffer.Length;
int offset = 0;
while (count > 0) while (count > 0)
{ {
if (this.writeOffset == chunkSize) if (this.writeOffset == chunkSize)
@ -364,12 +379,13 @@ namespace SixLabors.ImageSharp.IO
this.writeChunk.Next = this.AllocateMemoryChunk(); this.writeChunk.Next = this.AllocateMemoryChunk();
this.writeChunk = this.writeChunk.Next; this.writeChunk = this.writeChunk.Next;
this.writeOffset = 0; this.writeOffset = 0;
chunkBuffer = this.writeChunk.Buffer.Array; chunkBuffer = this.writeChunk.Buffer.GetSpan();
chunkSize = this.writeChunk.Length; chunkSize = this.writeChunk.Length;
} }
int copyCount = Math.Min(count, chunkSize - this.writeOffset); int copyCount = Math.Min(count, chunkSize - this.writeOffset);
Buffer.BlockCopy(buffer, offset, chunkBuffer, this.writeOffset, copyCount); buffer.Slice(offset, copyCount).CopyTo(chunkBuffer.Slice(this.writeOffset));
offset += copyCount; offset += copyCount;
count -= copyCount; count -= copyCount;
this.writeOffset += copyCount; this.writeOffset += copyCount;
@ -493,9 +509,11 @@ namespace SixLabors.ImageSharp.IO
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowDisposed() private static void ThrowDisposed()
{ => throw new ObjectDisposedException(null, "The stream is closed.");
throw new ObjectDisposedException(null, "The stream is closed.");
} [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowArgumentOutOfRange(string value)
=> throw new ArgumentOutOfRangeException(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private MemoryChunk AllocateMemoryChunk() private MemoryChunk AllocateMemoryChunk()

Loading…
Cancel
Save