diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 749de4d3..93ddc7da 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -13,10 +13,10 @@ jobs: name: Run Benchmark.Net runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: actions/setup-dotnet@v5 with: - dotnet-version: 8.0.100 + dotnet-version: 8.0.x - name: Run benchmark run: cd BenchmarkTests && dotnet run -c Release --framework net8.0 --exporters json --filter '*' diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d8d1cf09..d7868e5c 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -8,14 +8,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 # Tooling setup - name: Install .NET SDK uses: actions/setup-dotnet@v5 with: - dotnet-version: 8.0.100 + dotnet-version: 8.0.x # Build and test validation @@ -38,7 +38,7 @@ jobs: --no-build - name: Upload test results as pipeline artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: Test results path: 'Test results/' @@ -65,7 +65,7 @@ jobs: } - name: Upload publish output as pipeline artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: Publish outputs path: 'Publish outputs/' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d47e077e..fda2b65e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -18,10 +18,10 @@ jobs: - name: Setup .NET SDK uses: actions/setup-dotnet@v5 with: - dotnet-version: 8.0.100 + dotnet-version: 8.0.x - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Initialize CodeQL uses: github/codeql-action/init@v4 diff --git a/CHANGES.md b/CHANGES.md index 8f106dc0..8178e10c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,12 @@ +# Version 4.0.0 + +**Breaking Changes** +* Dropping net6.0 will more easily support trimming [PR #409](https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream/pull/409) +* Switch `MemoryStreamDoubleDispose` event level from Critical to Verbose [PR #406](https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream/pull/406) + +**Other Changes** +* Readme: Add clarity for the large pool of buffers and the GetBuffer method pertaining to the .NET max array length [PR #370](https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream/pull/370) + # Version 3.0.1 **Bug Fix** diff --git a/README.md b/README.md index 05869143..b7a2ae36 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,7 @@ You can optionally configure the `RecyclableStreamManager.ThrowExceptionOnToArra | -----|-------|-------------| | MemoryStreamCreated | Verbose | Logged every time a stream object is allocated. Fields: `guid`, `tag`, `requestedSize`, `actualSize`. | | MemoryStreamDisposed | Verbose | Logged every time a stream object is disposed. Fields: `guid`, `tag`, `allocationStack`, `disposeStack`. | -| MemoryStreamDoubleDispose | Critical | Logged if a stream is disposed more than once. This indicates a logic error by the user of the stream. Dispose should happen exactly once per stream to avoid resource usage bugs. Fields: `guid`, `tag`, `allocationStack`, `disposeStack1`, `disposeStack2`. | +| MemoryStreamDoubleDispose | Verbose | Logged if a stream is disposed more than once. This indicates a logic error by the user of the stream. Dispose should happen exactly once per stream to avoid resource usage bugs. Fields: `guid`, `tag`, `allocationStack`, `disposeStack1`, `disposeStack2`. | | MemoryStreamFinalized | Error | Logged if a stream has gone out of scope without being disposed. This indicates a resource leak. Fields: `guid`, `tag`, `allocationStack`.| | MemoryStreamToArray | Verbose | Logged whenever `ToArray` is called. This indicates a potential problem, as calling `ToArray` goes against the concepts of good memory practice which `RecyclableMemoryStream` is trying to solve. Fields: `guid`, `tag`, `stack`, `size`.| | MemoryStreamManagerInitialized| Informational | Logged when the `RecyclableMemoryStreamManager` is initialized. Fields: `blockSize`, `largeBufferMultiple`, `maximumBufferSize`.| diff --git a/UnitTests/Tests.cs b/UnitTests/Tests.cs index 8751a515..c5380b53 100644 --- a/UnitTests/Tests.cs +++ b/UnitTests/Tests.cs @@ -4057,9 +4057,8 @@ protected override void TestDroppingLargeBuffer(long maxFreeLargeBufferSize) } } } -#pragma warning disable 618 // Timeout is obsolete because it kills the thread, which isn't allowed, but it's still handy - // for tests that are expected to run indefinitely in the failure case. - [Test, Timeout(10000)] + + [Test, MaxTime(10000)] public void TryGetBuffer_InfiniteLoop_Issue344() { // see https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream/issues/344 diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index 4c0ba6fb..5c3eaa61 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -9,10 +9,10 @@ NUnit2045 - - - - + + + + diff --git a/global.json b/global.json index ad3aafa3..d1615c2c 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.416", + "version": "8.0.422", "rollForward": "latestMinor" } } diff --git a/src/Events.cs b/src/Events.cs index 076685bf..3a4d8799 100644 --- a/src/Events.cs +++ b/src/Events.cs @@ -110,7 +110,7 @@ public void MemoryStreamDisposed(Guid guid, string? tag, long lifetimeMs, string /// Call stack of the first dispose. /// Call stack of the second dispose. /// Note: Stacks will only be populated if RecyclableMemoryStreamManager.GenerateCallStacks is true. - [Event(3, Level = EventLevel.Critical)] + [Event(3, Level = EventLevel.Verbose)] public void MemoryStreamDoubleDispose(Guid guid, string? tag, string? allocationStack, string? disposeStack1, string? disposeStack2) { diff --git a/src/Microsoft.IO.RecyclableMemoryStream.csproj b/src/Microsoft.IO.RecyclableMemoryStream.csproj index 9b7dda10..5d6a3fdf 100644 --- a/src/Microsoft.IO.RecyclableMemoryStream.csproj +++ b/src/Microsoft.IO.RecyclableMemoryStream.csproj @@ -1,13 +1,13 @@ - netstandard2.0;netstandard2.1;net6.0 + netstandard2.0;netstandard2.1;net8.0 false false Microsoft.IO bin\$(Configuration)\$(TargetFramework)\Microsoft.IO.RecyclableMemoryStream.xml Microsoft.IO.RecyclableMemoryStream - 3.0.1 + 4.0.0-alpha Microsoft.IO.RecyclableMemoryStream Microsoft A pooled MemoryStream allocator to decrease GC load and improve performance on highly scalable systems. @@ -43,7 +43,7 @@ - + diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs index dc7d6251..2d244776 100644 --- a/src/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -33,8 +33,8 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.0.1.0")] -[assembly: AssemblyFileVersion("3.0.1.0")] +[assembly: AssemblyVersion("4.0.0.0")] +[assembly: AssemblyFileVersion("4.0.0.0")] [assembly: CLSCompliant(true)] diff --git a/src/RecyclableMemoryStream.cs b/src/RecyclableMemoryStream.cs index 42f16431..27a2064f 100644 --- a/src/RecyclableMemoryStream.cs +++ b/src/RecyclableMemoryStream.cs @@ -280,7 +280,7 @@ protected override void Dispose(bool disposing) if (this.disposed) { string? doubleDisposeStack = null; - if (this.memoryManager.options.GenerateCallStacks) + if (this.memoryManager.GenerateDoubleDisposedStackTrace) { doubleDisposeStack = Environment.StackTrace; } diff --git a/src/RecyclableMemoryStreamManager.cs b/src/RecyclableMemoryStreamManager.cs index 985309b7..5f8f85f9 100644 --- a/src/RecyclableMemoryStreamManager.cs +++ b/src/RecyclableMemoryStreamManager.cs @@ -25,6 +25,7 @@ namespace Microsoft.IO using System; using System.Collections.Concurrent; using System.Collections.Generic; + using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; using System.Threading; @@ -82,6 +83,13 @@ public partial class RecyclableMemoryStreamManager internal readonly Options options; + internal bool GenerateDoubleDisposedStackTrace => + this.options.GenerateCallStacks && + ( + this.StreamDoubleDisposed != null || + Events.Writer.IsEnabled(EventLevel.Verbose, EventKeywords.None) + ); + /// /// Settings for controlling the behavior of RecyclableMemoryStream ///