Refine partial factor primality caching

This commit is contained in:
Marek Lemańczyk committed 2025-10-19 23:48:07 +02:00
1 parent 0fbd635828
commit 43e2894661
2 files changed
+35 -16

No files matched your search

@@ -730,7 +730,8 @@ internal static partial class PrimeOrderCalculator
} }
ulong globalCacheLimit = (ulong)PerfectNumberConstants.MaxQForDivisorCycles; ulong globalCacheLimit = (ulong)PerfectNumberConstants.MaxQForDivisorCycles;
if (candidate > globalCacheLimit) bool bypassesGlobalCache = candidate > globalCacheLimit;
if (bypassesGlobalCache)
{ {
Dictionary<ulong, bool>? cache = localCache; Dictionary<ulong, bool>? cache = localCache;
if (cache is not null && cache.TryGetValue(candidate, out bool cachedValue)) if (cache is not null && cache.TryGetValue(candidate, out bool cachedValue))
@@ -742,12 +743,13 @@ internal static partial class PrimeOrderCalculator
bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(candidate); bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(candidate);
CachePrimalityResult(candidate, isPrime); CachePrimalityResult(candidate, isPrime);
if (candidate > globalCacheLimit) if (bypassesGlobalCache)
{ {
Dictionary<ulong, bool>? cache = localCache; Dictionary<ulong, bool>? cache = localCache;
if (cache is null) if (cache is null)
{ {
cache = ThreadStaticPools.RentUlongBoolDictionary(4); cache = ThreadStaticPools.RentUlongBoolDictionary(4);
cache.Clear();
localCache = cache; localCache = cache;
} }
+31 -14
View File
@@ -279,22 +279,39 @@ namespace PerfectNumbers.Core
} }
[ThreadStatic] [ThreadStatic]
private static List<Dictionary<ulong, bool>>? _ulongBoolDictionaryPool; private static Stack<Dictionary<ulong, bool>>? _ulongBoolDictionaryPool;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Dictionary<ulong, bool> RentUlongBoolDictionary(int capacityHint) public static Dictionary<ulong, bool> RentUlongBoolDictionary(int capacityHint)
{ {
List<Dictionary<ulong, bool>>? pool = _ulongBoolDictionaryPool; Stack<Dictionary<ulong, bool>>? pool = _ulongBoolDictionaryPool;
if (pool is not null && pool.Count > 0) if (pool is null)
{ {
int lastIndex = pool.Count - 1; pool = new Stack<Dictionary<ulong, bool>>(4);
Dictionary<ulong, bool> dictionary = pool[lastIndex]; _ulongBoolDictionaryPool = pool;
pool.RemoveAt(lastIndex); }
if (dictionary.Count > 0)
{
dictionary.Clear();
}
// Keep the previous null-check implementation here for reference.
// Do not uncomment this branch; the pool is always initialized above.
// if (pool is not null && pool.Count > 0)
// {
// Dictionary<ulong, bool> dictionary = pool.Pop();
// if (dictionary.Count < capacityHint)
// {
// dictionary.EnsureCapacity(capacityHint);
// }
//
// return dictionary;
// }
if (pool.Count > 0)
{
Dictionary<ulong, bool> dictionary = pool.Pop();
// Callers clear dictionaries after renting to avoid duplicate work.
// if (dictionary.Count > 0)
// {
// dictionary.Clear();
// }
if (dictionary.Count < capacityHint) if (dictionary.Count < capacityHint)
{ {
dictionary.EnsureCapacity(capacityHint); dictionary.EnsureCapacity(capacityHint);
@@ -309,15 +326,15 @@ namespace PerfectNumbers.Core
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ReturnUlongBoolDictionary(Dictionary<ulong, bool> dictionary) public static void ReturnUlongBoolDictionary(Dictionary<ulong, bool> dictionary)
{ {
List<Dictionary<ulong, bool>>? pool = _ulongBoolDictionaryPool; Stack<Dictionary<ulong, bool>>? pool = _ulongBoolDictionaryPool;
if (pool is null) if (pool is null)
{ {
pool = new List<Dictionary<ulong, bool>>(4); pool = new Stack<Dictionary<ulong, bool>>(4);
_ulongBoolDictionaryPool = pool; _ulongBoolDictionaryPool = pool;
} }
dictionary.Clear(); // Do not clear pooled dictionaries here; callers must clear on rent.
pool.Add(dictionary); pool.Push(dictionary);
} }
[ThreadStatic] [ThreadStatic]