private static async Task <CompetitionResult> runCompetition(DirectoryInfo rootDirectory, Gene gene, int port, string mapPath, CompetetionMode competetionMode, CancellationToken cancellationToken = default) { var tryCount = 1; while (tryCount <= _maximumTryCount) { bool result; switch (competetionMode) { case CompetetionMode.NoContainer: result = await runCompetitionInsideHost(gene, port, mapPath, rootDirectory, cancellationToken); break; case CompetetionMode.ContainerPerCompetetion: result = await runCompetitionInsideContainer(gene, mapPath, rootDirectory, cancellationToken); if (!result) { backupAttempt(rootDirectory, tryCount); } break; case CompetetionMode.ReusableContainer: result = await runCompetetionInsideReusableContainer(gene, mapPath, rootDirectory, cancellationToken); break; default: throw new ArgumentOutOfRangeException(nameof(competetionMode), competetionMode, null); } if (result) { return(new CompetitionResult { Status = CompetitionResultStatus.Successful, TryCount = tryCount, }); } tryCount++; } return(new CompetitionResult { Status = CompetitionResultStatus.Failed, TryCount = tryCount - 1, }); }
public static async Task RunCompetitions(string mapPath, CompetetionMode competetionMode, CancellationToken cancellationToken = default) { switch (competetionMode) { case CompetetionMode.NoContainer: break; case CompetetionMode.ContainerPerCompetetion: await DockerService.BuildImageAsync(Directory.GetCurrentDirectory(), Program.DockerImageName, cancellationToken); await DockerService.StopAndRemoveAllContainersAsync(cancellationToken); break; case CompetetionMode.ReusableContainer: await DockerService.BuildImageAsync(Directory.GetCurrentDirectory(), Program.DockerImageName, cancellationToken); await DockerService.StopAndRemoveAllContainersAsync(cancellationToken); await ContainerRepository.InitalizeContainers(_geneProcessLimit, Program.DockerImageName, cancellationToken); break; } _arenaStartTime = DateTime.Now; Console.WriteLine("welcome to Colosseum. enjoy the show :)"); List <Gene> lastGeneration = null; var lastGenerationFile = new FileInfo("generationInfo.json"); if (lastGenerationFile.Exists) { Console.WriteLine($"loading last generation from {lastGenerationFile.FullName}"); try { var content = await File.ReadAllTextAsync(lastGenerationFile.FullName, cancellationToken); lastGeneration = JsonConvert.DeserializeObject <List <Gene> >(content); } catch (Exception ex) { Console.WriteLine($"loading last generation failed. error:{Environment.NewLine}{ex}"); } } var generationNumber = 1; var arenaDir = new DirectoryInfo("arena"); arenaDir.Create(); var currentRunDir = arenaDir.CreateSubdirectory(DateTime.Now.ToString("s").Replace(" ", "-").ToValidFileName()); currentRunDir.Create(); var port = _startPort; var cts = new CancellationTokenSource(); cancellationToken.Register(() => cts.Cancel()); while (true) { var generationProcessStartTime = DateTime.Now; var generationDir = currentRunDir.CreateSubdirectory(generationNumber.ToString()); generationDir.Create(); var newGeneration = _generationGenerator.Genetic(lastGeneration); lastGeneration = new List <Gene>(); var competitionTasks = new List <Task>(); switch (competetionMode) { case CompetetionMode.NoContainer: await cleanSystem(cancellationToken); break; case CompetetionMode.ContainerPerCompetetion: await DockerService.StopAndRemoveAllContainersAsync(cancellationToken); break; case CompetetionMode.ReusableContainer: break; } Console.WriteLine($"running generation #{generationNumber}"); Console.WriteLine($"this generation will have {newGeneration.Count} genes and we'll process up to {_geneProcessLimit} genes simultaneously"); Console.WriteLine("-----------"); Console.WriteLine("no.\tsuccess\tscore\t\tid\t\telapsed\t\tsystem elapsed\t\tPPM\t\tcurrent time"); foreach (var gene in newGeneration) { competitionTasks.AddThreadSafe(processGene(gene, mapPath, lastGeneration, port, generationDir, competetionMode, cancellationToken)); port++; } await Task.WhenAll(competitionTasks).CancelOnFaulted(cts); var generationInfoFilePath = Path.Combine(generationDir.FullName, "generationInfo.json"); await File.WriteAllTextAsync(generationInfoFilePath, JsonConvert.SerializeObject(newGeneration, Formatting.Indented), cancellationToken); var generationScoreAverage = newGeneration.Average(x => x.Score); Console.WriteLine($"generation score average: {generationScoreAverage}, generation elapsed time: {DateTime.Now - generationProcessStartTime}"); generationNumber++; } }
private static async Task processGene(Gene gene, string mapPath, List <Gene> lastGeneration, int port, DirectoryInfo generationDir, CompetetionMode competetionMode, CancellationToken cancellationToken) { await _geneProcessSemaphoreSlim.WaitAsync(cancellationToken); try { var processStopwatch = new Stopwatch(); processStopwatch.Start(); var geneDir = generationDir.CreateSubdirectory(gene.Id.ToString()); geneDir.Create(); var competitionResult = await runCompetition(geneDir, gene, port, mapPath, competetionMode, cancellationToken); if (competitionResult.Status == CompetitionResultStatus.Successful) { var defenseOutputPath = ClientManager.GetClientOutputPath(geneDir, ClientMode.defend); var scoreString = (await File.ReadAllLinesAsync(defenseOutputPath, cancellationToken)).First(); if (double.TryParse(scoreString, out var score)) { gene.Score = score; } else { gene.Score = null; } } else { gene.Score = null; } lastGeneration.AddThreadSafe(gene); processStopwatch.Stop(); await _geneProcessLogSemaphoreSlim.WaitAsync(cancellationToken); try { _geneProcessTimes.AddThreadSafe(processStopwatch.Elapsed); var processCount = _geneProcessTimes.Count; Console.Write($"{processCount.ToString().PadRight(8)}"); var successState = ""; if (competitionResult.Status == CompetitionResultStatus.Successful) { successState = "x" + (competitionResult.TryCount == 1 ? "" : competitionResult.TryCount.ToString()); } Console.Write($"{successState.PadRight(8)}"); var score = gene.Score.HasValue ? gene.Score?.ToString("F2") : "null"; Console.Write($"{score.PadRight(16)}"); Console.Write($"{gene.Id.ToString().PadRight(16)}"); var processElapsed = processStopwatch.Elapsed; Console.Write($"{processElapsed.ToString(@"mm\:ss\.fff").PadRight(16)}"); var arenaElapse = DateTime.Now - _arenaStartTime; Console.Write($"{arenaElapse.ToString(@"hh\:mm\:ss\.fff").PadRight(24)}"); var allProcessAverage = arenaElapse / processCount; var taskPerMinute = TimeSpan.FromSeconds(60) / allProcessAverage; Console.Write($"{taskPerMinute.ToString("F2").PadRight(12)}"); Console.Write(DateTime.Now.ToString("s")); } finally { _geneProcessLogSemaphoreSlim.Release(); Console.WriteLine(); } } catch (Exception ex) { Console.WriteLine($"an error occurred while running task for gene hash {gene.Id}{Environment.NewLine}{ex}"); } finally { _geneProcessSemaphoreSlim.Release(); } }