Merge pull request #173 from mlemanczyk/codex/analyze-and-reduce-gc-cost-in-primeordercalculator
Reduce Pollard Rho stopwatch allocations to lower GC pressure
This commit is contained in:
2 files changed
+80
-47
No files matched your search
@@ -603,12 +603,12 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
if (config.PollardRhoMilliseconds > 0 && pending.Count > 0)
|
if (config.PollardRhoMilliseconds > 0 && pending.Count > 0)
|
||||||
{
|
{
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
long deadlineTimestamp = CreateDeadlineTimestamp(config.PollardRhoMilliseconds);
|
||||||
long budgetTicks = TimeSpan.FromMilliseconds(config.PollardRhoMilliseconds).Ticks;
|
|
||||||
Stack<UInt128> stack = new();
|
Stack<UInt128> stack = new();
|
||||||
stack.Push(remaining);
|
stack.Push(remaining);
|
||||||
pending.Clear();
|
pending.Clear();
|
||||||
|
|
||||||
|
long timestamp = 0L; // reused for deadline checks.
|
||||||
while (stack.Count > 0)
|
while (stack.Count > 0)
|
||||||
{
|
{
|
||||||
UInt128 composite = stack.Pop();
|
UInt128 composite = stack.Pop();
|
||||||
@@ -623,13 +623,14 @@ internal static partial class PrimeOrderCalculator
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stopwatch.ElapsedTicks > budgetTicks)
|
timestamp = Stopwatch.GetTimestamp();
|
||||||
|
if (timestamp > deadlineTimestamp)
|
||||||
{
|
{
|
||||||
pending.Add(composite);
|
pending.Add(composite);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryPollardRhoWide(composite, stopwatch, budgetTicks, out UInt128 factor))
|
if (!TryPollardRhoWide(composite, deadlineTimestamp, out UInt128 factor))
|
||||||
{
|
{
|
||||||
pending.Add(composite);
|
pending.Add(composite);
|
||||||
continue;
|
continue;
|
||||||
@@ -728,7 +729,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
return remaining;
|
return remaining;
|
||||||
}
|
}
|
||||||
private static bool TryPollardRhoWide(in UInt128 n, Stopwatch stopwatch, long budgetTicks, out UInt128 factor)
|
private static bool TryPollardRhoWide(in UInt128 n, long deadlineTimestamp, out UInt128 factor)
|
||||||
{
|
{
|
||||||
factor = UInt128.Zero;
|
factor = UInt128.Zero;
|
||||||
if ((n & UInt128.One) == UInt128.Zero)
|
if ((n & UInt128.One) == UInt128.Zero)
|
||||||
@@ -740,10 +741,12 @@ internal static partial class PrimeOrderCalculator
|
|||||||
UInt128 c = UInt128.One;
|
UInt128 c = UInt128.One;
|
||||||
UInt128 x = (UInt128)2UL;
|
UInt128 x = (UInt128)2UL;
|
||||||
UInt128 y = x;
|
UInt128 y = x;
|
||||||
|
long timestamp = 0L; // reused for deadline checks.
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (stopwatch.ElapsedTicks > budgetTicks)
|
timestamp = Stopwatch.GetTimestamp();
|
||||||
|
if (timestamp > deadlineTimestamp)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -873,12 +873,12 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
if (config.PollardRhoMilliseconds > 0 && pending.Count > 0)
|
if (config.PollardRhoMilliseconds > 0 && pending.Count > 0)
|
||||||
{
|
{
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
long deadlineTimestamp = CreateDeadlineTimestamp(config.PollardRhoMilliseconds);
|
||||||
long budgetTicks = TimeSpan.FromMilliseconds(config.PollardRhoMilliseconds).Ticks;
|
|
||||||
compositeStack = AcquireCompositeStack(Math.Max(pending.Count * 2, 4));
|
compositeStack = AcquireCompositeStack(Math.Max(pending.Count * 2, 4));
|
||||||
compositeStack.Push(remaining);
|
compositeStack.Push(remaining);
|
||||||
pending.Clear();
|
pending.Clear();
|
||||||
|
|
||||||
|
long timestamp = 0L; // reused for deadline checks.
|
||||||
while (compositeStack.Count > 0)
|
while (compositeStack.Count > 0)
|
||||||
{
|
{
|
||||||
ulong composite = compositeStack.Pop();
|
ulong composite = compositeStack.Pop();
|
||||||
@@ -894,13 +894,14 @@ internal static partial class PrimeOrderCalculator
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stopwatch.ElapsedTicks > budgetTicks)
|
timestamp = Stopwatch.GetTimestamp();
|
||||||
|
if (timestamp > deadlineTimestamp)
|
||||||
{
|
{
|
||||||
pending.Add(composite);
|
pending.Add(composite);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryPollardRho(composite, stopwatch, budgetTicks, out ulong factor))
|
if (!TryPollardRho(composite, deadlineTimestamp, out ulong factor))
|
||||||
{
|
{
|
||||||
pending.Add(composite);
|
pending.Add(composite);
|
||||||
continue;
|
continue;
|
||||||
@@ -1143,48 +1144,77 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private static bool TryPollardRho(ulong n, Stopwatch stopwatch, long budgetTicks, out ulong factor)
|
private static long CreateDeadlineTimestamp(int milliseconds)
|
||||||
{
|
{
|
||||||
factor = 0UL;
|
if (milliseconds <= 0)
|
||||||
if ((n & 1UL) == 0UL)
|
{
|
||||||
{
|
return long.MaxValue;
|
||||||
factor = 2UL;
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
long stopwatchTicks = ConvertMillisecondsToStopwatchTicks(milliseconds);
|
||||||
{
|
long startTimestamp = Stopwatch.GetTimestamp();
|
||||||
if (stopwatch.ElapsedTicks > budgetTicks)
|
long deadline = startTimestamp + stopwatchTicks;
|
||||||
{
|
if (deadline < startTimestamp)
|
||||||
return false;
|
{
|
||||||
}
|
return long.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
ulong c = (DeterministicRandom.NextUInt64() % (n - 1UL)) + 1UL;
|
return deadline;
|
||||||
ulong x = (DeterministicRandom.NextUInt64() % (n - 2UL)) + 2UL;
|
}
|
||||||
ulong y = x;
|
|
||||||
ulong d = 1UL;
|
|
||||||
|
|
||||||
while (d == 1UL)
|
private static long ConvertMillisecondsToStopwatchTicks(int milliseconds)
|
||||||
{
|
{
|
||||||
if (stopwatch.ElapsedTicks > budgetTicks)
|
long frequency = Stopwatch.Frequency;
|
||||||
{
|
long baseTicks = (frequency / 1000L) * milliseconds;
|
||||||
return false;
|
long remainder = (frequency % 1000L) * milliseconds;
|
||||||
}
|
return baseTicks + (remainder / 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
x = AdvancePolynomial(x, c, n);
|
private static bool TryPollardRho(ulong n, long deadlineTimestamp, out ulong factor)
|
||||||
y = AdvancePolynomial(y, c, n);
|
{
|
||||||
y = AdvancePolynomial(y, c, n);
|
factor = 0UL;
|
||||||
ulong diff = x > y ? x - y : y - x;
|
if ((n & 1UL) == 0UL)
|
||||||
d = BinaryGcd(diff, n);
|
{
|
||||||
}
|
factor = 2UL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (d != n)
|
long timestamp = 0L; // reused for deadline checks.
|
||||||
{
|
while (true)
|
||||||
factor = d;
|
{
|
||||||
return true;
|
timestamp = Stopwatch.GetTimestamp();
|
||||||
}
|
if (timestamp > deadlineTimestamp)
|
||||||
}
|
{
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong c = (DeterministicRandom.NextUInt64() % (n - 1UL)) + 1UL;
|
||||||
|
ulong x = (DeterministicRandom.NextUInt64() % (n - 2UL)) + 2UL;
|
||||||
|
ulong y = x;
|
||||||
|
ulong d = 1UL;
|
||||||
|
|
||||||
|
while (d == 1UL)
|
||||||
|
{
|
||||||
|
timestamp = Stopwatch.GetTimestamp();
|
||||||
|
if (timestamp > deadlineTimestamp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = AdvancePolynomial(x, c, n);
|
||||||
|
y = AdvancePolynomial(y, c, n);
|
||||||
|
y = AdvancePolynomial(y, c, n);
|
||||||
|
ulong diff = x > y ? x - y : y - x;
|
||||||
|
d = BinaryGcd(diff, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d != n)
|
||||||
|
{
|
||||||
|
factor = d;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ulong AdvancePolynomial(ulong x, ulong c, ulong modulus)
|
private static ulong AdvancePolynomial(ulong x, ulong c, ulong modulus)
|
||||||
|
|||||||
Reference in new issue
Block a user