Skip to content

Commit

Permalink
Refactoring PowCachedExtension class with MethodImplAttribute hints.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheSquidCombatant committed Aug 20, 2023
1 parent e8d446a commit 3902ee2
Showing 1 changed file with 30 additions and 36 deletions.
66 changes: 30 additions & 36 deletions TheSquid.Numerics.Extensions/PowCachedExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;

namespace TheSquid.Numerics
{
Expand All @@ -16,11 +17,6 @@ public static partial class PowCachedExtension
/// </summary>
private static Dictionary<ValueTuple<BigInteger, int>, ValueTuple<BigInteger, long>> powCache;

/// <summary>
/// Cache access synchronization object.
/// </summary>
private static Object syncObject;

/// <summary>
/// Life time counter for sort items by age.
/// </summary>
Expand All @@ -37,7 +33,6 @@ public static partial class PowCachedExtension
static PowCachedExtension()
{
powCache = new Dictionary<ValueTuple<BigInteger, int>, ValueTuple<BigInteger, long>>();
syncObject = new Object();
itemsLifetime = 0;
}

Expand Down Expand Up @@ -70,28 +65,27 @@ public static BigInteger Pow(this ref BigInteger basement, int exponent)
/// <returns>
/// The result of raising basement to the exponent power.
/// </returns>
[MethodImpl(MethodImplOptions.Synchronized)]
public static BigInteger PowCached(this ref BigInteger basement, int exponent)
{
lock (syncObject)
try
{
try
{
const string negativeExponentMessage = "Negative exponent values are not supported.";
if (exponent < 0) throw new ArgumentOutOfRangeException(negativeExponentMessage);
if (itemsLifetime >= int.MaxValue) ShrinkCacheData(powCache.LongCount() / 2);
return CalculateNewValue(ref basement, exponent);
}
catch (OutOfMemoryException)
{
if (powCache.LongCount() > 0) ShrinkCacheData(0);
return CalculateNewValue(ref basement, exponent);
}
const string negativeExponentMessage = "Negative exponent values are not supported.";
if (exponent < 0) throw new ArgumentOutOfRangeException(negativeExponentMessage);
if (itemsLifetime >= int.MaxValue) ShrinkCacheData(powCache.LongCount() / 2);
return CalculateNewValue(ref basement, exponent);
}
catch (OutOfMemoryException)
{
if (powCache.LongCount() > 0) ShrinkCacheData(0);
return CalculateNewValue(ref basement, exponent);
}
}

/// <summary>
/// Get power result from cache.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryGetValue(ref BigInteger basement, int exponent, out BigInteger power)
{
var key = new ValueTuple<BigInteger, int>(basement, exponent);
Expand All @@ -104,6 +98,7 @@ private static bool TryGetValue(ref BigInteger basement, int exponent, out BigIn
/// <summary>
/// Put power result to cache.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void CacheNewValue(ref BigInteger basement, int exponent, BigInteger power)
{
var key = new ValueTuple<BigInteger, int>(basement, exponent);
Expand All @@ -114,6 +109,7 @@ private static void CacheNewValue(ref BigInteger basement, int exponent, BigInte
/// <summary>
/// Calculate new power value.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static BigInteger CalculateNewValue(ref BigInteger basement, int exponent)
{
if (exponent == 0) return 1;
Expand All @@ -138,26 +134,24 @@ private static BigInteger CalculateNewValue(ref BigInteger basement, int exponen
/// <remarks>
/// Associated items count value in the ItemsCount property.
/// </remarks>
[MethodImpl(MethodImplOptions.Synchronized)]
public static void ShrinkCacheData(long itemsInCache)
{
lock (syncObject)
if (itemsInCache == 0)
{
if (powCache.LongCount() == 0) return;
itemsLifetime = 0;
powCache.Clear();
GC.Collect();
GC.WaitForPendingFinalizers();
}
else
{
if (itemsInCache == 0)
{
if (powCache.LongCount() == 0) return;
itemsLifetime = 0;
powCache.Clear();
GC.Collect();
GC.WaitForPendingFinalizers();
}
else
{
itemsLifetime = 0;
powCache = powCache
.OrderBy(p => p.Value.Item2)
.Skip((int)Math.Min(powCache.LongCount() - itemsInCache, int.MaxValue))
.ToDictionary(p => p.Key, p => new ValueTuple<BigInteger, long>(p.Value.Item1, ++itemsLifetime));
}
itemsLifetime = 0;
powCache = powCache
.OrderBy(p => p.Value.Item2)
.Skip((int)Math.Min(powCache.LongCount() - itemsInCache, int.MaxValue))
.ToDictionary(p => p.Key, p => new ValueTuple<BigInteger, long>(p.Value.Item1, ++itemsLifetime));
}
}
}
Expand Down

0 comments on commit 3902ee2

Please sign in to comment.