From b9b3bcfe917e22e3bb441176e209802e6fe2685c Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 10 Nov 2025 20:40:11 +0000 Subject: [PATCH] Reduce allocation in TextWriter.NewLine It's reasonably common for a codebase to pick a specific newline string and set it regardless of OS, but currently that ends up allocating on every OS. Two changes: 1. When setting TextWriter.NewLine to the existing value, make it a nop to avoid unnecessarily calling ToCharArray. 2. When setting TextWriter.NewLine to "\n" on Windows or to "\r\n" on Unix, use a cached array. --- .../src/System/IO/TextWriter.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs index cc34daa1d34da0..df6e6a68aa381b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; @@ -25,6 +26,9 @@ public abstract partial class TextWriter : MarshalByRefObject, IDisposable, IAsy // We don't want to allocate on every TextWriter creation, so cache the char array. private static readonly char[] s_coreNewLine = Environment.NewLineConst.ToCharArray(); + // s_coreNewLine will be ['\r', '\n'] on Windows and ['\n'] on Unix. This is the opposite, lazily created/cached. + private static char[]? s_otherCoreNewLine; + /// /// This is the 'NewLine' property expressed as a char[]. /// It is exposed to subclasses as a protected field for read-only @@ -112,8 +116,17 @@ public virtual string NewLine { value ??= Environment.NewLineConst; - CoreNewLineStr = value; - CoreNewLine = value.ToCharArray(); + if (CoreNewLineStr != value) + { + CoreNewLineStr = value; + CoreNewLine = + value == Environment.NewLineConst ? s_coreNewLine : // current OS default + Environment.NewLineConst == "\r\n" && value == "\n" ? (s_otherCoreNewLine ??= ['\n']) : // other OS default + Environment.NewLineConst == "\n" && value == "\r\n" ? (s_otherCoreNewLine ??= ['\r', '\n']) : // other OS default + value.ToCharArray(); // unknown + } + + Debug.Assert(CoreNewLineStr == new string(CoreNewLine)); } }