added benchmarks
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Engines;
|
||||
|
||||
namespace ParadoxSaveParser.Benchmarks;
|
||||
|
||||
/// <summary>
|
||||
/// jq runs as an external process on the JSON twin of the save.
|
||||
/// Numbers therefore include process start and reading the file from the OS page cache,
|
||||
/// which is exactly what you pay when you shell out to jq.
|
||||
/// <see cref="JqNoop" /> measures that fixed overhead so it can be subtracted.
|
||||
/// </summary>
|
||||
[SimpleJob(RunStrategy.Monitoring, launchCount: 1, warmupCount: 1, iterationCount: 5)]
|
||||
public class JqBenchmarks
|
||||
{
|
||||
public static string JqPath { get; set; } = "jq";
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup() => Run("--version", null);
|
||||
|
||||
[Benchmark(Description = "jq .countries | map_values(.technology)")]
|
||||
public int Jq() => Run("-c", BenchData.JqQuery);
|
||||
|
||||
[Benchmark(Description = "jq empty (parse only)")]
|
||||
public int JqParseOnly() => Run("-c", "empty");
|
||||
|
||||
[Benchmark(Description = "jq --stream (no DOM)")]
|
||||
public int JqStream() => Run("-c --stream", "empty");
|
||||
|
||||
[Benchmark(Description = "jq process startup only (tiny input)")]
|
||||
public int JqNoop()
|
||||
{
|
||||
var psi = new ProcessStartInfo(JqPath)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardInput = true,
|
||||
UseShellExecute = false,
|
||||
};
|
||||
psi.ArgumentList.Add("-c");
|
||||
psi.ArgumentList.Add("empty");
|
||||
using var p = Process.Start(psi)!;
|
||||
p.StandardInput.Write("{}");
|
||||
p.StandardInput.Close();
|
||||
p.StandardOutput.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
return p.ExitCode;
|
||||
}
|
||||
|
||||
private static int Run(string flags, string? program)
|
||||
{
|
||||
var psi = new ProcessStartInfo(JqPath)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
};
|
||||
foreach (var f in flags.Split(' ', StringSplitOptions.RemoveEmptyEntries))
|
||||
psi.ArgumentList.Add(f);
|
||||
if (program != null)
|
||||
{
|
||||
psi.ArgumentList.Add(program);
|
||||
psi.ArgumentList.Add(BenchData.JsonPath);
|
||||
}
|
||||
|
||||
using var p = Process.Start(psi)!;
|
||||
// output must be drained, otherwise jq blocks on a full pipe
|
||||
long bytes = 0;
|
||||
var buf = new char[1 << 16];
|
||||
int read;
|
||||
while ((read = p.StandardOutput.Read(buf, 0, buf.Length)) > 0)
|
||||
bytes += read;
|
||||
p.StandardError.ReadToEnd();
|
||||
p.WaitForExit();
|
||||
if (p.ExitCode != 0)
|
||||
throw new Exception($"jq exited with {p.ExitCode}");
|
||||
return (int)(bytes & int.MaxValue);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user