Conversation
Utf8LogWriter previously dropped writes silently when the fixed stackalloc buffer was too small. This caused entire string parameters (e.g. long Vulkan validation messages, stack traces, serialized payloads) to vanish from log output with no indication. Now falls back to ArrayPool<byte> on overflow, with Dispose() returning the rented buffer after dispatch. The hot path (message fits in stackalloc) remains zero-allocation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Utf8LogWriterpreviously dropped writes silently when the fixed stackalloc buffer was too small. This caused entire string parameters (e.g. long Vulkan validation messages, stack traces, serialized payloads) to vanish from log output with no indication. The writer now falls back toArrayPool<byte>on overflow, withDispose()returning the rented buffer after dispatch.Reason for the change
Users reported that runtime string values containing text like
{VkBuffer 0x...}appeared to be "eaten" — when in reality the entire string parameter was being silently dropped because it exceeded the 128-byte budget allocated for string params in the stackalloc buffer. This affects any log method where the message content exceeds the estimated buffer size (clamped at 4096 bytes max), which is common for:Impacts of changes
Utf8LogWriter: All write methods (Write,WriteString,WriteFormatted) now grow viaArrayPool<byte>.Sharedwhen the stackalloc buffer is exhausted, instead of silently discarding content.Grow(): Marked[MethodImpl(MethodImplOptions.NoInlining)]to keep the hot path (no overflow) lean and inlineable.writer.Dispose()after dispatch to return any rented buffer.Migration Steps
None. This is a transparent behavioral fix. No API surface changes, no configuration required.
Performance Considerations
Dispose()is a null check on_rented.ArrayPool<byte>.Shared.Rent+ copy of existing bytes +Returnon dispose. This is the standard .NET pooling pattern and avoids GC pressure.WriteStringcomputes the exact byte count needed viaEncoding.UTF8.GetByteCount()so it grows precisely once.WriteFormattedretries in a doubling loop since the exact formatted size isn't known upfront.Security Considerations
None. No new input surfaces, no external data handling changes.
Breaking changes
Public consumer-facing changes
None.
Utf8LogWriteris aref structused internally by generated code. The public API surface is unchanged.Internal non-consumer changes
Utf8LogWriter._bufferchanged fromreadonly Span<byte>toSpan<byte>(required forGrowto reassign it).Utf8LogWritergains abyte[]? _rentedfield andDispose()method.writer.Dispose()call after dispatch.🤖 Generated with Claude Code