diff --git a/src/DotFastLZ.Benchmark/Benchmark.cs b/src/DotFastLZ.Benchmark/Benchmark.cs new file mode 100644 index 0000000..18c97c7 --- /dev/null +++ b/src/DotFastLZ.Benchmark/Benchmark.cs @@ -0,0 +1,83 @@ +using System; +using System.Diagnostics; + +namespace DotFastLZ.Benchmark; + +public static class Benchmarks +{ + public static BenchmarkResult Start(string name, string filename, byte[] srcBytes, byte[] dstBytes, Func compress, Func decompress) + { + var result = new BenchmarkResult(); + result.Name = name; + result.FileName = filename; + result.SourceByteLength = srcBytes.Length; + result.Compression.ElapsedWatch = new Stopwatch(); + result.Compression.ElapsedWatch.Start(); + for (int i = 0; i < 5; ++i) + { + long size = compress.Invoke(srcBytes, dstBytes); + result.Compression.InputBytes += result.SourceByteLength; + result.Compression.OutputBytes += size; + result.Times += 1; + } + + result.Compression.ElapsedWatch.Stop(); + + var decompInputLength = result.Compression.OutputBytes / result.Times; + //dstBytes.AsSpan(0, (int)(compressedResult.DestBytes / compressedResult.Times)).CopyTo(srcBytes); + + result.Decompression.ElapsedWatch = new Stopwatch(); + result.Decompression.ElapsedWatch.Start(); + for (int i = 0; i < 5; ++i) + { + long size = decompress.Invoke(dstBytes, decompInputLength, srcBytes); + result.Decompression.InputBytes += decompInputLength; + result.Decompression.OutputBytes += size; + result.Times += 1; + } + + result.Decompression.ElapsedWatch.Stop(); + + //Console.WriteLine(result.ToString()); + return result; + } +} + +public class Benchmark +{ + public virtual string Name => "unknown"; + + public virtual BenchmarkResult Start(string filename, byte[] srcBytes, byte[] dstBytes) + { + return null; + } +} + +public class BenchmarkMemCopy : Benchmark +{ + public override string Name => "memcpy"; + + //var memoryCopy = Benchmark($"memcpy", filename, srcBytes.ToArray(), dstBytes, CompressMemcpy, DecompressMemcpy); + + public BenchmarkMemCopy() + { + } + + public override BenchmarkResult Start(string filename, byte[] srcBytes, byte[] dstBytes) + { + return Benchmarks.Start(Name, filename, srcBytes, dstBytes, CompressMemcpy, DecompressMemcpy); + } + + + public static long CompressMemcpy(byte[] srcBytes, byte[] dstBytes) + { + srcBytes.CopyTo(new Span(dstBytes)); + return srcBytes.Length; + } + + public static long DecompressMemcpy(byte[] srcBytes, long size, byte[] dstBytes) + { + srcBytes.AsSpan(0, (int)size).CopyTo(new Span(dstBytes)); + return size; + } +} \ No newline at end of file diff --git a/src/DotFastLZ.Benchmark/BenchmarkResult.cs b/src/DotFastLZ.Benchmark/BenchmarkResult.cs index a5bf282..9967583 100644 --- a/src/DotFastLZ.Benchmark/BenchmarkResult.cs +++ b/src/DotFastLZ.Benchmark/BenchmarkResult.cs @@ -2,8 +2,12 @@ public class BenchmarkResult { - public const int CollSize = 4; + public const int CollSize = 6; + public string Name; + public string FileName; + public long SourceByteLength; + public int Times; public BenchmarkSpeed Compression; public BenchmarkSpeed Decompression; @@ -13,7 +17,8 @@ public override string ToString() var result = ""; result += $"{Name}\n"; result += $" - times: {Times}\n"; - result += $" - source bytes: {Compression.InputBytes / Times}\n"; + result += $" - filename : {FileName}\n"; + result += $" - source bytes: {ToSourceKbString()} kB/s\n"; result += $" - compression bytes: {Compression.OutputBytes / Times}\n"; result += $" - compression rate: {Compression.ComputeRate():F2}%\n"; result += $" - compression speed: {Compression.ComputeSpeed():F2} MB/s\n"; @@ -22,6 +27,12 @@ public override string ToString() return result; } + public string ToSourceKbString() + { + double mb = (double)SourceByteLength / 1024; + return $"{mb:F2}"; + } + public double ComputeTotalSpeed() { return Compression.ComputeSpeed() + Decompression.ComputeSpeed(); diff --git a/src/DotFastLZ.Benchmark/Program.cs b/src/DotFastLZ.Benchmark/Program.cs index 85811ad..e4668b5 100644 --- a/src/DotFastLZ.Benchmark/Program.cs +++ b/src/DotFastLZ.Benchmark/Program.cs @@ -17,12 +17,15 @@ public static void Main(string[] args) try { R.ExtractAll(); + + var totalResults = new List(); foreach (var file in R.SourceFiles) { var results = BenchmarkFile(file); - Print($"Benchmark : compression {file}", results); - //break; + totalResults.AddRange(results); } + + Print($"Benchmark", totalResults); } catch (Exception e) { @@ -35,98 +38,49 @@ public static void Main(string[] args) } } - private static List BenchmarkFile(string file) + private static List BenchmarkFile(string filename) { var results = new List(); - var filepath = R.Find(Path.Combine(R.Prefix, file)); + var filepath = R.Find(Path.Combine(R.Prefix, filename)); var srcBytes = R.ToBytes(filepath); var dstBytes = new byte[srcBytes.Length * 2]; // memcpy - var memoryCopy = Benchmark($"memcpy", srcBytes.ToArray(), dstBytes, CompressMemcpy, DecompressMemcpy); + var benchmark = new BenchmarkMemCopy(); + var memoryCopy = benchmark.Start(filename, srcBytes.ToArray(), dstBytes); results.Add(memoryCopy); - // DotFastLZ fastlz - var fastlzLv1 = Benchmark($"DotFastLZ.Compression L1", srcBytes.ToArray(), dstBytes, CompressDotFastLZL1, DecompressDotFastLZ); - var fastlzLv2 = Benchmark($"DotFastLZ.Compression L2", srcBytes.ToArray(), dstBytes, CompressDotFastLZL2, DecompressDotFastLZ); - results.Add(fastlzLv1); - results.Add(fastlzLv2); - - // K4os LZ4 - var k4osL01 = Benchmark($"K4os.Compression.LZ4 L00", srcBytes.ToArray(), dstBytes, - (s, d) => CompressK4osLZ4(s, d, LZ4Level.L00_FAST), DecompressK4osLZ4); - var k4osL12 = Benchmark($"K4os.Compression.LZ4 L12", srcBytes.ToArray(), dstBytes, - (s, d) => CompressK4osLZ4(s, d, LZ4Level.L12_MAX), DecompressK4osLZ4); - var k4osL03HC = Benchmark($"K4os.Compression.LZ4 L03_HC", srcBytes.ToArray(), dstBytes, - (s, d) => CompressK4osLZ4(s, d, LZ4Level.L03_HC), DecompressK4osLZ4); - var k4osL09HC = Benchmark($"K4os.Compression.LZ4 L09_HC", srcBytes.ToArray(), dstBytes, - (s, d) => CompressK4osLZ4(s, d, LZ4Level.L09_HC), DecompressK4osLZ4); - results.Add(k4osL01); - results.Add(k4osL12); - results.Add(k4osL03HC); - results.Add(k4osL09HC); - - var zipFastest = Benchmark($"System.IO.Compression.ZipArchive Fastest", srcBytes.ToArray(), dstBytes, - (s, d) => CompressZip(s, d, CompressionLevel.Fastest), DecompressZip); - var zipOptimal = Benchmark($"System.IO.Compression.ZipArchive Optimal", srcBytes.ToArray(), dstBytes, - (s, d) => CompressZip(s, d, CompressionLevel.Optimal), DecompressZip); - results.Add(zipFastest); - results.Add(zipOptimal); + // // DotFastLZ fastlz + // var fastlzLv1 = Benchmark($"DotFastLZ.Compression L1", filename, srcBytes.ToArray(), dstBytes, CompressDotFastLZL1, DecompressDotFastLZ); + // var fastlzLv2 = Benchmark($"DotFastLZ.Compression L2", filename, srcBytes.ToArray(), dstBytes, CompressDotFastLZL2, DecompressDotFastLZ); + // results.Add(fastlzLv1); + // results.Add(fastlzLv2); + // + // // K4os LZ4 + // var k4osL01 = Benchmark($"K4os.Compression.LZ4 L00", filename, + // srcBytes.ToArray(), dstBytes, (s, d) => CompressK4osLZ4(s, d, LZ4Level.L00_FAST), DecompressK4osLZ4); + // var k4osL12 = Benchmark($"K4os.Compression.LZ4 L12", filename, + // srcBytes.ToArray(), dstBytes, (s, d) => CompressK4osLZ4(s, d, LZ4Level.L12_MAX), DecompressK4osLZ4); + // var k4osL03HC = Benchmark($"K4os.Compression.LZ4 L03_HC", filename, + // srcBytes.ToArray(), dstBytes, (s, d) => CompressK4osLZ4(s, d, LZ4Level.L03_HC), DecompressK4osLZ4); + // var k4osL09HC = Benchmark($"K4os.Compression.LZ4 L09_HC", filename, + // srcBytes.ToArray(), dstBytes, (s, d) => CompressK4osLZ4(s, d, LZ4Level.L09_HC), DecompressK4osLZ4); + // results.Add(k4osL01); + // results.Add(k4osL12); + // results.Add(k4osL03HC); + // results.Add(k4osL09HC); + // + // var zipFastest = Benchmark($"System.IO.Compression.ZipArchive Fastest", filename, + // srcBytes.ToArray(), dstBytes, (s, d) => CompressZip(s, d, CompressionLevel.Fastest), DecompressZip); + // var zipOptimal = Benchmark($"System.IO.Compression.ZipArchive Optimal", filename, + // srcBytes.ToArray(), dstBytes, (s, d) => CompressZip(s, d, CompressionLevel.Optimal), DecompressZip); + // results.Add(zipFastest); + // results.Add(zipOptimal); return results; } - private static BenchmarkResult Benchmark(string name, byte[] srcBytes, byte[] dstBytes, Func compress, Func decompress) - { - long compressionSourceByteLength = srcBytes.Length; - - var result = new BenchmarkResult(); - result.Name = name; - result.Compression.ElapsedWatch = new Stopwatch(); - result.Compression.ElapsedWatch.Start(); - for (int i = 0; i < 5; ++i) - { - long size = compress.Invoke(srcBytes, dstBytes); - result.Compression.InputBytes += compressionSourceByteLength; - result.Compression.OutputBytes += size; - result.Times += 1; - } - - result.Compression.ElapsedWatch.Stop(); - - var decompInputLength = result.Compression.OutputBytes / result.Times; - //dstBytes.AsSpan(0, (int)(compressedResult.DestBytes / compressedResult.Times)).CopyTo(srcBytes); - - result.Decompression.ElapsedWatch = new Stopwatch(); - result.Decompression.ElapsedWatch.Start(); - for (int i = 0; i < 5; ++i) - { - long size = decompress.Invoke(dstBytes, decompInputLength, srcBytes); - result.Decompression.InputBytes += decompInputLength; - result.Decompression.OutputBytes += size; - result.Times += 1; - } - - result.Decompression.ElapsedWatch.Stop(); - - //Console.WriteLine(result.ToString()); - return result; - } - - - private static long CompressMemcpy(byte[] srcBytes, byte[] dstBytes) - { - srcBytes.CopyTo(new Span(dstBytes)); - return srcBytes.Length; - } - - private static long DecompressMemcpy(byte[] srcBytes, long size, byte[] dstBytes) - { - srcBytes.AsSpan(0, (int)size).CopyTo(new Span(dstBytes)); - return size; - } - private static long CompressZip(byte[] srcBytes, byte[] dstBytes, CompressionLevel level) { @@ -195,47 +149,58 @@ private static void Print(string headline, List results) for (int i = 0; i < rows.Count; i++) { widths[0] = Math.Max(rows[i].Name.Length, widths[0]); - widths[1] = Math.Max(rows[i].Compression.ToSpeedString().Length, widths[1]); - widths[2] = Math.Max(rows[i].Decompression.ToSpeedString().Length, widths[2]); - widths[3] = Math.Max(rows[i].Compression.ToRateString().Length, widths[3]); + widths[1] = Math.Max(rows[i].FileName.Length, widths[1]); + widths[2] = Math.Max(rows[i].ToSourceKbString().Length, widths[2]); + widths[3] = Math.Max(rows[i].Compression.ToSpeedString().Length, widths[3]); + widths[4] = Math.Max(rows[i].Decompression.ToSpeedString().Length, widths[4]); + widths[5] = Math.Max(rows[i].Compression.ToRateString().Length, widths[5]); } var headName = "Name"; + var headFilename = "Filename"; + var headFileSize = "File kB"; var headCompMbs = "Comp. MB/s"; var headDecompMbs = "Decomp. MB/s"; var headRate = "Rate"; - + widths[0] = Math.Max(widths[0], headName.Length) + 1; - widths[1] = Math.Max(widths[1], headCompMbs.Length) + 1; - widths[2] = Math.Max(widths[2], headDecompMbs.Length) + 1; - widths[3] = Math.Max(widths[3], headRate.Length) + 1; + widths[1] = Math.Max(widths[1], headFilename.Length) + 1; + widths[2] = Math.Max(widths[2], headFileSize.Length) + 1; + widths[3] = Math.Max(widths[3], headCompMbs.Length) + 1; + widths[4] = Math.Max(widths[4], headDecompMbs.Length) + 1; + widths[5] = Math.Max(widths[5], headRate.Length) + 1; Console.WriteLine(); Console.WriteLine($"### {headline} ###"); Console.WriteLine(); - // 표 출력 Console.WriteLine("| " + headName + new string(' ', widths[0] - headName.Length) + "| " + - headCompMbs + new string(' ', widths[1] - headCompMbs.Length) + "| " + - headDecompMbs + new string(' ', widths[2] - headDecompMbs.Length) + "| " + - headRate + new string(' ', widths[3] - headRate.Length) + "|"); + headFilename + new string(' ', widths[1] - headFilename.Length) + "| " + + headFileSize + new string(' ', widths[2] - headFileSize.Length) + "| " + + headCompMbs + new string(' ', widths[3] - headCompMbs.Length) + "| " + + headDecompMbs + new string(' ', widths[4] - headDecompMbs.Length) + "| " + + headRate + new string(' ', widths[5] - headRate.Length) + "|"); Console.WriteLine("|-" + new string('-', widths[0]) + "|-" + new string('-', widths[1]) + "|-" + new string('-', widths[2]) + "|-" + - new string('-', widths[3]) + "|"); + new string('-', widths[3]) + "|-" + + new string('-', widths[4]) + "|-" + + new string('-', widths[5]) + "|"); foreach (var row in rows) { Console.WriteLine( "| " + row.Name.PadRight(widths[0]) + "| " + - row.Compression.ToSpeedString().PadRight(widths[1]) + "| " + - row.Decompression.ToSpeedString().PadRight(widths[2]) + "| " + - row.Compression.ToRateString().PadRight(widths[3]) + "|" + row.FileName.PadRight(widths[1]) + "| " + + row.ToSourceKbString().PadRight(widths[2]) + "| " + + row.Compression.ToSpeedString().PadRight(widths[3]) + "| " + + row.Decompression.ToSpeedString().PadRight(widths[4]) + "| " + + row.Compression.ToRateString().PadRight(widths[5]) + "|" ); } }