From ab12a66c7262bb1c2b0bc572bc21398c76e07cdd Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 20 Oct 2020 07:54:20 -0700 Subject: [PATCH] Optimize FixedArray8 indexer * Use `Unsafe.Add` for direct access * Apply MethodImplOptions.AggressiveInlining * Use throw helper --- .../Immutable/FixedArray8`1.cs | 78 ++++--------------- .../ThrowHelper.cs | 17 ++++ .../TunnelVisionLabs.Collections.Trees.csproj | 1 + 3 files changed, 32 insertions(+), 64 deletions(-) create mode 100644 TunnelVisionLabs.Collections.Trees/ThrowHelper.cs diff --git a/TunnelVisionLabs.Collections.Trees/Immutable/FixedArray8`1.cs b/TunnelVisionLabs.Collections.Trees/Immutable/FixedArray8`1.cs index 4c7ccd7..ae27c96 100644 --- a/TunnelVisionLabs.Collections.Trees/Immutable/FixedArray8`1.cs +++ b/TunnelVisionLabs.Collections.Trees/Immutable/FixedArray8`1.cs @@ -7,10 +7,14 @@ namespace TunnelVisionLabs.Collections.Trees.Immutable using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + [StructLayout(LayoutKind.Sequential)] internal struct FixedArray8 { private T _item0; +#pragma warning disable IDE0044 // Add readonly modifier +#pragma warning disable CS0169 // The field 'name' is never used private T _item1; private T _item2; private T _item3; @@ -18,83 +22,29 @@ internal struct FixedArray8 private T _item5; private T _item6; private T _item7; +#pragma warning restore CS0169 // The field 'name' is never used +#pragma warning restore IDE0044 // Add readonly modifier public int Length => 8; public T this[int index] { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - switch (index) - { - case 0: - return _item0; - - case 1: - return _item1; - - case 2: - return _item2; - - case 3: - return _item3; - - case 4: - return _item4; + if ((uint)index >= 8) + ThrowHelper.ThrowIndexOutOfRangeException(); - case 5: - return _item5; - - case 6: - return _item6; - - case 7: - return _item7; - - default: - throw new IndexOutOfRangeException(); - } + return Unsafe.Add(ref _item0, index); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - switch (index) - { - case 0: - _item0 = value; - break; - - case 1: - _item1 = value; - break; - - case 2: - _item2 = value; - break; - - case 3: - _item3 = value; - break; - - case 4: - _item4 = value; - break; + if ((uint)index >= 8) + ThrowHelper.ThrowIndexOutOfRangeException(); - case 5: - _item5 = value; - break; - - case 6: - _item6 = value; - break; - - case 7: - _item7 = value; - break; - - default: - throw new IndexOutOfRangeException(); - } + Unsafe.Add(ref _item0, index) = value; } } diff --git a/TunnelVisionLabs.Collections.Trees/ThrowHelper.cs b/TunnelVisionLabs.Collections.Trees/ThrowHelper.cs new file mode 100644 index 0000000..3b85532 --- /dev/null +++ b/TunnelVisionLabs.Collections.Trees/ThrowHelper.cs @@ -0,0 +1,17 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +namespace TunnelVisionLabs.Collections.Trees +{ + using System; + using System.Diagnostics.CodeAnalysis; + + internal static class ThrowHelper + { + [DoesNotReturn] + internal static void ThrowIndexOutOfRangeException() + { + throw new IndexOutOfRangeException(); + } + } +} diff --git a/TunnelVisionLabs.Collections.Trees/TunnelVisionLabs.Collections.Trees.csproj b/TunnelVisionLabs.Collections.Trees/TunnelVisionLabs.Collections.Trees.csproj index 436aafd..5eb4bad 100644 --- a/TunnelVisionLabs.Collections.Trees/TunnelVisionLabs.Collections.Trees.csproj +++ b/TunnelVisionLabs.Collections.Trees/TunnelVisionLabs.Collections.Trees.csproj @@ -26,6 +26,7 @@ + \ No newline at end of file