added benchmarks
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using ParadoxSaveParser.Lib;
|
||||
|
||||
namespace ParadoxSaveParser.Benchmarks;
|
||||
|
||||
/// <summary>
|
||||
/// Locates and lazily loads the benchmark corpus:
|
||||
/// a real EU4 <c>gamestate</c> file and its compact JSON twin (for jq).
|
||||
/// Override the directory with the PSP_BENCH_DATA environment variable.
|
||||
/// </summary>
|
||||
public static class BenchData
|
||||
{
|
||||
public const string PdxQuery = "countries.*.technology";
|
||||
|
||||
/// <summary>jq program extracting the same data as <see cref="PdxQuery" />.</summary>
|
||||
public const string JqQuery = ".countries | map_values(.technology)";
|
||||
|
||||
public static string Dir { get; } =
|
||||
Environment.GetEnvironmentVariable("PSP_BENCH_DATA")
|
||||
?? Path.Combine(FindRepoRoot(), "ParadoxSaveParser.CLI", "bin", "Debug", "net10.0");
|
||||
|
||||
public static string PdxPath => Path.Combine(Dir, "gamestate");
|
||||
public static string JsonPath => Path.Combine(Dir, "gamestate.min.json");
|
||||
|
||||
private static byte[]? _pdxBytes;
|
||||
private static string? _pdxText;
|
||||
|
||||
/// <summary>Raw bytes of the save, kept in memory so benchmarks don't measure disk I/O.</summary>
|
||||
public static byte[] PdxBytes => _pdxBytes ??= File.ReadAllBytes(PdxPath);
|
||||
|
||||
/// <summary>
|
||||
/// The save decoded as text for the regex engines.
|
||||
/// Latin1 is used because EU4 saves contain non-UTF8 bytes inside dynasty names,
|
||||
/// and it maps every byte to exactly one char.
|
||||
/// </summary>
|
||||
public static string PdxText => _pdxText ??= Encoding.Latin1.GetString(PdxBytes);
|
||||
|
||||
private static string FindRepoRoot()
|
||||
{
|
||||
var dir = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (dir != null && !File.Exists(Path.Combine(dir.FullName, "ParadoxSaveParser.sln")))
|
||||
dir = dir.Parent;
|
||||
return dir?.FullName ?? Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Produces the compact JSON twin of the save file, which is what jq is given.
|
||||
/// Compact (not indented) so jq isn't penalized by parsing whitespace.
|
||||
/// </summary>
|
||||
public static void PrepareJson()
|
||||
{
|
||||
if (File.Exists(JsonPath))
|
||||
{
|
||||
Console.WriteLine($"{JsonPath} already exists, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"parsing {PdxPath} ...");
|
||||
using var input = File.OpenRead(PdxPath);
|
||||
var root = new SaveParserEU4(input, null).Parse();
|
||||
Console.WriteLine($"serializing to {JsonPath} ...");
|
||||
using var output = File.Create(JsonPath);
|
||||
JsonSerializer.Serialize(output, root, new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = false,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
MaxDepth = 1024,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
});
|
||||
Console.WriteLine($"done: {new FileInfo(JsonPath).Length / 1024 / 1024} MB");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user