From 926c273b7ff93e55ba342c5e9d32fa3a184b33ec Mon Sep 17 00:00:00 2001 From: Uchuvadov Stanislav Date: Fri, 28 Nov 2025 12:32:13 +0300 Subject: [PATCH 1/3] Switch MemoryStreamDoubleDispose event level from Critical to Verbose --- README.md | 2 +- src/Events.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/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) { From 84ed227c454da476b84c3db57e909c10ec21ee94 Mon Sep 17 00:00:00 2001 From: Uchuvadov Stanislav Date: Fri, 19 Dec 2025 01:13:42 +0300 Subject: [PATCH 2/3] Avoided unnecessary stacktrace allocation on double dispose --- src/RecyclableMemoryStream.cs | 3 ++- src/RecyclableMemoryStreamManager.cs | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/RecyclableMemoryStream.cs b/src/RecyclableMemoryStream.cs index 42f16431..50333f22 100644 --- a/src/RecyclableMemoryStream.cs +++ b/src/RecyclableMemoryStream.cs @@ -26,6 +26,7 @@ namespace Microsoft.IO using System.Buffers; using System.Collections.Generic; using System.Diagnostics; + using System.Diagnostics.Tracing; using System.IO; using System.Runtime.CompilerServices; using System.Threading; @@ -280,7 +281,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 /// From aa59f47ccca6de4e93e8084437c87ae3d39241c5 Mon Sep 17 00:00:00 2001 From: Uchuvadov Stanislav Date: Fri, 19 Dec 2025 01:16:29 +0300 Subject: [PATCH 3/3] Removed unnecessary using --- src/RecyclableMemoryStream.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/RecyclableMemoryStream.cs b/src/RecyclableMemoryStream.cs index 50333f22..27a2064f 100644 --- a/src/RecyclableMemoryStream.cs +++ b/src/RecyclableMemoryStream.cs @@ -26,7 +26,6 @@ namespace Microsoft.IO using System.Buffers; using System.Collections.Generic; using System.Diagnostics; - using System.Diagnostics.Tracing; using System.IO; using System.Runtime.CompilerServices; using System.Threading;