Skip to content

Commit

Permalink
Use BitOperations.RoundUpToPowerOf2 in more places (dotnet#101405)
Browse files Browse the repository at this point in the history
* Use BitOperations.RoundUpToPowerOf2 in ThreadLocal

* Use BitOperations.RoundUpToPowerOf2 in CacheDict
  • Loading branch information
PaulusParssinen authored and matouskozak committed Apr 30, 2024
1 parent 5a3df85 commit fef7ba0
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Threading;

namespace System.Dynamic.Utils
Expand Down Expand Up @@ -40,27 +41,11 @@ internal Entry(int hash, TKey key, TValue value)
/// <param name="size">The maximum number of elements to store will be this number aligned to next ^2.</param>
internal CacheDict(int size)
{
int alignedSize = AlignSize(size);
int alignedSize = (int)BitOperations.RoundUpToPowerOf2((uint)size);
_mask = alignedSize - 1;
_entries = new Entry[alignedSize];
}

private static int AlignSize(int size)
{
Debug.Assert(size > 0);

size--;
size |= size >> 1;
size |= size >> 2;
size |= size >> 4;
size |= size >> 8;
size |= size >> 16;
size++;

Debug.Assert((size & (~size + 1)) == size, "aligned size should be a power of 2");
return size;
}

/// <summary>
/// Tries to get the value associated with 'key', returning true if it's found and
/// false if it's not present.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;

// A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing
// thread; this provides an alternative to using a ThreadStatic static variable and having
Expand Down Expand Up @@ -552,40 +553,15 @@ private static int GetNewTableSize(int minSize)
}
Debug.Assert(minSize > 0);

//
// Round up the size to the next power of 2
//
// The algorithm takes three steps:
// input -> subtract one -> propagate 1-bits to the right -> add one
//
// Let's take a look at the 3 steps in both interesting cases: where the input
// is (Example 1) and isn't (Example 2) a power of 2.
//
// Example 1: 100000 -> 011111 -> 011111 -> 100000
// Example 2: 011010 -> 011001 -> 011111 -> 100000
//
int newSize = minSize;

// Step 1: Decrement
newSize--;

// Step 2: Propagate 1-bits to the right.
newSize |= newSize >> 1;
newSize |= newSize >> 2;
newSize |= newSize >> 4;
newSize |= newSize >> 8;
newSize |= newSize >> 16;

// Step 3: Increment
newSize++;
uint newSize = BitOperations.RoundUpToPowerOf2((uint)minSize);

// Don't set newSize to more than Array.MaxArrayLength
if ((uint)newSize > Array.MaxLength)
if (newSize > Array.MaxLength)
{
newSize = Array.MaxLength;
newSize = (uint)Array.MaxLength;
}

return newSize;
return (int)newSize;
}

/// <summary>
Expand Down

0 comments on commit fef7ba0

Please sign in to comment.