Add SHA-256 benchmark with the option to display cycles per byte

This commit is contained in:
Alex Barney 2019-11-25 14:21:09 -06:00
parent 1aa5c9438e
commit 1efcf3327c
3 changed files with 63 additions and 2 deletions

View file

@ -60,6 +60,7 @@ namespace hactoolnet
new CliOption("hashedfs", 0, (o, a) => o.BuildHfs = true),
new CliOption("title", 1, (o, a) => o.TitleId = ParseTitleId(a[0])),
new CliOption("bench", 1, (o, a) => o.BenchType = a[0]),
new CliOption("cpufreq", 1, (o, a) => o.CpuFrequencyGhz = ParseDouble(a[0])),
new CliOption("replacefile", 2, (o, a) =>
{
@ -172,6 +173,16 @@ namespace hactoolnet
return id;
}
private static double ParseDouble(string input)
{
if (!double.TryParse(input, out double value))
{
PrintWithUsage($"Could not parse value \"{input}\"");
}
return value;
}
private static void PrintWithUsage(string toPrint)
{
Console.WriteLine(toPrint);

View file

@ -53,6 +53,7 @@ namespace hactoolnet
public bool BuildHfs;
public ulong TitleId;
public string BenchType;
public double CpuFrequencyGhz;
public IntegrityCheckLevel IntegrityLevel
{

View file

@ -24,6 +24,9 @@ namespace hactoolnet
private const int BatchCipherBenchSize = 1024 * 1024;
// ReSharper disable once UnusedMember.Local
private const int SingleBlockCipherBenchSize = 1024 * 128;
private const int ShaBenchSize = 1024 * 128;
private static double CpuFrequency { get; set; }
private static void CopyBenchmark(IStorage src, IStorage dst, int iterations, string label, IProgressReport logger)
{
@ -186,7 +189,7 @@ namespace hactoolnet
var input = new byte[BatchCipherBenchSize];
var output = new byte[BatchCipherBenchSize];
Func<double, string> resultPrinter = time => Util.GetBytesReadable((long)(BatchCipherBenchSize / time)) + "/s";
Func<double, string> resultPrinter = time => GetPerformanceString(time, BatchCipherBenchSize);
// Skip the first benchmark set if we don't have AES-NI intrinsics
for (int i = Aes.IsAesNiSupported() ? 0 : 1; i < 2; i++)
@ -235,7 +238,7 @@ namespace hactoolnet
var input = new byte[SingleBlockCipherBenchSize];
var output = new byte[SingleBlockCipherBenchSize];
Func<double, string> resultPrinter = time => Util.GetBytesReadable((long)(SingleBlockCipherBenchSize / time)) + "/s";
Func<double, string> resultPrinter = time => GetPerformanceString(time, SingleBlockCipherBenchSize);
bench.Register("AES single-block encrypt", () => { }, EncryptBlocks, resultPrinter);
bench.Register("AES single-block decrypt", () => { }, DecryptBlocks, resultPrinter);
@ -284,6 +287,35 @@ namespace hactoolnet
#endif
}
private static void RegisterShaBenchmarks(MultiBenchmark bench)
{
var input = new byte[ShaBenchSize];
var digest = new byte[Sha256.DigestSize];
Func<double, string> resultPrinter = time => GetPerformanceString(time, ShaBenchSize);
RegisterHash("SHA-256 built-in", () => new Sha256Generator());
void RegisterHash(string name, Func<IHash> hashGenerator)
{
IHash hash = null;
Action setup = () =>
{
hash = hashGenerator();
hash.Initialize();
};
Action action = () =>
{
hash.Update(input);
hash.GetHash(digest);
};
bench.Register(name, setup, action, resultPrinter);
}
}
private static void RunCipherBenchmark(Func<ICipher> cipherNet, Func<ICipher> cipherLibHac,
CipherTaskSeparate function, bool benchBlocked, string label, IProgressReport logger)
{
@ -341,8 +373,24 @@ namespace hactoolnet
}
}
private static string GetPerformanceString(double seconds, long bytes)
{
string cyclesPerByteString = string.Empty;
double bytesPerSec = bytes / seconds;
if (CpuFrequency > 0)
{
double cyclesPerByte = CpuFrequency / bytesPerSec;
cyclesPerByteString = $" ({cyclesPerByte:N3}x)";
}
return Util.GetBytesReadable((long)bytesPerSec) + "/s" + cyclesPerByteString;
}
public static void Process(Context ctx)
{
CpuFrequency = ctx.Options.CpuFrequencyGhz * 1_000_000_000;
switch (ctx.Options.BenchType?.ToLower())
{
case "aesctr":
@ -465,6 +513,7 @@ namespace hactoolnet
RegisterAesSequentialBenchmarks(bench);
RegisterAesSingleBlockBenchmarks(bench);
RegisterShaBenchmarks(bench);
bench.Run();
break;