From ccc9e231ced3f7ff2e89f2035f5666352f5d3363 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 6 Jul 2024 00:07:16 -0700 Subject: [PATCH] Avoid boxing in System.ObjectModel.KeydCollection during startup ArgumentNullException.ThrowIfNull can incur boxing when applied to argument of generic type. Tier-1 JIT optimizations are able to optimize this boxing in steady state, but Tier-0 JIT optimization are not. It can result into excessive allocations during startup. Switch KeyedCollection to use ThrowHelper that is pattern used by number of other collections. --- .../src/System.ObjectModel.csproj | 1 + .../Collections/ObjectModel/KeyedCollection.cs | 15 ++++++++++++--- .../System.ObjectModel/src/System/ThrowHelper.cs | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 src/libraries/System.ObjectModel/src/System/ThrowHelper.cs diff --git a/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj b/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj index 0ef93fda9ecd4b..3d787f35f0bbcf 100644 --- a/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj +++ b/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj @@ -8,6 +8,7 @@ + diff --git a/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs b/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs index d4fef7be1cb83f..f8e47d71e5e20a 100644 --- a/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs +++ b/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs @@ -71,7 +71,10 @@ public TItem this[TKey key] public bool Contains(TKey key) { - ArgumentNullException.ThrowIfNull(key); + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(nameof(key)); + } if (dict != null) { @@ -91,7 +94,10 @@ public bool Contains(TKey key) public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TItem item) { - ArgumentNullException.ThrowIfNull(key); + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(nameof(key)); + } if (dict != null) { @@ -131,7 +137,10 @@ private bool ContainsItem(TItem item) public bool Remove(TKey key) { - ArgumentNullException.ThrowIfNull(key); + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(nameof(key)); + } if (dict != null) { diff --git a/src/libraries/System.ObjectModel/src/System/ThrowHelper.cs b/src/libraries/System.ObjectModel/src/System/ThrowHelper.cs new file mode 100644 index 00000000000000..fe453d70771d34 --- /dev/null +++ b/src/libraries/System.ObjectModel/src/System/ThrowHelper.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; + +namespace System +{ + internal static class ThrowHelper + { + [DoesNotReturn] + public static void ThrowArgumentNullException(string? paramName) => + throw new ArgumentNullException(paramName); + } +}