diff --git a/src/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs b/src/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs index 90e18a452658..a2dd35c013ab 100644 --- a/src/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs +++ b/src/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs @@ -42,7 +42,9 @@ public sealed partial class Pipe private readonly PipeScheduler _readerScheduler; private readonly PipeScheduler _writerScheduler; + private int _pooledSegmentCount; private readonly BufferSegment[] _bufferSegmentPool; + private readonly BufferSegment[] _bufferSegmentsToReturn; private readonly DefaultPipeReader _reader; private readonly DefaultPipeWriter _writer; @@ -52,7 +54,6 @@ public sealed partial class Pipe private long _length; private long _currentWriteLength; - private int _pooledSegmentCount; private PipeAwaitable _readerAwaitable; private PipeAwaitable _writerAwaitable; @@ -97,6 +98,7 @@ public Pipe(PipeOptions options) } _bufferSegmentPool = new BufferSegment[SegmentPoolSize]; + _bufferSegmentsToReturn = new BufferSegment[SegmentPoolSize]; _operationState = default; _readerCompletion = default; @@ -257,25 +259,39 @@ private void ReturnSegments(BufferSegment from, BufferSegment toExclusive) Debug.Assert(from != null); Debug.Assert(from != toExclusive); + // Reset the Segments and return their data out of lock + BufferSegment[] segmentToReturn = _bufferSegmentsToReturn; + int count = 0; + do + { + BufferSegment next = from.NextSegment; + Debug.Assert(next != null || toExclusive == null); + + from.ResetMemory(); + + if ((uint)count < (uint)segmentToReturn.Length) + { + segmentToReturn[count] = from; + count++; + } + + from = next; + } while (from != toExclusive); + + // Add the Segments back to pool under lock BufferSegment[] segmentPool = _bufferSegmentPool; lock (segmentPool) { int index = _pooledSegmentCount; - do + for (int i = 0; i < count; i++) { - BufferSegment next = from.NextSegment; - Debug.Assert(next != null || toExclusive == null); - - from.ResetMemory(); - if ((uint)index < (uint)segmentPool.Length) { - segmentPool[index] = from; + segmentPool[index] = segmentToReturn[i]; index++; } - - from = next; - } while (from != toExclusive); + segmentToReturn[i] = null; + } _pooledSegmentCount = index; } @@ -786,9 +802,12 @@ private void CompletePipe() _readTail = null; } - if (segment != null) + while (segment != null) { - ReturnSegments(segment, toExclusive: null); + BufferSegment returnSegment = segment; + segment = segment.NextSegment; + + returnSegment.ResetMemory(); } }