Skip to content

Commit

Permalink
🧹 Engine initialization/cleanup refactoring (#1201)
Browse files Browse the repository at this point in the history
- Move static class initialization from Engine to Searcher (prep for multiple, shorter-lived engines)
- Move forced GC collection from Engine to Searcher (prep for multiple engines)
- Prepare engine to be disposed, aka allowing it to be clear its resources (prep for multiple engines, and potential engine re-allocation)
- Remove Engine `_isNewGameCommandSupported` and `_isNewGameComing`
- Dispose Engine `_searchCancellationTokenSource` and `_absoluteSearchCancellationTokenSource`
  • Loading branch information
eduherminio authored Nov 26, 2024
1 parent 741768f commit e8bdff6
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 36 deletions.
5 changes: 0 additions & 5 deletions src/Lynx/Bench.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,6 @@ public partial class Engine

_engineWriter.TryWrite($"Total time: {Utils.CalculateUCITime(totalSeconds)}");

// Cleanup game
NewGame();
_isNewGameComing = false;
_isNewGameCommandSupported = false;

return (totalNodes, Utils.CalculateNps(totalNodes, totalSeconds));
}

Expand Down
61 changes: 30 additions & 31 deletions src/Lynx/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@

namespace Lynx;

public sealed partial class Engine
public sealed partial class Engine : IDisposable
{
internal const int DefaultMaxDepth = 5;

private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly ChannelWriter<object> _engineWriter;
private readonly TranspositionTable _tt;

private bool _disposedValue;

private bool _isSearching;

/// <summary>
Expand All @@ -32,11 +34,6 @@ public sealed partial class Engine
/// </summary>
private bool _stopRequested;

#pragma warning disable IDE0052, CS0414, S4487 // Remove unread private members
private bool _isNewGameCommandSupported;
private bool _isNewGameComing;
#pragma warning restore IDE0052, CS0414 // Remove unread private members

public double AverageDepth { get; private set; }

public Game Game { get; private set; }
Expand All @@ -52,7 +49,6 @@ public Engine(ChannelWriter<object> engineWriter, TranspositionTable tt)
{
AverageDepth = 0;
Game = new Game(Constants.InitialPositionFEN);
_isNewGameComing = true;
_searchCancellationTokenSource = new();
_absoluteSearchCancellationTokenSource = new();
_engineWriter = engineWriter;
Expand All @@ -78,13 +74,8 @@ public Engine(ChannelWriter<object> engineWriter, TranspositionTable tt)

_engineWriter = engineWriter;

// No need for ResetEngine() call here, WarmupEngine -> Bench -> NewGame() calls it
NewGame();
#endif

#pragma warning disable S1215 // "GC.Collect" should not be called
GC.Collect();
GC.WaitForPendingFinalizers();
#pragma warning restore S1215 // "GC.Collect" should not be called
}

#pragma warning disable S1144 // Unused private types or members should be removed - used in Release mode
Expand All @@ -93,8 +84,6 @@ private void WarmupEngine()
_logger.Info("Warming up engine");
var sw = Stopwatch.StartNew();

InitializeStaticClasses();

const string goWarmupCommand = "go depth 10"; // ~300 ms
var command = new GoCommand(goWarmupCommand);

Expand Down Expand Up @@ -138,16 +127,9 @@ public void NewGame()
AverageDepth = 0;
Game.FreeResources();
Game = new Game(Constants.InitialPositionFEN);
_isNewGameComing = true;
_isNewGameCommandSupported = true;
_stopRequested = false;

ResetEngine();

#pragma warning disable S1215 // "GC.Collect" should not be called
GC.Collect();
GC.WaitForPendingFinalizers();
#pragma warning restore S1215 // "GC.Collect" should not be called
}

[SkipLocalsInit]
Expand All @@ -156,7 +138,6 @@ public void AdjustPosition(ReadOnlySpan<char> rawPositionCommand)
Span<Move> moves = stackalloc Move[Constants.MaxNumberOfPossibleMovesInAPosition];
Game.FreeResources();
Game = PositionCommand.ParseGame(rawPositionCommand, moves);
_isNewGameComing = false;
_stopRequested = false;
}

Expand Down Expand Up @@ -303,14 +284,32 @@ public void StopSearching()
_absoluteSearchCancellationTokenSource.Cancel();
}

private static void InitializeStaticClasses()
public void FreeResources()
{
Game.FreeResources();

_absoluteSearchCancellationTokenSource.Dispose();
_searchCancellationTokenSource.Dispose();

_disposedValue = true;
}

private void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
FreeResources();
}
_disposedValue = true;
}
}

public void Dispose()
{
_ = PVTable.Indexes[0];
_ = Attacks.KingAttacks;
_ = ZobristTable.SideHash();
_ = Masks.FileMasks;
_ = EvaluationConstants.HistoryBonus[1];
_ = MoveGenerator.Init();
_ = GoCommand.Init();
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
18 changes: 18 additions & 0 deletions src/Lynx/Searcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public Searcher(ChannelReader<string> uciReader, ChannelWriter<object> engineWri
_engine = new Engine(_engineWriter, _ttWrapper);

_logger = LogManager.GetCurrentClassLogger();

InitializeStaticClasses();
}

public async Task Run(CancellationToken cancellationToken)
Expand Down Expand Up @@ -97,6 +99,11 @@ public void NewGame()
}

_engine.NewGame();

#pragma warning disable S1215 // "GC.Collect" should not be called
GC.Collect();
GC.WaitForPendingFinalizers();
#pragma warning restore S1215 // "GC.Collect" should not be called
}

public void Quit()
Expand All @@ -113,4 +120,15 @@ public async ValueTask RunBench(int depth)
var results = _engine.Bench(depth);
await _engine.PrintBenchResults(results);
}

private static void InitializeStaticClasses()
{
_ = PVTable.Indexes[0];
_ = Attacks.KingAttacks;
_ = ZobristTable.SideHash();
_ = Masks.FileMasks;
_ = EvaluationConstants.HistoryBonus[1];
_ = MoveGenerator.Init();
_ = GoCommand.Init();
}
}

0 comments on commit e8bdff6

Please sign in to comment.