diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs
index 5ad2bdebda39..0e12af30275c 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs
@@ -36,29 +36,28 @@ private FrozenHashTable(int[] hashCodes, Bucket[] buckets, ulong fastModMultipli
}
/// Initializes a frozen hash table.
- /// The set of entries to track from the hash table.
- /// A delegate that produces a hash code for a given entry.
- /// A delegate that assigns the index to a specific entry.
+ /// The number of entries to track from the hash table.
+ /// A delegate that produces a hash code for a given entry. It's passed the index of the entry and returns that entry's hash code.
+ /// A delegate that assigns the index to a specific entry. It's passed the destination and source indices.
/// true to spend additional effort tuning for subsequent read speed on the table; false to prioritize construction time.
- /// The type of elements in the hash table.
///
/// This method will iterate through the incoming entries and will invoke the hasher on each once.
/// It will then determine the optimal number of hash buckets to allocate and will populate the
- /// bucket table. In the process of doing so, it calls out to the to indicate
+ /// bucket table. In the process of doing so, it calls out to the to indicate
/// the resulting index for that entry.
/// then uses this index to reference individual entries by indexing into .
///
/// A frozen hash table.
- public static FrozenHashTable Create(T[] entries, Func hasher, Action setter, bool optimizeForReading = true)
+ public static FrozenHashTable Create(int entriesLength, Func hashAtIndex, Action storeDestIndexFromSrcIndex, bool optimizeForReading = true)
{
- Debug.Assert(entries.Length != 0);
+ Debug.Assert(entriesLength != 0);
// Calculate the hashcodes for every entry.
- int[] arrayPoolHashCodes = ArrayPool.Shared.Rent(entries.Length);
- Span hashCodes = arrayPoolHashCodes.AsSpan(0, entries.Length);
- for (int i = 0; i < entries.Length; i++)
+ int[] arrayPoolHashCodes = ArrayPool.Shared.Rent(entriesLength);
+ Span hashCodes = arrayPoolHashCodes.AsSpan(0, entriesLength);
+ for (int i = 0; i < entriesLength; i++)
{
- hashCodes[i] = hasher(entries[i]);
+ hashCodes[i] = hashAtIndex(i);
}
// Determine how many buckets to use. This might be fewer than the number of entries
@@ -113,7 +112,7 @@ public static FrozenHashTable Create(T[] entries, Func hasher, Action
while (index >= 0)
{
hashtableHashcodes[count] = hashCodes[index];
- setter(count, entries[index]);
+ storeDestIndexFromSrcIndex(count, index);
count++;
bucketCount++;
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs
index 43214afba91a..bedcbb6bd080 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs
@@ -28,9 +28,9 @@ internal Int32FrozenDictionary(Dictionary source) : base(EqualityCo
_values = new TValue[entries.Length];
_hashTable = FrozenHashTable.Create(
- entries,
- pair => pair.Key,
- (index, pair) => _values[index] = pair.Value);
+ entries.Length,
+ index => entries[index].Key,
+ (destIndex, srcIndex) => _values[destIndex] = entries[srcIndex].Value);
}
///
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs
index 7e474864d273..7f1da9dfa552 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs
@@ -1,9 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Linq;
namespace System.Collections.Frozen
{
@@ -21,10 +21,16 @@ internal Int32FrozenSet(HashSet source) : base(EqualityComparer.Defaul
Debug.Assert(source.Count != 0);
Debug.Assert(ReferenceEquals(source.Comparer, EqualityComparer.Default));
+ int count = source.Count;
+ int[] entries = ArrayPool.Shared.Rent(count);
+ source.CopyTo(entries);
+
_hashTable = FrozenHashTable.Create(
- source.ToArray(),
- item => item,
- (_, _) => { });
+ count,
+ index => entries[index],
+ delegate { });
+
+ ArrayPool.Shared.Return(entries);
}
///
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs
index 61fdf6a4ee13..abf91889fe46 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs
@@ -23,9 +23,9 @@ protected ItemsFrozenSet(HashSet source, bool optimizeForReading = true) : ba
_items = new T[entries.Length];
_hashTable = FrozenHashTable.Create(
- entries,
- o => o is null ? 0 : Comparer.GetHashCode(o),
- (index, item) => _items[index] = item,
+ entries.Length,
+ index => entries[index] is T t ? Comparer.GetHashCode(t) : 0,
+ (destIndex, srcIndex) => _items[destIndex] = entries[srcIndex],
optimizeForReading);
}
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs
index f3bd4952ce49..fb168cf1b65e 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs
@@ -25,12 +25,12 @@ protected KeysAndValuesFrozenDictionary(Dictionary source, bool op
_values = new TValue[entries.Length];
_hashTable = FrozenHashTable.Create(
- entries,
- pair => Comparer.GetHashCode(pair.Key),
- (index, pair) =>
+ entries.Length,
+ index => Comparer.GetHashCode(entries[index].Key),
+ (destIndex, srcIndex) =>
{
- _keys[index] = pair.Key;
- _values[index] = pair.Value;
+ _keys[destIndex] = entries[srcIndex].Key;
+ _values[destIndex] = entries[srcIndex].Value;
},
optimizeForReading);
}
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs
index 4ff5c907486e..b9f7dfd89cd1 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs
@@ -41,12 +41,12 @@ internal abstract class OrdinalStringFrozenDictionary : FrozenDictionary
HashCount = hashCount;
_hashTable = FrozenHashTable.Create(
- entries,
- pair => GetHashCode(pair.Key),
- (index, pair) =>
+ entries.Length,
+ index => GetHashCode(entries[index].Key),
+ (destIndex, srcIndex) =>
{
- _keys[index] = pair.Key;
- _values[index] = pair.Value;
+ _keys[destIndex] = entries[srcIndex].Key;
+ _values[destIndex] = entries[srcIndex].Value;
});
}
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs
index bd1ee3cad40a..f4c7700f0dd8 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs
@@ -31,9 +31,9 @@ internal abstract class OrdinalStringFrozenSet : FrozenSetInternalBase _items[index] = item);
+ entries.Length,
+ index => GetHashCode(entries[index]),
+ (destIndex, srcIndex) => _items[destIndex] = entries[srcIndex]);
}
private protected int HashIndex { get; }