Bug Fix
- Fix infinite loop bug when calling (Try)GetBuffer on a stream longer than 1 GB when using the
UseExponentialLargeBufferoption. (Issue #344)
Breaking Changes
- Removed
int-based constructor andGetStreamoverloads wherelong-based methods exist. - Removed all methods marked with
[Obsolete]:StreamDisposedEventArgs.ctor(Guid, string, string, string)RecyclableMemoryStreamManager.GetStream(Guid, string, Memory<byte>)RecyclableMemoryStreamManager.GetStream(Memory<byte>)RecyclableMemoryStreamManager.GetStream(string, Memory<byte>)
- Enable nullable annotations and warnings. i.e., added
<Nullable>enabled</Nullable>to the project file. - All overloads of
RecyclableMemoryStreamManager.GetStreamnow return typeRecyclableMemoryStreaminstead ofMemoryStream. - Removed explicit targets for net462, netcoreapp2.1, and net5.0. Supported targets are netstandard2.0, netstandard2.1, and net6.0 (there are a few net6.0-specific optimizations).
- Moved all the configuration settings for
RecyclableMemoryStreamManagerto the newRecyclableMemoryStreamManager.Optionsclass. Removed many of the constructors as a result. This class will facilitate easier dependency injection through use of the Options pattern, for those who need it. - Renamed some settings' names to be more consistent (e.g.,
MaximumLargePoolFreeBytes)
New Feature
- Added a new option for
RecyclableMemoryStreamManager:ZeroOutBuffer, which will cause all buffers to be cleared on allocation and when returning to the pool. Off by default.
Other Changes
- Upgrade NUnit test library to version 4.
- Fix some spelling issues in comments and variable names.
- Update code to the latest recommended C# syntax.
Optimizations
- Calculating blocks and offsets was made more efficient by using
Math.DivRem. - Reading and writing to the stream was made more efficient with fewer array accesses.
CopyTowas overridden to avoid using the slower default implementation.
New Feature
- Stream lifetime (creation through dispose) is now tracked and reported through the
MemoryStreamDisposeEventSourceevent, as well as through theStreamDisposed.NET event.
Changes
- The pool statistics used to be reported only when blocks/buffers were returned to the pool. This could lead to lopsided reporting patterns in some cases. Now, pool statistics are reported on stream creation and disposal.
- Added pool stats information to the
MemoryStreamDiscardBufferevent. - Changed events relating to buffer creation to be at the warning level instead of verbose. These are signals that the pool might not be large enough to handle the load.
Bug Fixes
- Fixed allocation/finalization bug that could cause a
NullReferenceExceptionin some low-memory scenarios.
Internal
- .NET 7 SDK used to build
- Changed coding style to match some newer patterns (and added .editorconfig file to enforce in the future)
- Fixed punctuation and spelling in API documentation.
API change
- There are now overloads that take a type
longparameter for requestedSize.
Bug Fix
ToStringwill no longer throw an exception if the stream is disposed.
API changes
- Add an override for
GetStreamthat takes aReadOnlySpan<byte>. This supersedes the versions ofGetStreamthat takeMemory<byte>, which were marked as[Obsolete].
Bug Fixes
- Fixed:
GetReadOnlySequence()throwsArgumentOutOfRangeException
Performance Improvements
- Removed enumerator allocation when returning blocks to the pool.
- Changed default size of stream's block list to 0 because
EnsureCapacitywill always run, potentially resizing the list anyway. - Removed unneeded closure allocation when copying buffers.
- Use
GC.AllocateUninitializedArrayin an additional spot, for better performance in .NET 5+.
Documentation
- Improved documentation, standardized punctuation, fixed code formatting.
** Bug Fixes**
- Fixed another integer overflow error when returning buffers to the pool.
Bug Fixes
- Added
[SecurityRules(SecurityRuyleSet.Level1)]to assembly to allow more relaxed inheritance security rules. - Fixed an integer overflow when calculating large buffer sizes.
- Added
RecyclableMemoryStreamManagerconstructor overloads that take parameters for specifying the maximum free pool sizes. Updated IntelliSense documentation to make clear that these values need to be explicitly set to avoid unbounded pool growth. - Buffers are now allocated using
GC.AllocateUninitializedArrayin .NET 5. - net462 and netstandard2.0 targets can now support the
Span-related APIs via a dependency on System.Memory. - Updated documentation to fix typos and clarify language in some parts.
- Support for Source Link
Breaking Changes
- Removed 2 GB stream limit. Extremely large streams can be created by chaining together blocks. Attempts to convert a stream into a contiguous buffer longer than the runtime's limits will result in an exception.
- Removed build targets for net40, net45, net46, and netstandard1.4. Added net462.
- Changed some ETW events to provide more information.
- Refactored .NET events to match the information payloads of the ETW events.
GetBuffernow throwsOutOfMemoryExceptioninstead ofInvalidOperationExceptionif the needed size is too large for a contiguous array.
Other Changes
- Removed use of
Interlockedmethods when checking whether the stream is disposed. This should improve performance. (Concurrent use of streams has never been supported.) RecyclableMemoryStreamnow implementsIBufferWriter<byte>- New method overloads of
WriteTothat allow you write the contents of the stream directly to anotherbyte[]buffer. - Reformatted all code documentation to be more readable.
Development-only Changes
- Significantly improved unit test speed
- Added netstandard2.0 target. There was an issue calling
GetBufferfrom a netstandard2.0 project, which would resolve to the netstandard1.4 target of RMS. netstandard1.4 doesn't support overridingGetBuffer, so you could hitUnauthorizedAccessException. - A bug fix for
CopyToAsync. It was copying the entire stream, but the expected behavior based onSystem.IO.MemoryStreamis to copy from the current position. - Some performance improvements to
CopyToAsync.
Minor updates
- Override
CopyToAsyncto save some allocations. - Apply
AllowPartiallyTrustedCallersattribute to assembly
Performance Improvements
WriteBytehas been significantly optimized to be faster.CheckDisposed, which is called in many code paths, has similarly been optimized.
New API
void WriteTo(Stream stream, int offset, int count)-- Allows you to write a portion of the current stream to a destination stream without first having to callGetBuffer.
Functionality
- Added
RecyclableMemoryStreamManager.ThrowExceptionOnToArray. Causes aNotSupportedExceptionto be thrown ifRecyclableMemoryStream.ToArrayis called. Default isfalse. - Added overloads of
RecyclableMemoryStreamManager.GetStreamthat acceptMemory<byte>arguments.
Meta
- Added changes.md to solution
- Regenerated API documentation for new XML comments and new APIs.
Bug Fixes
- Removed a buggy and unnecessary boundary check in Write methods.
Performance
- Removed LINQ iteration in some properties.
- Overloads of
Read,SafeRead, andWritethat acceptSpanarguments (.NET Core and .NET Standard targets only)
Functionality
- New buffer allocation strategy: exponential. Instead of linearly increasing large buffer sizes by a fixed multiple (say, 1MB), you can choose to have it increase exponentially in size, starting with smaller large buffers. This will allow you more efficient use of space, especially in smaller heap scenarios where you don't have gobs of memory to keep in a pool. We use this in Bing in some data centers that are more resource constrained than others.
- New targets for .NET Framework 4.6, .NET Standard 2.1
- Overload for
TryGetBuffer, introduced in .NET Framework 4.6. - Allow the Stream's GUID to be set explicitly
Meta
- Removed CBT build support files. Using dotnet.exe to build now.
- Added public key for delayed signing during build
- Consolidate and updated all NuGet package settings in the .csproj file.
- Added setting for generating a NuGet package for symbols (.snupkg)
- Bugs fixed when allocating very large streams.
- Concurrent methods for reading from a single stream added.
- Support for .NET 4.0 (without ETW instrumentation).
- It is now safe to call Dispose from multiple threads on the same object.
- Binaries on nuget.org are now signed through Microsoft.
- Some documentation enhancements and typo-cleanup.
- Some minor performance improvements.
- Fix behavior of
Dispose()to be safe on double-dispose.
- Initial release.