Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
ied206 committed Aug 27, 2023
2 parents 0b0b9c0 + 1701804 commit 3907d8a
Show file tree
Hide file tree
Showing 177 changed files with 159,997 additions and 503 deletions.
165 changes: 153 additions & 12 deletions Benchmark/BenchConfig.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,175 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
#if ENABLE_MEMORY_PROFILER
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
#endif
using BenchmarkDotNet.Filters;
using BenchmarkDotNet.Order;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

namespace Benchmark
{
#region (Base) BenchConfig
public class BenchConfig : ManualConfig
{
public const string ZLib = "ZLib";
public const string XZ = "XZ";
public const string LZ4 = "LZ4";
public const string ZSTD = "ZSTD";
public const string ZLib = nameof(ZLib);
public const string XZ = nameof(XZ);
public const string LZ4 = nameof(LZ4);
public const string Zstd = nameof(Zstd);

public BenchConfig()
private readonly AlgorithmFlags _algoFlags;

public BenchConfig() :
base()
{
switch (Program.Opts.Algorithms)
WithOptions(ConfigOptions.Default);

_algoFlags = Program.Opts.Algorithms;

// Memory Profiler - Takes up too much time
#if ENABLE_MEMORY_PROFILER
AddDiagnoser(MemoryDiagnoser.Default);
if (IsAdminPrivilege())
AddDiagnoser(new NativeMemoryProfiler());
#endif

// Catergory - Run only designated compression algorithm tests
switch (_algoFlags)
{
case AlgorithmFlags.None:
case AlgorithmFlags.All:
return;
}

List<string> categories = new List<string>();
if (Program.Opts.Algorithms.HasFlag(AlgorithmFlags.ZLib))
if (_algoFlags.HasFlag(AlgorithmFlags.ZLibNg) || _algoFlags.HasFlag(AlgorithmFlags.ZLibUp))
categories.Add(ZLib);
else if (Program.Opts.Algorithms.HasFlag(AlgorithmFlags.XZ))

if (_algoFlags.HasFlag(AlgorithmFlags.XZ))
categories.Add(XZ);
else if (Program.Opts.Algorithms.HasFlag(AlgorithmFlags.LZ4))
if (_algoFlags.HasFlag(AlgorithmFlags.LZ4))
categories.Add(LZ4);
if (_algoFlags.HasFlag(AlgorithmFlags.Zstd))
categories.Add(Zstd);

AddFilter(new AnyCategoriesFilter(categories.ToArray()));
}

#if ENABLE_MEMORY_PROFILER
private static bool IsAdminPrivilege()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return false;

switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X86:
case Architecture.X64:
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
default:
return false;
}
}
#endif
}
#endregion

#region ParamOrderConfig
public class ParamOrderer : IOrderer
{
public bool SeparateLogicalGroups => true;

public IEnumerable<BenchmarkCase> GetExecutionOrder(ImmutableArray<BenchmarkCase> benchmarksCase, IEnumerable<BenchmarkLogicalGroupRule> order = null)
{
//return benchmarksCase.OrderByDescending(x => x.Parameters.DisplayInfo)
// .OrderByDescending(x => x.Descriptor.WorkloadMethodDisplayInfo);
return benchmarksCase;
}

public string GetHighlightGroupKey(BenchmarkCase benchmarkCase)
{
return null;
}

public string GetLogicalGroupKey(ImmutableArray<BenchmarkCase> allBenchmarksCases, BenchmarkCase benchmarkCase)
{
//if (benchmarkCase.Parameters.GetArgument("SrcFileName").Value is not string srcFileName)
// return benchmarkCase.Job.DisplayInfo;
return benchmarkCase.Parameters.DisplayInfo;
}

public IEnumerable<IGrouping<string, BenchmarkCase>> GetLogicalGroupOrder(IEnumerable<IGrouping<string, BenchmarkCase>> logicalGroups, IEnumerable<BenchmarkLogicalGroupRule> order = null)
{
return logicalGroups.OrderBy(x => x.Key);
}

public IEnumerable<BenchmarkCase> GetSummaryOrder(ImmutableArray<BenchmarkCase> benchmarksCases, Summary summary)
{
return benchmarksCases.OrderBy(x => x.Parameters.ValueInfo);
}
}

public class ParamOrderConfig : BenchConfig
{
public ParamOrderConfig() : base()
{
// Orderder
Orderer = new ParamOrderer();
}
}
#endregion

#region ReturnValueColumn
public abstract class ReturnValueColumn : IColumn
{
public virtual string Id { get; protected set; } = $"{nameof(ReturnValueColumn)}.Return";
public virtual string ColumnName { get; protected set; } = "Return";
public virtual string Legend => $"Return value of the benchmark case.";
public bool AlwaysShow => true;
public ColumnCategory Category => ColumnCategory.Custom;
public int PriorityInCategory => 0;
public bool IsNumeric => true;
public UnitType UnitType => UnitType.Size;

public ReturnValueColumn()
{
}

public string GetValue(Summary summary, BenchmarkCase benchmarkCase)
{
// Create an instance of benchmark instances
Descriptor descriptor = benchmarkCase.Descriptor;
object instance = Activator.CreateInstance(descriptor.Type);
descriptor.GlobalSetupMethod?.Invoke(instance, Array.Empty<object>());

// Get parameters from benchmarkCase & Set parameters to benchmark instances
if (!LoadParams(instance, benchmarkCase))
return "Param load failed";

// Run a benchmark ourselves and record return value
object ret = descriptor.WorkloadMethod.Invoke(instance, null);
return ParseReturnObject(ret);
}

public string GetValue(Summary summary, BenchmarkCase benchmarkCase, SummaryStyle style) => GetValue(summary, benchmarkCase);

public bool IsAvailable(Summary summary) => true;
public bool IsDefault(Summary summary, BenchmarkCase benchmarkCase) => false;

public abstract bool LoadParams(object instance, BenchmarkCase benchmarkCase);
public abstract string ParseReturnObject(object ret);

protected static string ParseDouble(object ret)
{
if (ret is not double retVal)
return $"[{ret.GetType().Name}] is not a dobule";
return retVal.ToString("0.000");
}
}
}
#endregion
}
113 changes: 84 additions & 29 deletions Benchmark/BenchProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ namespace Benchmark
public enum AlgorithmFlags
{
None = 0x0,
ZLib = 0x1,
XZ = 0x2,
LZ4 = 0x4,
Zstd = 0x8,
All = ZLib | XZ | LZ4 | Zstd,
ZLib = 0x2,
ZLibUp = 0x1,
ZLibNg = 0x2,
XZ = 0x4,
LZ4 = 0x8,
Zstd = 0x10,
All = ZLibUp | ZLibNg | XZ | LZ4 | Zstd,
}

public abstract class ParamOptions
{
[Option("algo", Default = AlgorithmFlags.All, HelpText = "Choose algorithms to benchmark | zlib,xz,lz4,all")]
[Option("algo", Default = AlgorithmFlags.All, HelpText = "Choose algorithms to benchmark | zlib,xz,lz4,zstd,all")]
public AlgorithmFlags Algorithms { get; set; }
}

Expand All @@ -44,14 +46,20 @@ public class HashBenchOptions : ParamOptions { }

[Verb("buffer", HelpText = "Benchmark buffer size")]
public class BufferSizeBenchOptions : ParamOptions { }

[Verb("conf-test", HelpText = "Test BenchConfig")]
public class ConfTestBenchOptions : ParamOptions { }
#endregion

#region Program
public static class Program
{
#region Directories
public static string BaseDir => Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", ".."));
public static string SampleDir => Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", "..", "..", "..", "Samples"));
/// <summary>
/// Used in real benchmarks
/// </summary>
public static string BaseDir { get; private set; } = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", ".."));
public static string SampleDir { get; private set; } = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", "..", "..", "..", "Samples"));
#endregion

#region PrintErrorAndExit
Expand All @@ -63,13 +71,42 @@ internal static void PrintErrorAndExit(IEnumerable<Error> errs)
}
#endregion

#region Static properties
private static AlgorithmFlags _initFlags = AlgorithmFlags.None;
#endregion

#region Init and Cleanup
public static void NativeGlobalInit()
public static void SetGlobalDir()
{
const string runtimes = "runtimes";

/// Paths used in real benchmarks
BaseDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", ".."));
SampleDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", "..", "..", "..", "Samples"));

string runtimeRootDir = Path.Combine(BaseDir, runtimes);
if (!Directory.Exists(runtimeRootDir))
{ // Paths used in summary/results
// CompRatioConfig has return value collecting column. It runs at result print time.
BaseDir = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory);
SampleDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "Samples"));
}
}

public static void NativeGlobalInit(AlgorithmFlags flags)
{
// Unload any native library that has been loaded.
NativeGlobalCleanup();

_initFlags = flags;

SetGlobalDir();

const string runtimes = "runtimes";
const string native = "native";

string zlibPath = null;
string zlibNgCompatPath = null;
string zlibUpstreamPath = null;
string xzPath = null;
string lz4Path = null;
string zstdPath = null;
Expand All @@ -82,7 +119,8 @@ public static void NativeGlobalInit()
Architecture.Arm64 => Path.Combine(BaseDir, runtimes, "win-arm64", native),
_ => throw new PlatformNotSupportedException(),
};
zlibPath = Path.Combine(libDir, "zlibwapi.dll");
zlibNgCompatPath = Path.Combine(libDir, "zlib1.dll");
zlibUpstreamPath = Path.Combine(libDir, "zlibwapi-upstream.dll");
xzPath = Path.Combine(libDir, "liblzma.dll");
lz4Path = Path.Combine(libDir, "liblz4.dll");
zstdPath = Path.Combine(libDir, "libzstd.dll");
Expand All @@ -96,7 +134,8 @@ public static void NativeGlobalInit()
Architecture.Arm64 => Path.Combine(BaseDir, runtimes, "linux-arm64", native),
_ => throw new PlatformNotSupportedException(),
};
zlibPath = Path.Combine(libDir, "libz.so");
zlibNgCompatPath = Path.Combine(libDir, "libz.so");
zlibUpstreamPath = Path.Combine(libDir, "libz-upstream.so");
xzPath = Path.Combine(libDir, "liblzma.so");
lz4Path = Path.Combine(libDir, "liblz4.so");
zstdPath = Path.Combine(libDir, "libzstd.so");
Expand All @@ -109,27 +148,44 @@ public static void NativeGlobalInit()
Architecture.Arm64 => Path.Combine(BaseDir, runtimes, "osx-arm64", native),
_ => throw new PlatformNotSupportedException(),
};
zlibPath = Path.Combine(libDir, "libz.dylib");
zlibNgCompatPath = Path.Combine(libDir, "libz.dylib");
zlibUpstreamPath = Path.Combine(libDir, "libz-upstream.dylib");
xzPath = Path.Combine(libDir, "liblzma.dylib");
lz4Path = Path.Combine(libDir, "liblz4.dylib");
zstdPath = Path.Combine(libDir, "libzstd.dylib");
}

if (zlibPath == null || xzPath == null || lz4Path == null)
if (zlibNgCompatPath == null || zlibUpstreamPath == null ||
xzPath == null || lz4Path == null)
throw new PlatformNotSupportedException();

Joveler.Compression.ZLib.ZLibInit.GlobalInit(zlibPath);
Joveler.Compression.XZ.XZInit.GlobalInit(xzPath);
Joveler.Compression.LZ4.LZ4Init.GlobalInit(lz4Path);
Joveler.Compression.Zstd.ZstdInit.GlobalInit(zstdPath);
// zlib-ng and zlib are mutually exclusive.
// Joveler.Compression.ZLib cannot load two or more zlib at once.
if (flags.HasFlag(AlgorithmFlags.ZLibNg))
Joveler.Compression.ZLib.ZLibInit.GlobalInit(zlibNgCompatPath, false);
else if (flags.HasFlag(AlgorithmFlags.ZLibUp))
Joveler.Compression.ZLib.ZLibInit.GlobalInit(zlibUpstreamPath, true);

if (flags.HasFlag(AlgorithmFlags.XZ))
Joveler.Compression.XZ.XZInit.GlobalInit(xzPath);
if (flags.HasFlag(AlgorithmFlags.LZ4))
Joveler.Compression.LZ4.LZ4Init.GlobalInit(lz4Path);
if (flags.HasFlag(AlgorithmFlags.Zstd))
Joveler.Compression.Zstd.ZstdInit.GlobalInit(zstdPath);
}

public static void NativeGlobalCleanup()
{
Joveler.Compression.ZLib.ZLibInit.GlobalCleanup();
Joveler.Compression.XZ.XZInit.GlobalCleanup();
Joveler.Compression.LZ4.LZ4Init.GlobalCleanup();
Joveler.Compression.Zstd.ZstdInit.GlobalCleanup();
if (_initFlags.HasFlag(AlgorithmFlags.ZLibNg) || _initFlags.HasFlag(AlgorithmFlags.ZLibUp))
Joveler.Compression.ZLib.ZLibInit.GlobalCleanup();
if (_initFlags.HasFlag(AlgorithmFlags.XZ))
Joveler.Compression.XZ.XZInit.GlobalCleanup();
if (_initFlags.HasFlag(AlgorithmFlags.LZ4))
Joveler.Compression.LZ4.LZ4Init.GlobalCleanup();
if (_initFlags.HasFlag(AlgorithmFlags.Zstd))
Joveler.Compression.Zstd.ZstdInit.GlobalCleanup();

_initFlags = AlgorithmFlags.None;
}
#endregion

Expand All @@ -148,23 +204,19 @@ public static void Main(string[] args)
});

argParser.ParseArguments<AllBenchOptions,
CompBenchOptions, DecompBenchOptions, XZMultiOptionBenchOptions, HashBenchOptions, BufferSizeBenchOptions>(args)
CompBenchOptions, DecompBenchOptions, XZMultiOptionBenchOptions,
HashBenchOptions, BufferSizeBenchOptions, ConfTestBenchOptions>(args)
.WithParsed<AllBenchOptions>(x => Opts = x)
.WithParsed<CompBenchOptions>(x => Opts = x)
.WithParsed<DecompBenchOptions>(x => Opts = x)
.WithParsed<XZMultiOptionBenchOptions>(x => Opts = x)
.WithParsed<HashBenchOptions>(x => Opts = x)
.WithParsed<BufferSizeBenchOptions>(x => Opts = x)
.WithParsed<ConfTestBenchOptions>(x => Opts = x)
.WithNotParsed(PrintErrorAndExit);
Debug.Assert(Opts != null, $"{nameof(Opts)} != null");

// InvertedTomato.Crc is the slowest, and ships unoptimized binaries.
// Disable for awhile to avoid BenchmarkDotNet's unoptimized run error.
#if INVERTEDTOMATO_CRC_EANBLE
ManualConfig config = DefaultConfig.Instance.WithOptions(ConfigOptions.DisableOptimizationsValidator);
#else
ManualConfig config = DefaultConfig.Instance.WithOptions(ConfigOptions.Default);
#endif

switch (Opts)
{
Expand All @@ -190,6 +242,9 @@ public static void Main(string[] args)
case BufferSizeBenchOptions _:
BenchmarkRunner.Run<BufferSizeBench>(config);
break;
case ConfTestBenchOptions _:
BenchmarkRunner.Run<ConfigTestBench>();
break;
}
}
#endregion
Expand Down
Loading

0 comments on commit 3907d8a

Please sign in to comment.