From 60b21b0b1da717bc54207d79201f6aba4d0c8e3a Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 27 Oct 2022 09:01:34 -0400 Subject: [PATCH 1/2] Don't store references in Consumer. Don't box nullable value types. --- src/BenchmarkDotNet/Engines/Consumer.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/BenchmarkDotNet/Engines/Consumer.cs b/src/BenchmarkDotNet/Engines/Consumer.cs index 015b3a952d..fc973064b9 100644 --- a/src/BenchmarkDotNet/Engines/Consumer.cs +++ b/src/BenchmarkDotNet/Engines/Consumer.cs @@ -30,8 +30,6 @@ private static readonly HashSet SupportedTypes private double doubleHolder; private long longHolder; private ulong ulongHolder; - private string stringHolder; - private object objectHolder; private IntPtr ptrHolder; private UIntPtr uptrHolder; @@ -97,16 +95,16 @@ private static readonly HashSet SupportedTypes [MethodImpl(MethodImplOptions.AggressiveInlining)] [PublicAPI] - public void Consume(string stringValue) => Volatile.Write(ref stringHolder, stringValue); + public void Consume(string stringValue) => DeadCodeEliminationHelper.KeepAliveWithoutBoxing(stringValue); [MethodImpl(MethodImplOptions.AggressiveInlining)] [PublicAPI] - public void Consume(object objectValue) => Volatile.Write(ref objectHolder, objectValue); + public void Consume(object objectValue) => DeadCodeEliminationHelper.KeepAliveWithoutBoxing(objectValue); [MethodImpl(MethodImplOptions.AggressiveInlining)] [PublicAPI] public void Consume(T objectValue) where T : class // class constraint prevents from boxing structs - => Volatile.Write(ref objectHolder, objectValue); + => DeadCodeEliminationHelper.KeepAliveWithoutBoxing(objectValue); [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Consume(T* ptrValue) where T: unmanaged => Volatile.Write(ref ptrHolder, (IntPtr)ptrValue); @@ -141,15 +139,12 @@ public void Consume(in T value) Volatile.Write(ref longHolder, (long)(object)value); else if (typeof(T) == typeof(ulong)) Volatile.Write(ref ulongHolder, (ulong)(object)value); - else if (default(T) == null) - objectHolder = (object) value; + else if (default(T) == null && !typeof(T).IsValueType) + DeadCodeEliminationHelper.KeepAliveWithoutBoxing(value); else - ValueTypesConsumer(value); // non-primitive value types + DeadCodeEliminationHelper.KeepAliveWithoutBoxingReadonly(value); // non-primitive value types } - [MethodImpl(MethodImplOptions.NoInlining)] - private void ValueTypesConsumer(in T _) { } - internal static bool IsConsumable(Type type) => SupportedTypes.Contains(type) || type.GetTypeInfo().IsClass || type.GetTypeInfo().IsInterface; From df1029476b30f225ef3a0c56b2d242d9a770e29e Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 27 Oct 2022 09:08:13 -0400 Subject: [PATCH 2/2] Removed reference check as it's no longer necessary. --- src/BenchmarkDotNet/Engines/Consumer.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/BenchmarkDotNet/Engines/Consumer.cs b/src/BenchmarkDotNet/Engines/Consumer.cs index fc973064b9..f35c466c63 100644 --- a/src/BenchmarkDotNet/Engines/Consumer.cs +++ b/src/BenchmarkDotNet/Engines/Consumer.cs @@ -139,10 +139,8 @@ public void Consume(in T value) Volatile.Write(ref longHolder, (long)(object)value); else if (typeof(T) == typeof(ulong)) Volatile.Write(ref ulongHolder, (ulong)(object)value); - else if (default(T) == null && !typeof(T).IsValueType) - DeadCodeEliminationHelper.KeepAliveWithoutBoxing(value); else - DeadCodeEliminationHelper.KeepAliveWithoutBoxingReadonly(value); // non-primitive value types + DeadCodeEliminationHelper.KeepAliveWithoutBoxingReadonly(value); // non-primitive and nullable value types } internal static bool IsConsumable(Type type)