Skip to content

Commit

Permalink
Release 2.2.0: Update version and documentation (#207)
Browse files Browse the repository at this point in the history
* Update documentation and version

* Re-generated using latest xmldocmd (2.7.0)

Co-authored-by: Ben Watson <bewatson@microsoft.com>
  • Loading branch information
benmwatson and Ben Watson committed Oct 6, 2021
1 parent 36b471a commit 667bec5
Show file tree
Hide file tree
Showing 111 changed files with 526 additions and 409 deletions.
28 changes: 28 additions & 0 deletions CHANGES.md
@@ -1,3 +1,31 @@
# Version 2.2.0

API changes:
* Add an override for `GetStream` that takes a `ReadOnlySpan<byte>`. This supercedes the versions of `GetStream` that take `Memory<byte>`, which were marked as `[Obsolete]`.

Bug Fixes:
* Fixed: `GetReadOnlySequence()` throws `ArgumentOutOfRangeException`

Performance Improvements:
* Removed enumerator allocation when returning blocks to the pool.
* Changed default size of stream's block list to 0 because `EnsureCapacity` will always run, potentially resizing the list anyway.
* Removed unneeded closure allocation when copying buffers.
* Use `GC.AllocateUninitializedArray` in an additional spot, for better performance in .NET 5+.

Documentation:
* Improved documentation, standardized puncutation, fixed code formatting.

# Version 2.1.3

Bug Fixes:
* Fixed another integer overflow error when returning buffers to the pool.

# Version 2.1.2

Bug Fixes:
* Added `[SecurityRules(SecurityRuyleSet.Level1)]` to assembly to allow more relaxed inheritance security rules.
* Fixed an integer overflow when calculating large buffer sizes.

# Version 2.1.0

* Added `RecyclableMemoryStreamManager` constructor overloads that take parameters for specifying the maximum free pool sizes. Updated IntelliSense documentation to make clear that these values need to be explciitly set to avoid unbounded pool growth.
Expand Down
4 changes: 2 additions & 2 deletions docs/Microsoft.IO.RecyclableMemoryStream.md
Expand Up @@ -4,7 +4,7 @@

| public type | description |
| --- | --- |
| class [RecyclableMemoryStream](Microsoft.IO/RecyclableMemoryStream.md) | MemoryStream implementation that deals with pooling and managing memory streams which use potentially large buffers. |
| class [RecyclableMemoryStreamManager](Microsoft.IO/RecyclableMemoryStreamManager.md) | Manages pools of [`RecyclableMemoryStream`](Microsoft.IO/RecyclableMemoryStream.md) objects. |
| class [RecyclableMemoryStream](./Microsoft.IO/RecyclableMemoryStream.md) | MemoryStream implementation that deals with pooling and managing memory streams which use potentially large buffers. |
| class [RecyclableMemoryStreamManager](./Microsoft.IO/RecyclableMemoryStreamManager.md) | Manages pools of [`RecyclableMemoryStream`](./Microsoft.IO/RecyclableMemoryStream.md) objects. |

<!-- DO NOT EDIT: generated by xmldocmd for Microsoft.IO.RecyclableMemoryStream.dll -->
36 changes: 18 additions & 18 deletions docs/Microsoft.IO/RecyclableMemoryStream.md
Expand Up @@ -10,32 +10,32 @@ public sealed class RecyclableMemoryStream : MemoryStream, IBufferWriter<byte>

| name | description |
| --- | --- |
| [RecyclableMemoryStream](RecyclableMemoryStream/RecyclableMemoryStream.md)(…) | Allocate a new RecyclableMemoryStream object. (8 constructors) |
| override [CanRead](RecyclableMemoryStream/CanRead.md) { get; } | Whether the stream can currently read |
| override [CanSeek](RecyclableMemoryStream/CanSeek.md) { get; } | Whether the stream can currently seek |
| override [CanTimeout](RecyclableMemoryStream/CanTimeout.md) { get; } | Always false |
| override [CanWrite](RecyclableMemoryStream/CanWrite.md) { get; } | Whether the stream can currently write |
| override [Capacity](RecyclableMemoryStream/Capacity.md) { getset; } | Gets or sets the capacity |
| [RecyclableMemoryStream](RecyclableMemoryStream/RecyclableMemoryStream.md)(…) | Initializes a new instance of the [`RecyclableMemoryStream`](./RecyclableMemoryStream.md) class. (8 constructors) |
| override [CanRead](RecyclableMemoryStream/CanRead.md) { get; } | Whether the stream can currently read. |
| override [CanSeek](RecyclableMemoryStream/CanSeek.md) { get; } | Whether the stream can currently seek. |
| override [CanTimeout](RecyclableMemoryStream/CanTimeout.md) { get; } | Always false. |
| override [CanWrite](RecyclableMemoryStream/CanWrite.md) { get; } | Whether the stream can currently write. |
| override [Capacity](RecyclableMemoryStream/Capacity.md) { getset; } | Gets or sets the capacity. |
| [Capacity64](RecyclableMemoryStream/Capacity64.md) { getset; } | Returns a 64-bit version of capacity, for streams larger than `int.MaxValue` in length. |
| override [Length](RecyclableMemoryStream/Length.md) { get; } | Gets the number of bytes written to this stream. |
| override [Position](RecyclableMemoryStream/Position.md) { getset; } | Gets the current position in the stream |
| [Advance](RecyclableMemoryStream/Advance.md)(…) | Notifies the stream that *count* bytes were written to the buffer returned by [`GetMemory`](RecyclableMemoryStream/GetMemory.md) or [`GetSpan`](RecyclableMemoryStream/GetSpan.md). Seeks forward by *count* bytes. |
| override [Close](RecyclableMemoryStream/Close.md)() | Equivalent to `Dispose` |
| override [Position](RecyclableMemoryStream/Position.md) { getset; } | Gets the current position in the stream. |
| [Advance](RecyclableMemoryStream/Advance.md)(…) | Notifies the stream that *count* bytes were written to the buffer returned by [`GetMemory`](./RecyclableMemoryStream/GetMemory.md) or [`GetSpan`](./RecyclableMemoryStream/GetSpan.md). Seeks forward by *count* bytes. |
| override [Close](RecyclableMemoryStream/Close.md)() | Equivalent to `Dispose`. |
| override [CopyToAsync](RecyclableMemoryStream/CopyToAsync.md)(…) | Asynchronously reads all the bytes from the current position in this stream and writes them to another stream. |
| override [GetBuffer](RecyclableMemoryStream/GetBuffer.md)() | Returns a single buffer containing the contents of the stream. The buffer may be longer than the stream length. |
| [GetMemory](RecyclableMemoryStream/GetMemory.md)(…) | |
| [GetReadOnlySequence](RecyclableMemoryStream/GetReadOnlySequence.md)() | Returns a sequence containing the contents of the stream. |
| [GetSpan](RecyclableMemoryStream/GetSpan.md)(…) | |
| override [Read](RecyclableMemoryStream/Read.md)(…) | Reads from the current position into the provided buffer (2 methods) |
| override [Read](RecyclableMemoryStream/Read.md)(…) | Reads from the current position into the provided buffer. (2 methods) |
| override [ReadByte](RecyclableMemoryStream/ReadByte.md)() | Reads a single byte from the current position in the stream. |
| [SafeRead](RecyclableMemoryStream/SafeRead.md)(…) | Reads from the specified position into the provided buffer (4 methods) |
| [SafeRead](RecyclableMemoryStream/SafeRead.md)(…) | Reads from the specified position into the provided buffer. (4 methods) |
| [SafeReadByte](RecyclableMemoryStream/SafeReadByte.md)(…) | Reads a single byte from the specified position in the stream. (2 methods) |
| override [Seek](RecyclableMemoryStream/Seek.md)(…) | Sets the position to the offset from the seek location |
| override [SetLength](RecyclableMemoryStream/SetLength.md)(…) | Sets the length of the stream |
| override [ToArray](RecyclableMemoryStream/ToArray.md)() | Returns a new array with a copy of the buffer's contents. You should almost certainly be using [`GetBuffer`](RecyclableMemoryStream/GetBuffer.md) combined with the [`Length`](RecyclableMemoryStream/Length.md) to access the bytes in this stream. Calling `ToArray` will destroy the benefits of pooled buffers, but it is included for the sake of completeness. |
| override [Seek](RecyclableMemoryStream/Seek.md)(…) | Sets the position to the offset from the seek location. |
| override [SetLength](RecyclableMemoryStream/SetLength.md)(…) | Sets the length of the stream. |
| override [ToArray](RecyclableMemoryStream/ToArray.md)() | Returns a new array with a copy of the buffer's contents. You should almost certainly be using [`GetBuffer`](./RecyclableMemoryStream/GetBuffer.md) combined with the [`Length`](./RecyclableMemoryStream/Length.md) to access the bytes in this stream. Calling `ToArray` will destroy the benefits of pooled buffers, but it is included for the sake of completeness. |
| override [ToString](RecyclableMemoryStream/ToString.md)() | Returns a useful string for debugging. This should not normally be called in actual production code. |
| override [TryGetBuffer](RecyclableMemoryStream/TryGetBuffer.md)(…) | Returns an `ArraySegment` that wraps a single buffer containing the contents of the stream. |
| override [Write](RecyclableMemoryStream/Write.md)(…) | Writes the buffer to the stream (2 methods) |
| override [Write](RecyclableMemoryStream/Write.md)(…) | Writes the buffer to the stream. (2 methods) |
| override [WriteByte](RecyclableMemoryStream/WriteByte.md)(…) | Writes a single byte to the current position in the stream. |
| override [WriteTo](RecyclableMemoryStream/WriteTo.md)(…) | Synchronously writes this stream's bytes to the argument stream. |
| [WriteTo](RecyclableMemoryStream/WriteTo.md)(…) | Synchronously writes this stream's bytes, starting at offset, for count bytes, to the argument stream. (5 methods) |
Expand All @@ -49,16 +49,16 @@ public sealed class RecyclableMemoryStream : MemoryStream, IBufferWriter<byte>

## Remarks

This class works in tandem with the [`RecyclableMemoryStreamManager`](RecyclableMemoryStreamManager.md) to supply `MemoryStream`-derived objects to callers, while avoiding these specific problems:
This class works in tandem with the [`RecyclableMemoryStreamManager`](./RecyclableMemoryStreamManager.md) to supply `MemoryStream`-derived objects to callers, while avoiding these specific problems:

1. **LOH allocations** – Since all large buffers are pooled, they will never incur a Gen2 GC
2. **Memory waste** – A standard memory stream doubles its size when it runs out of room. This leads to continual memory growth as each stream approaches the maximum allowed size.
3. **Memory copying** – Each time a `MemoryStream` grows, all the bytes are copied into new buffers. This implementation only copies the bytes when [`GetBuffer`](RecyclableMemoryStream/GetBuffer.md) is called.
3. **Memory copying** – Each time a `MemoryStream` grows, all the bytes are copied into new buffers. This implementation only copies the bytes when [`GetBuffer`](./RecyclableMemoryStream/GetBuffer.md) is called.
4. **Memory fragmentation** – By using homogeneous buffer sizes, it ensures that blocks of memory can be easily reused.

The stream is implemented on top of a series of uniformly-sized blocks. As the stream's length grows, additional blocks are retrieved from the memory manager. It is these blocks that are pooled, not the stream object itself.

The biggest wrinkle in this implementation is when [`GetBuffer`](RecyclableMemoryStream/GetBuffer.md) is called. This requires a single contiguous buffer. If only a single block is in use, then that block is returned. If multiple blocks are in use, we retrieve a larger buffer from the memory manager. These large buffers are also pooled, split by size--they are multiples/exponentials of a chunk size (1 MB by default).
The biggest wrinkle in this implementation is when [`GetBuffer`](./RecyclableMemoryStream/GetBuffer.md) is called. This requires a single contiguous buffer. If only a single block is in use, then that block is returned. If multiple blocks are in use, we retrieve a larger buffer from the memory manager. These large buffers are also pooled, split by size--they are multiples/exponentials of a chunk size (1 MB by default).

Once a large buffer is assigned to the stream the small blocks are NEVER again used for this stream. All operations take place on the large buffer. The large buffer can be replaced by a larger buffer from the pool as needed. All blocks and large buffers are maintained in the stream until the stream is disposed (unless AggressiveBufferReturn is enabled in the stream manager).

Expand Down
10 changes: 5 additions & 5 deletions docs/Microsoft.IO/RecyclableMemoryStream/Advance.md
@@ -1,22 +1,22 @@
# RecyclableMemoryStream.Advance method

Notifies the stream that *count* bytes were written to the buffer returned by [`GetMemory`](GetMemory.md) or [`GetSpan`](GetSpan.md). Seeks forward by *count* bytes.
Notifies the stream that *count* bytes were written to the buffer returned by [`GetMemory`](./GetMemory.md) or [`GetSpan`](./GetSpan.md). Seeks forward by *count* bytes.

```csharp
public void Advance(int count)
```

| parameter | description |
| --- | --- |
| count | How many bytes to advance |
| count | How many bytes to advance. |

## Exceptions

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| ArgumentOutOfRangeException | *count* is negative |
| InvalidOperationException | *count* is larger than the size of the previously requested buffer |
| ObjectDisposedException | Object has been disposed. |
| ArgumentOutOfRangeException | *count* is negative. |
| InvalidOperationException | *count* is larger than the size of the previously requested buffer. |

## Remarks

Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/CanRead.md
@@ -1,6 +1,6 @@
# RecyclableMemoryStream.CanRead property

Whether the stream can currently read
Whether the stream can currently read.

```csharp
public override bool CanRead { get; }
Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/CanSeek.md
@@ -1,6 +1,6 @@
# RecyclableMemoryStream.CanSeek property

Whether the stream can currently seek
Whether the stream can currently seek.

```csharp
public override bool CanSeek { get; }
Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/CanTimeout.md
@@ -1,6 +1,6 @@
# RecyclableMemoryStream.CanTimeout property

Always false
Always false.

```csharp
public override bool CanTimeout { get; }
Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/CanWrite.md
@@ -1,6 +1,6 @@
# RecyclableMemoryStream.CanWrite property

Whether the stream can currently write
Whether the stream can currently write.

```csharp
public override bool CanWrite { get; }
Expand Down
7 changes: 4 additions & 3 deletions docs/Microsoft.IO/RecyclableMemoryStream/Capacity.md
@@ -1,6 +1,6 @@
# RecyclableMemoryStream.Capacity property

Gets or sets the capacity
Gets or sets the capacity.

```csharp
public override int Capacity { get; set; }
Expand All @@ -10,15 +10,16 @@ public override int Capacity { get; set; }

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| ObjectDisposedException | Object has been disposed. |
| InvalidOperationException | Capacity is larger than int.MaxValue. |

## Remarks

Capacity is always in multiples of the memory manager's block size, unless the large buffer is in use. Capacity never decreases during a stream's lifetime. Explicitly setting the capacity to a lower value than the current value will have no effect. This is because the buffers are all pooled by chunks and there's little reason to allow stream truncation.

Writing past the current capacity will cause `Capacity` to automatically increase, until MaximumStreamCapacity is reached.

If the capacity is larger than `int.MaxValue`, then `int.MaxValue` will be returned. If you anticipate using larger streams, use the [`Capacity64`](Capacity64.md) property instead.
If the capacity is larger than `int.MaxValue`, then `InvalidOperationException` will be thrown. If you anticipate using larger streams, use the [`Capacity64`](./Capacity64.md) property instead.

## See Also

Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/Close.md
@@ -1,6 +1,6 @@
# RecyclableMemoryStream.Close method

Equivalent to `Dispose`
Equivalent to `Dispose`.

```csharp
public override void Close()
Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/Dispose.md
Expand Up @@ -8,7 +8,7 @@ protected override void Dispose(bool disposing)

| parameter | description |
| --- | --- |
| disposing | Whether we're disposing (true), or being called by the finalizer (false) |
| disposing | Whether we're disposing (true), or being called by the finalizer (false). |

## See Also

Expand Down
8 changes: 4 additions & 4 deletions docs/Microsoft.IO/RecyclableMemoryStream/GetBuffer.md
Expand Up @@ -8,18 +8,18 @@ public override byte[] GetBuffer()

## Return Value

A byte[] buffer
A byte[] buffer.

## Exceptions

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| OutOfMemoryException | stream is too large for a contiguous buffer |
| ObjectDisposedException | Object has been disposed. |
| OutOfMemoryException | stream is too large for a contiguous buffer. |

## Remarks

IMPORTANT: Doing a [`Write`](Write.md) after calling `GetBuffer` invalidates the buffer. The old buffer is held onto until [`Dispose`](Dispose.md) is called, but the next time `GetBuffer` is called, a new buffer from the pool will be required.
IMPORTANT: Doing a [`Write`](./Write.md) after calling `GetBuffer` invalidates the buffer. The old buffer is held onto until [`Dispose`](./Dispose.md) is called, but the next time `GetBuffer` is called, a new buffer from the pool will be required.

## See Also

Expand Down
Expand Up @@ -8,13 +8,13 @@ public ReadOnlySequence<byte> GetReadOnlySequence()

## Return Value

A ReadOnlySequence of bytes
A ReadOnlySequence of bytes.

## Exceptions

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| ObjectDisposedException | Object has been disposed. |

## Remarks

Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/GetSpan.md
Expand Up @@ -6,7 +6,7 @@ public Span<byte> GetSpan(int sizeHint = 0)

## Remarks

IMPORTANT: Calling Write(), GetBuffer(), TryGetBuffer(), Seek(), GetLength(), Advance(), or setting Position after calling GetMemory() invalidates the memory.
IMPORTANT: Calling Write(), GetBuffer(), TryGetBuffer(), Seek(), GetLength(), Advance(), or setting Position after calling GetSpan() invalidates the span.

## See Also

Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/Length.md
Expand Up @@ -10,7 +10,7 @@ public override long Length { get; }

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| ObjectDisposedException | Object has been disposed. |

## Remarks

Expand Down
6 changes: 3 additions & 3 deletions docs/Microsoft.IO/RecyclableMemoryStream/Position.md
@@ -1,6 +1,6 @@
# RecyclableMemoryStream.Position property

Gets the current position in the stream
Gets the current position in the stream.

```csharp
public override long Position { get; set; }
Expand All @@ -10,8 +10,8 @@ public override long Position { get; set; }

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| ArgumentOutOfRangeException | A negative value was passed |
| ObjectDisposedException | Object has been disposed. |
| ArgumentOutOfRangeException | A negative value was passed. |
| InvalidOperationException | Stream is in large-buffer mode, but an attempt was made to set the position past the maximum allowed array length. |

## Remarks
Expand Down
22 changes: 11 additions & 11 deletions docs/Microsoft.IO/RecyclableMemoryStream/Read.md
@@ -1,24 +1,24 @@
# RecyclableMemoryStream.Read method (1 of 2)

Reads from the current position into the provided buffer
Reads from the current position into the provided buffer.

```csharp
public override int Read(Span<byte> buffer)
```

| parameter | description |
| --- | --- |
| buffer | Destination buffer |
| buffer | Destination buffer. |

## Return Value

The number of bytes read
The number of bytes read.

## Exceptions

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| ObjectDisposedException | Object has been disposed. |

## See Also

Expand All @@ -29,30 +29,30 @@ The number of bytes read

# RecyclableMemoryStream.Read method (2 of 2)

Reads from the current position into the provided buffer
Reads from the current position into the provided buffer.

```csharp
public override int Read(byte[] buffer, int offset, int count)
```

| parameter | description |
| --- | --- |
| buffer | Destination buffer |
| buffer | Destination buffer. |
| offset | Offset into buffer at which to start placing the read bytes. |
| count | Number of bytes to read. |

## Return Value

The number of bytes read
The number of bytes read.

## Exceptions

| exception | condition |
| --- | --- |
| ArgumentNullException | buffer is null |
| ArgumentOutOfRangeException | offset or count is less than 0 |
| ArgumentException | offset subtracted from the buffer length is less than count |
| ObjectDisposedException | Object has been disposed |
| ArgumentNullException | buffer is null. |
| ArgumentOutOfRangeException | offset or count is less than 0. |
| ArgumentException | offset subtracted from the buffer length is less than count. |
| ObjectDisposedException | Object has been disposed. |

## See Also

Expand Down
2 changes: 1 addition & 1 deletion docs/Microsoft.IO/RecyclableMemoryStream/ReadByte.md
Expand Up @@ -14,7 +14,7 @@ The byte at the current position, or -1 if the position is at the end of the str

| exception | condition |
| --- | --- |
| ObjectDisposedException | Object has been disposed |
| ObjectDisposedException | Object has been disposed. |

## See Also

Expand Down

0 comments on commit 667bec5

Please sign in to comment.