mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add crypto benchmarks
This commit is contained in:
parent
ff23a9179c
commit
e02e719ea5
2 changed files with 136 additions and 0 deletions
75
src/hactoolnet/MultiBenchmark.cs
Normal file
75
src/hactoolnet/MultiBenchmark.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace hactoolnet
|
||||||
|
{
|
||||||
|
internal class MultiBenchmark
|
||||||
|
{
|
||||||
|
public int RunsNeeded { get; set; } = 500;
|
||||||
|
|
||||||
|
private List<BenchmarkItem> Benchmarks { get; } = new List<BenchmarkItem>();
|
||||||
|
|
||||||
|
public void Register(string name, Action setupAction, Action runAction, Func<double, string> resultPrinter)
|
||||||
|
{
|
||||||
|
var benchmark = new BenchmarkItem
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
Setup = setupAction,
|
||||||
|
Run = runAction,
|
||||||
|
PrintResult = resultPrinter
|
||||||
|
};
|
||||||
|
|
||||||
|
Benchmarks.Add(benchmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
foreach (BenchmarkItem item in Benchmarks)
|
||||||
|
{
|
||||||
|
RunBenchmark(item);
|
||||||
|
|
||||||
|
Console.WriteLine($"{item.Name}: {item.Result}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunBenchmark(BenchmarkItem item)
|
||||||
|
{
|
||||||
|
double fastestRun = double.MaxValue;
|
||||||
|
var watch = new Stopwatch();
|
||||||
|
|
||||||
|
int runsSinceLastBest = 0;
|
||||||
|
|
||||||
|
while (runsSinceLastBest < RunsNeeded)
|
||||||
|
{
|
||||||
|
runsSinceLastBest++;
|
||||||
|
item.Setup();
|
||||||
|
|
||||||
|
watch.Restart();
|
||||||
|
item.Run();
|
||||||
|
watch.Stop();
|
||||||
|
|
||||||
|
if (fastestRun > watch.Elapsed.TotalSeconds)
|
||||||
|
{
|
||||||
|
fastestRun = watch.Elapsed.TotalSeconds;
|
||||||
|
|
||||||
|
runsSinceLastBest = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Time = fastestRun;
|
||||||
|
item.Result = item.PrintResult(item.Time);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BenchmarkItem
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public double Time { get; set; }
|
||||||
|
public string Result { get; set; }
|
||||||
|
|
||||||
|
public Action Setup { get; set; }
|
||||||
|
public Action Run { get; set; }
|
||||||
|
public Func<double, string> PrintResult { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ namespace hactoolnet
|
||||||
private const int BlockSizeBlocked = 0x10;
|
private const int BlockSizeBlocked = 0x10;
|
||||||
private const int BlockSizeSeparate = 0x10;
|
private const int BlockSizeSeparate = 0x10;
|
||||||
|
|
||||||
|
private const int BatchCipherBenchSize = 1024 * 1024;
|
||||||
|
|
||||||
private static void CopyBenchmark(IStorage src, IStorage dst, int iterations, string label, IProgressReport logger)
|
private static void CopyBenchmark(IStorage src, IStorage dst, int iterations, string label, IProgressReport logger)
|
||||||
{
|
{
|
||||||
// Warmup
|
// Warmup
|
||||||
|
@ -171,6 +173,53 @@ namespace hactoolnet
|
||||||
logger.LogMessage($"{label}{averageRate}/s, fastest run: {fastestRate}/s, slowest run: {slowestRate}/s");
|
logger.LogMessage($"{label}{averageRate}/s, fastest run: {fastestRate}/s, slowest run: {slowestRate}/s");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RegisterAllCipherBenchmarks(MultiBenchmark bench)
|
||||||
|
{
|
||||||
|
var input = new byte[BatchCipherBenchSize];
|
||||||
|
var output = new byte[BatchCipherBenchSize];
|
||||||
|
|
||||||
|
Func<double, string> resultPrinter = time => Util.GetBytesReadable((long)(BatchCipherBenchSize / time)) + "/s";
|
||||||
|
|
||||||
|
// Skip the first benchmark set if we don't have AES-NI intrinsics
|
||||||
|
for (int i = Aes.IsAesNiSupported() ? 0 : 1; i < 2; i++)
|
||||||
|
{
|
||||||
|
// Prefer .NET crypto on the second set
|
||||||
|
string nameSuffix = i == 1 ? "built-in " : string.Empty;
|
||||||
|
bool preferDotNetImpl = i == 1;
|
||||||
|
|
||||||
|
RegisterCipher($"AES-ECB {nameSuffix}encrypt",
|
||||||
|
() => Aes.CreateEcbEncryptor(new byte[0x10], preferDotNetImpl));
|
||||||
|
|
||||||
|
RegisterCipher($"AES-ECB {nameSuffix}decrypt",
|
||||||
|
() => Aes.CreateEcbDecryptor(new byte[0x10], preferDotNetImpl));
|
||||||
|
|
||||||
|
RegisterCipher($"AES-CBC {nameSuffix}encrypt",
|
||||||
|
() => Aes.CreateCbcEncryptor(new byte[0x10], new byte[0x10], preferDotNetImpl));
|
||||||
|
|
||||||
|
RegisterCipher($"AES-CBC {nameSuffix}decrypt",
|
||||||
|
() => Aes.CreateCbcDecryptor(new byte[0x10], new byte[0x10], preferDotNetImpl));
|
||||||
|
|
||||||
|
RegisterCipher($"AES-CTR {nameSuffix}decrypt",
|
||||||
|
() => Aes.CreateCtrDecryptor(new byte[0x10], new byte[0x10], preferDotNetImpl));
|
||||||
|
|
||||||
|
RegisterCipher($"AES-XTS {nameSuffix}encrypt",
|
||||||
|
() => Aes.CreateXtsEncryptor(new byte[0x10], new byte[0x10], new byte[0x10], preferDotNetImpl));
|
||||||
|
|
||||||
|
RegisterCipher($"AES-XTS {nameSuffix}decrypt",
|
||||||
|
() => Aes.CreateXtsDecryptor(new byte[0x10], new byte[0x10], new byte[0x10], preferDotNetImpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterCipher(string name, Func<ICipher> cipherGenerator)
|
||||||
|
{
|
||||||
|
ICipher cipher = null;
|
||||||
|
|
||||||
|
Action setup = () => cipher = cipherGenerator();
|
||||||
|
Action action = () => cipher.Transform(input, output);
|
||||||
|
|
||||||
|
bench.Register(name, setup, action, resultPrinter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void RunCipherBenchmark(Func<ICipher> cipherNet, Func<ICipher> cipherLibHac,
|
private static void RunCipherBenchmark(Func<ICipher> cipherNet, Func<ICipher> cipherLibHac,
|
||||||
CipherTaskSeparate function, bool benchBlocked, string label, IProgressReport logger)
|
CipherTaskSeparate function, bool benchBlocked, string label, IProgressReport logger)
|
||||||
{
|
{
|
||||||
|
@ -295,6 +344,7 @@ namespace hactoolnet
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "aescbcnew":
|
case "aescbcnew":
|
||||||
{
|
{
|
||||||
Func<ICipher> encryptorNet = () => Aes.CreateCbcEncryptor(new byte[0x10], new byte[0x10], true);
|
Func<ICipher> encryptorNet = () => Aes.CreateCbcEncryptor(new byte[0x10], new byte[0x10], true);
|
||||||
|
@ -325,6 +375,7 @@ namespace hactoolnet
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "aesxtsnew":
|
case "aesxtsnew":
|
||||||
{
|
{
|
||||||
Func<ICipher> encryptorNet = () => Aes.CreateXtsEncryptor(new byte[0x10], new byte[0x10], new byte[0x10], true);
|
Func<ICipher> encryptorNet = () => Aes.CreateXtsEncryptor(new byte[0x10], new byte[0x10], new byte[0x10], true);
|
||||||
|
@ -344,6 +395,16 @@ namespace hactoolnet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "crypto":
|
||||||
|
{
|
||||||
|
var bench = new MultiBenchmark();
|
||||||
|
|
||||||
|
RegisterAllCipherBenchmarks(bench);
|
||||||
|
|
||||||
|
bench.Run();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ctx.Logger.LogMessage("Unknown benchmark type.");
|
ctx.Logger.LogMessage("Unknown benchmark type.");
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue