summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Kuhne <jeremy.kuhne@microsoft.com>2018-08-05 23:22:57 -0700
committerGitHub <noreply@github.com>2018-08-05 23:22:57 -0700
commitac8f8e52c49b0ffa712d68730a41883d281bea01 (patch)
tree1a44dbcc7bf1b93e710a544a4e720681e2387dbc
parent29b59d54f3816886742cb9aaff6b96ee0625264c (diff)
downloadcoreclr-ac8f8e52c49b0ffa712d68730a41883d281bea01.tar.gz
coreclr-ac8f8e52c49b0ffa712d68730a41883d281bea01.tar.bz2
coreclr-ac8f8e52c49b0ffa712d68730a41883d281bea01.zip
Improve StreamWriter format perf (#19235)
* Improve StreamWriter format perf Override the format overloads for TextWriter and skip the extra string allocation for the formatted string by using StringBuilder directly, copying straight to the output buffer. Improves performance roughtly 10% and cuts allocations by 10x and up (formatting a string into a string goes to *zero* allocations). * Fix copy/paste slipup- test added to CoreFX PR
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
index b510b6b287..8d94ac60b9 100644
--- a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
@@ -476,6 +476,123 @@ namespace System.IO
}
}
+ private void WriteFormatHelper(string format, ParamsArray args, bool appendNewLine)
+ {
+ StringBuilder sb =
+ StringBuilderCache.Acquire(format.Length + args.Length * 8)
+ .AppendFormatHelper(null, format, args);
+
+ StringBuilder.ChunkEnumerator chunks = sb.GetChunks();
+
+ bool more = chunks.MoveNext();
+ while (more)
+ {
+ ReadOnlySpan<char> current = chunks.Current.Span;
+ more = chunks.MoveNext();
+
+ // If final chunk, include the newline if needed
+ WriteSpan(current, appendNewLine: more ? false : appendNewLine);
+ }
+
+ StringBuilderCache.Release(sb);
+ }
+
+ public override void Write(string format, object arg0)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0);
+ }
+ }
+
+ public override void Write(string format, object arg0, object arg1)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0, arg1);
+ }
+ }
+
+ public override void Write(string format, object arg0, object arg1, object arg2)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1, arg2), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0, arg1, arg2);
+ }
+ }
+
+ public override void Write(string format, params object[] arg)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0, object arg1)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0, arg1);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0, object arg1, object arg2)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1, arg2), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0, arg1, arg2);
+ }
+ }
+
+ public override void WriteLine(string format, params object[] arg)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg);
+ }
+ }
+
#region Task based Async APIs
public override Task WriteAsync(char value)
{