using System; using System.IO; using System.Linq; using System.Text.RegularExpressions; using BenchmarkDotNet.Running; using PCRE; using ParadoxSaveParser.Lib; namespace ParadoxSaveParser.Benchmarks; public static class Program { public static void Main(string[] args) { switch (args.FirstOrDefault()) { case "prepare": BenchData.PrepareJson(); return; case "verify": Verify(); return; default: BenchmarkSwitcher.FromTypes([typeof(ExtractionBenchmarks), typeof(JqBenchmarks), typeof(ParserInputBenchmarks)]) .Run(args); return; } } /// /// Runs every extractor once and prints its checksum and wall time, /// so that differences in what each engine actually finds are visible before benchmarking. /// private static void Verify() { Console.WriteLine($"save: {BenchData.PdxPath} {new FileInfo(BenchData.PdxPath).Length / 1024 / 1024} MB"); Console.WriteLine($"json: {BenchData.JsonPath} {new FileInfo(BenchData.JsonPath).Length / 1024 / 1024} MB"); var pdx = BenchData.PdxBytes; var text = BenchData.PdxText; var json = File.ReadAllBytes(BenchData.JsonPath); var query = SearchExpressionCompiler.Compile(BenchData.PdxQuery); Time("SearchExpression", () => Extractors.SearchExpression(pdx, query)); Time("FullParse", () => Extractors.FullParseThenSelect(pdx)); Time("Regex path aware compiled", () => Extractors.RegexScan(new Regex(Extractors.PathAwarePattern, RegexOptions.Compiled), text)); Time("Regex path aware nonbacktracking", () => Extractors.RegexScan(new Regex(Extractors.PathAwarePattern, RegexOptions.NonBacktracking), text)); Time("Regex balanced two stage", () => Extractors.RegexTwoStage(new Regex(Extractors.CountriesBlockPattern, RegexOptions.Compiled), new Regex(Extractors.TechnologyBlockPattern, RegexOptions.Compiled), text)); Time("PCRE path aware", () => Extractors.PcreScan(new PcreRegex(Extractors.PathAwarePattern, PcreOptions.Compiled), text)); Time("Utf8JsonReader", () => Extractors.Utf8JsonReaderScan(json)); Mispairing.Report(pdx, text); Time("JsonDocument", () => Extractors.JsonDocumentScan(json)); } private static void Time(string name, Func f) { var sw = System.Diagnostics.Stopwatch.StartNew(); long checksum; try { checksum = f(); } catch (Exception ex) { Console.WriteLine($"{name,-34} FAILED: {ex.Message}"); return; } sw.Stop(); Console.WriteLine($"{name,-34} countries={checksum / 1_000_000,5} techSum={checksum % 1_000_000,7} {sw.ElapsedMilliseconds,7} ms"); } }