Remove some allocation at "hello world" startup (#44469)
authorStephen Toub <stoub@microsoft.com>
Wed, 11 Nov 2020 14:15:06 +0000 (09:15 -0500)
committerGitHub <noreply@github.com>
Wed, 11 Nov 2020 14:15:06 +0000 (09:15 -0500)
commitaa04371cabe4c82a39d993582cf7e14a07d1f1ab
tree860ac9f2d1ba5df21c0b17be652ee878aec06730
parente8bba0bcf8a4732f83d5c4b6b98bf9dd932311b9
Remove some allocation at "hello world" startup (#44469)

* Specialize `EqualityComparer<string>.Default`

Removes ~80 allocations at startup.

* Avoid loading Encoding.Unicode just for CodePage

* Use fixed instead of GCHandle.Alloc in EventSource.Initialize

* Remove lock / lock object from EncodingProvider.AddProvider

* Remove lock object from AppDomain.cs

* Lazily allocate EventSource's m_createEventLock

It's only used on an error path.  We don't need to allocate it for each EventSource that's created.

* Avoid unnecessary CultureInfo access in derived TextWriters

SyncTextWriter already overrides FormatProvider, in which case the t.FormatProvider passed to the base will never be used, so this call is incurring a virtual dispatch for no benefit.  And NullTextWriter needn't access InvariantCulture and force it into existence if it isn't yet, as the formatting should never actually be used, and if it is, its FormatProvider override can supply the culture.

* Avoid allocating AssemblyLoadContext's dictionary if no direct interaction with ALC

AssemblyLoadContext.OnProcessExit gets called by EventSource, which in turn forces s_allContexts into existence in order to lock on it in order to enumerate all active contexts, and if there's been no interaction with AssemblyLoadContext, there won't be any to enumerate.  So delay allocate the object.

* Address PR feedback

* Call EventListener.DisposeOnShutdown from AppContext.OnProcessExit

Avoids the need to register with AppContext.ProcessExit, avoiding an EventHandler allocation, and avoids the need in the common case to fire AppContext.ProcessExit, which in turn avoids allocating an AppDomain and EventArgs if they weren't otherwise created, plus it avoids the delegate invocation.

* Update src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs
src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs
src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventSetInformation.cs
src/libraries/Common/src/System/Text/EncodingHelper.Windows.cs
src/libraries/System.Console/src/System/ConsolePal.Windows.cs
src/libraries/System.Private.CoreLib/src/System/AppContext.cs
src/libraries/System.Private.CoreLib/src/System/AppDomain.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs
src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
src/libraries/System.Private.CoreLib/src/System/Text/EncodingProvider.cs