Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 3 additions & 31 deletions src/System.Collections/src/System/Collections/Generic/HashSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1148,15 +1148,15 @@ private void IncreaseCapacity()
}

// Able to increase capacity; copy elements to larger array and rehash
SetCapacity(newSize, false);
SetCapacity(newSize);
}

/// <summary>
/// Set the underlying buckets array to size newSize and rehash. Note that newSize
/// *must* be a prime. It is very likely that you want to call IncreaseCapacity()
/// instead of this method.
/// </summary>
private void SetCapacity(int newSize, bool forceNewHashCodes)
private void SetCapacity(int newSize)
{
Debug.Assert(_buckets != null, "SetCapacity called on a set with no elements");

Expand All @@ -1166,21 +1166,6 @@ private void SetCapacity(int newSize, bool forceNewHashCodes)
Array.Copy(_slots, 0, newSlots, 0, _lastIndex);
}

#if FEATURE_RANDOMIZED_STRING_HASHING
if (forceNewHashCodes)
{
for (int i = 0; i < _lastIndex; i++)
{
if (newSlots[i].hashCode != -1)
{
newSlots[i].hashCode = InternalGetHashCode(newSlots[i].value);
}
}
}
#else
Debug.Assert(!forceNewHashCodes);
#endif

int[] newBuckets = new int[newSize];
for (int i = 0; i < _lastIndex; i++)
{
Expand All @@ -1207,18 +1192,13 @@ private bool AddIfNotPresent(T value)

int hashCode = InternalGetHashCode(value);
int bucket = hashCode % _buckets.Length;
#if FEATURE_RANDOMIZED_STRING_HASHING
int collisionCount = 0;
#endif

for (int i = _buckets[bucket] - 1; i >= 0; i = _slots[i].next)
{
if (_slots[i].hashCode == hashCode && _comparer.Equals(_slots[i].value, value))
{
return false;
}
#if FEATURE_RANDOMIZED_STRING_HASHING
collisionCount++;
#endif
}

int index;
Expand All @@ -1245,14 +1225,6 @@ private bool AddIfNotPresent(T value)
_count++;
_version++;

#if FEATURE_RANDOMIZED_STRING_HASHING
if (collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_comparer))
{
_comparer = (IEqualityComparer<T>)HashHelpers.GetRandomizedEqualityComparer(_comparer);
SetCapacity(_buckets.Length, true);
}
#endif // FEATURE_RANDOMIZED_STRING_HASHING

return true;
}

Expand Down
132 changes: 5 additions & 127 deletions src/System.Runtime.Extensions/src/System/Collections/Hashtable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -732,13 +732,13 @@ public virtual Object this[Object key]
private void expand()
{
int rawsize = HashHelpers.ExpandPrime(_buckets.Length);
rehash(rawsize, false);
rehash(rawsize);
}

// We occasionally need to rehash the table to clean up the collision bits.
private void rehash()
{
rehash(_buckets.Length, false);
rehash(_buckets.Length);
}

private void UpdateVersion()
Expand All @@ -748,7 +748,7 @@ private void UpdateVersion()
_version++;
}

private void rehash(int newsize, bool forceNewHashCode)
private void rehash(int newsize)
{
// reset occupancy
_occupancy = 0;
Expand All @@ -768,7 +768,7 @@ private void rehash(int newsize, bool forceNewHashCode)
bucket oldb = _buckets[nb];
if ((oldb.key != null) && (oldb.key != _buckets))
{
int hashcode = ((forceNewHashCode ? GetHash(oldb.key) : oldb.hash_coll) & 0x7FFFFFFF);
int hashcode = oldb.hash_coll & 0x7FFFFFFF;
putEntry(newBuckets, oldb.key, oldb.val, hashcode);
}
}
Expand All @@ -781,7 +781,6 @@ private void rehash(int newsize, bool forceNewHashCode)
_isWriterInProgress = false;
// minimum size of hashtable is 3 now and maximum loadFactor is 0.72 now.
Debug.Assert(_loadsize < newsize, "Our current implementation means this is not possible.");
return;
}

// Returns an enumerator for this hashtable.
Expand Down Expand Up @@ -945,18 +944,7 @@ private void Insert(Object key, Object nvalue, bool add)
_count++;
UpdateVersion();
_isWriterInProgress = false;
#if FEATURE_RANDOMIZED_STRING_HASHING
if (ntry > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer))
{
// PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some
// cases there may not be any strings in the hashtable and we wouldn't get any mixing.
if (_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer))
{
_keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
rehash(buckets.Length, true);
}
}
#endif

return;
}

Expand All @@ -975,18 +963,6 @@ private void Insert(Object key, Object nvalue, bool add)
UpdateVersion();
_isWriterInProgress = false;

#if FEATURE_RANDOMIZED_STRING_HASHING
if (ntry > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer))
{
// PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some
// cases there may not be any strings in the hashtable and we wouldn't get any mixing.
if (_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer))
{
_keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
rehash(buckets.Length, true);
}
}
#endif
return;
}

Expand Down Expand Up @@ -1017,18 +993,6 @@ private void Insert(Object key, Object nvalue, bool add)
UpdateVersion();
_isWriterInProgress = false;

#if FEATURE_RANDOMIZED_STRING_HASHING
if (buckets.Length > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer))
{
// PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some
// cases there may not be any strings in the hashtable and we wouldn't get any mixing.
if (_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer))
{
_keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
rehash(buckets.Length, true);
}
}
#endif
return;
}

Expand Down Expand Up @@ -1690,10 +1654,6 @@ public KeyValuePairs[] Items

internal static class HashHelpers
{
#if FEATURE_RANDOMIZED_STRING_HASHING
public const int HashCollisionThreshold = 100;
public static bool s_UseRandomizedStringHashing = String.UseRandomizedHashing();
#endif
// Table of prime numbers to use as hash table sizes.
// A typical resize algorithm would pick the smallest prime number in this array
// that is larger than twice the previous capacity.
Expand Down Expand Up @@ -1771,87 +1731,5 @@ public static int ExpandPrime(int oldSize)

private static ConditionalWeakTable<object, SerializationInfo> s_serializationInfoTable;
public static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable => LazyInitializer.EnsureInitialized(ref s_serializationInfoTable);

#if FEATURE_RANDOMIZED_STRING_HASHING
public static bool IsWellKnownEqualityComparer(object comparer)
{
return (comparer == null || comparer == System.Collections.Generic.EqualityComparer<string>.Default || comparer is IWellKnownStringEqualityComparer);
}

public static IEqualityComparer GetRandomizedEqualityComparer(object comparer)
{
Debug.Assert(comparer == null || comparer == System.Collections.Generic.EqualityComparer<string>.Default || comparer is IWellKnownStringEqualityComparer);

if (comparer == null)
{
return new System.Collections.Generic.RandomizedObjectEqualityComparer();
}

if (comparer == System.Collections.Generic.EqualityComparer<string>.Default)
{
return new System.Collections.Generic.RandomizedStringEqualityComparer();
}

IWellKnownStringEqualityComparer cmp = comparer as IWellKnownStringEqualityComparer;

if (cmp != null)
{
return cmp.GetRandomizedEqualityComparer();
}

Debug.Fail("Missing case in GetRandomizedEqualityComparer!");

return null;
}

public static object GetEqualityComparerForSerialization(object comparer)
{
if (comparer == null)
{
return null;
}

IWellKnownStringEqualityComparer cmp = comparer as IWellKnownStringEqualityComparer;

if (cmp != null)
{
return cmp.GetEqualityComparerForSerialization();
}

return comparer;
}

private const int bufferSize = 1024;
private static RandomNumberGenerator rng;
private static byte[] data;
private static int currentIndex = bufferSize;
private static readonly object lockObj = new Object();

internal static long GetEntropy()
{
lock (lockObj)
{
long ret;

if (currentIndex == bufferSize)
{
if (null == rng)
{
rng = RandomNumberGenerator.Create();
data = new byte[bufferSize];
Debug.Assert(bufferSize % 8 == 0, "We increment our current index by 8, so our buffer size must be a multiple of 8");
}

rng.GetBytes(data);
currentIndex = 0;
}

ret = BitConverter.ToInt64(data, currentIndex);
currentIndex += 8;

return ret;
}
}
#endif // FEATURE_RANDOMIZED_STRING_HASHING
}
}