fixup SliceMemoryManager

pull/19792/head
Jan Tattermusch 5 years ago
parent 66cd7cbb8f
commit 532bdf7cd2
  1. 74
      src/csharp/Grpc.Core/Internal/SliceMemoryManager.cs

@ -24,64 +24,42 @@ using System.Buffers;
namespace Grpc.Core.Internal
{
internal class ReusableSliceBuffer
// Allow creating instances of Memory<byte> from Slice.
// Represents a chunk of native memory, but doesn't manage its lifetime.
// Instances of this class are reuseable - they can be reset to point to a different memory chunk.
// That is important to make the instances cacheable (rather then creating new instances
// the old ones will be reused to reduce GC pressure).
internal class SliceMemoryManager : MemoryManager<byte>
{
public const int MaxCachedSegments = 1024; // ~4MB payload for 4K slices
private Slice slice;
readonly SliceSegment[] cachedSegments = new SliceSegment[MaxCachedSegments];
int populatedSegmentCount;
public ReadOnlySequence<byte> PopulateFrom(IBufferReader bufferReader)
public void Reset(Slice slice)
{
populatedSegmentCount = 0;
long offset = 0;
SliceSegment prevSegment = null;
while (bufferReader.TryGetNextSlice(out Slice slice))
{
// Initialize cached segment if still null or just allocate a new segment if we already reached MaxCachedSegments
var current = populatedSegmentCount < cachedSegments.Length ? cachedSegments[populatedSegmentCount] : new SliceSegment();
if (current == null)
{
current = cachedSegments[populatedSegmentCount] = new SliceSegment();
}
current.Reset(slice, offset);
prevSegment?.SetNext(current);
this.slice = slice;
}
populatedSegmentCount ++;
offset += slice.Length;
prevSegment = current;
}
public void Reset()
{
Reset(new Slice(IntPtr.Zero, 0));
}
// Not necessary for ending the ReadOnlySequence, but for making sure we
// don't keep more than MaxCachedSegments alive.
prevSegment?.SetNext(null);
public override Span<byte> GetSpan()
{
return slice.ToSpanUnsafe();
}
if (populatedSegmentCount == 0)
{
return ReadOnlySequence<byte>.Empty;
}
public override MemoryHandle Pin(int elementIndex = 0)
{
throw new NotSupportedException();
}
var firstSegment = cachedSegments[0];
var lastSegment = prevSegment;
return new ReadOnlySequence<byte>(firstSegment, 0, lastSegment, lastSegment.Memory.Length);
public override void Unpin()
{
}
public void Invalidate()
protected override void Dispose(bool disposing)
{
if (populatedSegmentCount == 0)
{
return;
}
var segment = cachedSegments[0];
while (segment != null)
{
segment.Reset(new Slice(IntPtr.Zero, 0), 0);
var nextSegment = (SliceSegment) segment.Next;
segment.SetNext(null);
segment = nextSegment;
}
populatedSegmentCount = 0;
// NOP
}
}
}

Loading…
Cancel
Save