From b0fb3fa764cd644594d452565f6e0f994e731b30 Mon Sep 17 00:00:00 2001 From: Justin Van Patten Date: Mon, 11 May 2015 00:03:34 -0700 Subject: [PATCH] Avoid unnecessary delegate allocations There are 9 up-front delegate allocations (2 for TextReader and 7 for TextWriter) that are unnecessary in most cases as most TextReader/TextWriter subclasses override the base async methods where such delegates are used. Instead, let the compiler allocate and cache such delegates lazily, only in the rare cases when the delegates are actually used. --- src/mscorlib/src/System/IO/TextReader.cs | 25 ++++---- src/mscorlib/src/System/IO/TextWriter.cs | 105 ++++++++++++++----------------- 2 files changed, 59 insertions(+), 71 deletions(-) diff --git a/src/mscorlib/src/System/IO/TextReader.cs b/src/mscorlib/src/System/IO/TextReader.cs index 98a6c8a..448bcbc 100644 --- a/src/mscorlib/src/System/IO/TextReader.cs +++ b/src/mscorlib/src/System/IO/TextReader.cs @@ -40,16 +40,6 @@ namespace System.IO { public abstract class TextReader : IDisposable { #endif // FEATURE_REMOTING - [NonSerialized] - private static Func _ReadLineDelegate = state => ((TextReader)state).ReadLine(); - - [NonSerialized] - private static Func _ReadDelegate = state => - { - Tuple tuple = (Tuple)state; - return tuple.Item1.Read(tuple.Item2, tuple.Item3, tuple.Item4); - }; - public static readonly TextReader Null = new NullTextReader(); protected TextReader() {} @@ -189,7 +179,11 @@ namespace System.IO { [ComVisible(false)] public virtual Task ReadLineAsync() { - return Task.Factory.StartNew(_ReadLineDelegate, this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + return Task.Factory.StartNew(state => + { + return ((TextReader)state).ReadLine(); + }, + this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading=true)] @@ -228,8 +222,13 @@ namespace System.IO { Contract.Requires(count >= 0); Contract.Requires(buffer.Length - index >= count); - Tuple tuple = new Tuple(this, buffer, index, count); - return Task.Factory.StartNew(_ReadDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + var tuple = new Tuple(this, buffer, index, count); + return Task.Factory.StartNew(state => + { + var t = (Tuple)state; + return t.Item1.Read(t.Item2, t.Item3, t.Item4); + }, + tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading=true)] diff --git a/src/mscorlib/src/System/IO/TextWriter.cs b/src/mscorlib/src/System/IO/TextWriter.cs index 4203fa9..71d39a2 100644 --- a/src/mscorlib/src/System/IO/TextWriter.cs +++ b/src/mscorlib/src/System/IO/TextWriter.cs @@ -41,51 +41,6 @@ namespace System.IO { #endif // FEATURE_REMOTING public static readonly TextWriter Null = new NullTextWriter(); - [NonSerialized] - private static Action _WriteCharDelegate = state => - { - Tuple tuple = (Tuple)state; - tuple.Item1.Write(tuple.Item2); - }; - - [NonSerialized] - private static Action _WriteStringDelegate = state => - { - Tuple tuple = (Tuple)state; - tuple.Item1.Write(tuple.Item2); - }; - - [NonSerialized] - private static Action _WriteCharArrayRangeDelegate = state => - { - Tuple tuple = (Tuple)state; - tuple.Item1.Write(tuple.Item2, tuple.Item3, tuple.Item4); - }; - - [NonSerialized] - private static Action _WriteLineCharDelegate = state => - { - Tuple tuple = (Tuple)state; - tuple.Item1.WriteLine(tuple.Item2); - }; - - [NonSerialized] - private static Action _WriteLineStringDelegate = state => - { - Tuple tuple = (Tuple)state; - tuple.Item1.WriteLine(tuple.Item2); - }; - - [NonSerialized] - private static Action _WriteLineCharArrayRangeDelegate = state => - { - Tuple tuple = (Tuple)state; - tuple.Item1.WriteLine(tuple.Item2, tuple.Item3, tuple.Item4); - }; - - [NonSerialized] - private static Action _FlushDelegate = state => ((TextWriter)state).Flush(); - // This should be initialized to Environment.NewLine, but // to avoid loading Environment unnecessarily so I've duplicated // the value here. @@ -538,16 +493,26 @@ namespace System.IO { [ComVisible(false)] public virtual Task WriteAsync(char value) { - Tuple tuple = new Tuple(this, value); - return Task.Factory.StartNew(_WriteCharDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + var tuple = new Tuple(this, value); + return Task.Factory.StartNew(state => + { + var t = (Tuple)state; + t.Item1.Write(t.Item2); + }, + tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteAsync(String value) { - Tuple tuple = new Tuple(this, value); - return Task.Factory.StartNew(_WriteStringDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + var tuple = new Tuple(this, value); + return Task.Factory.StartNew(state => + { + var t = (Tuple)state; + t.Item1.Write(t.Item2); + }, + tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading = true)] @@ -562,24 +527,39 @@ namespace System.IO { [ComVisible(false)] public virtual Task WriteAsync(char[] buffer, int index, int count) { - Tuple tuple = new Tuple(this, buffer, index, count); - return Task.Factory.StartNew(_WriteCharArrayRangeDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + var tuple = new Tuple(this, buffer, index, count); + return Task.Factory.StartNew(state => + { + var t = (Tuple)state; + t.Item1.Write(t.Item2, t.Item3, t.Item4); + }, + tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteLineAsync(char value) { - Tuple tuple = new Tuple(this, value); - return Task.Factory.StartNew(_WriteLineCharDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + var tuple = new Tuple(this, value); + return Task.Factory.StartNew(state => + { + var t = (Tuple)state; + t.Item1.WriteLine(t.Item2); + }, + tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteLineAsync(String value) { - Tuple tuple = new Tuple(this, value); - return Task.Factory.StartNew(_WriteLineStringDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + var tuple = new Tuple(this, value); + return Task.Factory.StartNew(state => + { + var t = (Tuple)state; + t.Item1.WriteLine(t.Item2); + }, + tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading = true)] @@ -594,8 +574,13 @@ namespace System.IO { [ComVisible(false)] public virtual Task WriteLineAsync(char[] buffer, int index, int count) { - Tuple tuple = new Tuple(this, buffer, index, count); - return Task.Factory.StartNew(_WriteLineCharArrayRangeDelegate, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + var tuple = new Tuple(this, buffer, index, count); + return Task.Factory.StartNew(state => + { + var t = (Tuple)state; + t.Item1.WriteLine(t.Item2, t.Item3, t.Item4); + }, + tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } [HostProtection(ExternalThreading = true)] @@ -609,7 +594,11 @@ namespace System.IO { [ComVisible(false)] public virtual Task FlushAsync() { - return Task.Factory.StartNew(_FlushDelegate, this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + return Task.Factory.StartNew(state => + { + ((TextWriter)state).Flush(); + }, + this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } #endregion -- 2.7.4