Merge pull request #66 from mlemanczyk/codex/analyze-locking-mechanisms-in-evenperfectbitscanner
Trim PrintResult critical work further
This commit is contained in:
1 file changed
+121
-67
@@ -22,7 +22,8 @@ internal static class Program
|
|||||||
private static string ResultsFileName = "even_perfect_bit_scan_results.csv";
|
private static string ResultsFileName = "even_perfect_bit_scan_results.csv";
|
||||||
private const string PrimeFoundSuffix = " (FOUND VALID CANDIDATES)";
|
private const string PrimeFoundSuffix = " (FOUND VALID CANDIDATES)";
|
||||||
private static StringBuilder? _outputBuilder;
|
private static StringBuilder? _outputBuilder;
|
||||||
private static readonly object Sync = new();
|
private static readonly object Sync = new();
|
||||||
|
private static readonly object FileWriteSync = new();
|
||||||
private static int _consoleCounter;
|
private static int _consoleCounter;
|
||||||
private static int _writeIndex;
|
private static int _writeIndex;
|
||||||
private static int _primeCount;
|
private static int _primeCount;
|
||||||
@@ -1349,84 +1350,137 @@ internal static class Program
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void PrintResult(ulong currentP, bool searchedMersenne, bool detailedCheck, bool passedAllTests)
|
private static bool TryAcquireConsoleSlot(bool primeCandidate, out bool primeFlag)
|
||||||
{
|
{
|
||||||
if (passedAllTests)
|
int consoleInterval = PerfectNumberConstants.ConsoleInterval;
|
||||||
{
|
int counterValue = Interlocked.Increment(ref _consoleCounter);
|
||||||
int newCount = Interlocked.Increment(ref _primeCount);
|
if (counterValue >= consoleInterval)
|
||||||
if (newCount >= 2)
|
{
|
||||||
{
|
int previous = Interlocked.Exchange(ref _consoleCounter, 0);
|
||||||
Volatile.Write(ref _primeFoundAfterInit, true);
|
if (previous >= consoleInterval)
|
||||||
}
|
{
|
||||||
}
|
primeFlag = primeCandidate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool lastWasComposite = _lastCompositeP;
|
primeFlag = false;
|
||||||
bool primeFlag = false, printToConsole = false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder localBuilder = StringBuilderPool.Rent();
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
_ = localBuilder
|
private static StringBuilder? AppendToOutputBuffer(StringBuilder source)
|
||||||
.Append(currentP).Append(',')
|
{
|
||||||
.Append(searchedMersenne).Append(',')
|
StringBuilder? builderToFlush = null;
|
||||||
.Append(detailedCheck).Append(',')
|
|
||||||
.Append(passedAllTests).Append('\n');
|
|
||||||
|
|
||||||
lock (Sync)
|
lock (Sync)
|
||||||
{
|
{
|
||||||
if (_consoleCounter >= PerfectNumberConstants.ConsoleInterval)
|
StringBuilder outputBuilder = _outputBuilder!;
|
||||||
{
|
_ = outputBuilder.Append(source);
|
||||||
printToConsole = true;
|
|
||||||
primeFlag = passedAllTests && !lastWasComposite && _primeFoundAfterInit;
|
|
||||||
_consoleCounter = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_consoleCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = _outputBuilder!.Append(localBuilder);
|
int nextIndex = _writeIndex + 1;
|
||||||
|
if (nextIndex >= _writeBatchSize)
|
||||||
|
{
|
||||||
|
builderToFlush = outputBuilder;
|
||||||
|
_outputBuilder = StringBuilderPool.Rent();
|
||||||
|
_writeIndex = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_writeIndex = nextIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_writeIndex++;
|
return builderToFlush;
|
||||||
if (_writeIndex >= _writeBatchSize)
|
}
|
||||||
{
|
|
||||||
FlushBuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printToConsole)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
{
|
private static void PrintResult(ulong currentP, bool searchedMersenne, bool detailedCheck, bool passedAllTests)
|
||||||
if (primeFlag)
|
{
|
||||||
{
|
if (passedAllTests)
|
||||||
_ = localBuilder
|
{
|
||||||
.Remove(localBuilder.Length - 1, 1)
|
int newCount = Interlocked.Increment(ref _primeCount);
|
||||||
.Append(PrimeFoundSuffix)
|
if (newCount >= 2)
|
||||||
.Append('\n');
|
{
|
||||||
}
|
Volatile.Write(ref _primeFoundAfterInit, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Console.WriteLine(localBuilder.Remove(localBuilder.Length - 1, 1).ToString());
|
bool lastWasComposite = _lastCompositeP;
|
||||||
}
|
bool primeCandidate = passedAllTests && !lastWasComposite && Volatile.Read(ref _primeFoundAfterInit);
|
||||||
|
|
||||||
localBuilder.Clear();
|
StringBuilder localBuilder = StringBuilderPool.Rent();
|
||||||
StringBuilderPool.Return(localBuilder);
|
_ = localBuilder
|
||||||
}
|
.Append(currentP).Append(',')
|
||||||
|
.Append(searchedMersenne).Append(',')
|
||||||
|
.Append(detailedCheck).Append(',')
|
||||||
|
.Append(passedAllTests).Append('\n');
|
||||||
|
|
||||||
|
bool printToConsole = TryAcquireConsoleSlot(primeCandidate, out bool primeFlag);
|
||||||
|
StringBuilder? builderToFlush = AppendToOutputBuffer(localBuilder);
|
||||||
|
|
||||||
|
if (builderToFlush is not null)
|
||||||
|
{
|
||||||
|
FlushBuffer(builderToFlush);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printToConsole)
|
||||||
|
{
|
||||||
|
if (primeFlag)
|
||||||
|
{
|
||||||
|
_ = localBuilder
|
||||||
|
.Remove(localBuilder.Length - 1, 1)
|
||||||
|
.Append(PrimeFoundSuffix)
|
||||||
|
.Append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(localBuilder.Remove(localBuilder.Length - 1, 1).ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
localBuilder.Clear();
|
||||||
|
StringBuilderPool.Return(localBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void FlushBuffer()
|
private static void FlushBuffer()
|
||||||
{
|
{
|
||||||
var stream = new FileStream(ResultsFileName, FileMode.Append, FileAccess.Write, FileShare.Read);
|
StringBuilder? builderToFlush = null;
|
||||||
var writer = new StreamWriter(stream) { AutoFlush = false };
|
|
||||||
|
|
||||||
if (_writeIndex > 0)
|
lock (Sync)
|
||||||
{
|
{
|
||||||
writer.Write(_outputBuilder);
|
if (_writeIndex == 0 || _outputBuilder is null || _outputBuilder.Length == 0)
|
||||||
writer.Flush();
|
{
|
||||||
_outputBuilder!.Clear();
|
return;
|
||||||
_writeIndex = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
writer.Dispose();
|
builderToFlush = _outputBuilder;
|
||||||
stream.Dispose();
|
_outputBuilder = StringBuilderPool.Rent();
|
||||||
}
|
_writeIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlushBuffer(builderToFlush!);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void FlushBuffer(StringBuilder builderToFlush)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (FileWriteSync)
|
||||||
|
{
|
||||||
|
using FileStream stream = new(ResultsFileName, FileMode.Append, FileAccess.Write, FileShare.Read);
|
||||||
|
using StreamWriter writer = new(stream) { AutoFlush = false };
|
||||||
|
writer.Write(builderToFlush);
|
||||||
|
writer.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
builderToFlush.Clear();
|
||||||
|
StringBuilderPool.Return(builderToFlush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static ulong CountOnes(ulong value)
|
internal static ulong CountOnes(ulong value)
|
||||||
|
|||||||
Reference in new issue
Block a user