Refactor (#94)

This commit is contained in:
Alexey Golub
2021-03-21 09:54:00 +02:00
committed by GitHub
parent 58df63a7ad
commit 7d3d79b861
228 changed files with 10480 additions and 8968 deletions

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using CliFx.Attributes;
using CliFx.Infrastructure;
namespace CliFx.Benchmarks
{
public partial class Benchmarks
{
[Command]
public class CliFxCommand : ICommand
{
[CommandOption("str", 's')]
public string? StrOption { get; set; }
[CommandOption("int", 'i')]
public int IntOption { get; set; }
[CommandOption("bool", 'b')]
public bool BoolOption { get; set; }
public ValueTask ExecuteAsync(IConsole console) => default;
}
[Benchmark(Description = "CliFx", Baseline = true)]
public async ValueTask<int> ExecuteWithCliFx() =>
await new CliApplicationBuilder()
.AddCommand<CliFxCommand>()
.Build()
.RunAsync(Arguments, new Dictionary<string, string>());
}
}

View File

@@ -0,0 +1,27 @@
using BenchmarkDotNet.Attributes;
using clipr;
namespace CliFx.Benchmarks
{
public partial class Benchmarks
{
public class CliprCommand
{
[NamedArgument('s', "str")]
public string? StrOption { get; set; }
[NamedArgument('i', "int")]
public int IntOption { get; set; }
[NamedArgument('b', "bool", Constraint = NumArgsConstraint.Optional, Const = true)]
public bool BoolOption { get; set; }
public void Execute()
{
}
}
[Benchmark(Description = "Clipr")]
public void ExecuteWithClipr() => CliParser.Parse<CliprCommand>(Arguments).Execute();
}
}

View File

@@ -0,0 +1,24 @@
using BenchmarkDotNet.Attributes;
using Cocona;
namespace CliFx.Benchmarks
{
public partial class Benchmarks
{
public class CoconaCommand
{
public void Execute(
[Option("str", new []{'s'})]
string? strOption,
[Option("int", new []{'i'})]
int intOption,
[Option("bool", new []{'b'})]
bool boolOption)
{
}
}
[Benchmark(Description = "Cocona")]
public void ExecuteWithCocona() => CoconaApp.Run<CoconaCommand>(Arguments);
}
}

View File

@@ -0,0 +1,30 @@
using BenchmarkDotNet.Attributes;
using CommandLine;
namespace CliFx.Benchmarks
{
public partial class Benchmarks
{
public class CommandLineParserCommand
{
[Option('s', "str")]
public string? StrOption { get; set; }
[Option('i', "int")]
public int IntOption { get; set; }
[Option('b', "bool")]
public bool BoolOption { get; set; }
public void Execute()
{
}
}
[Benchmark(Description = "CommandLineParser")]
public void ExecuteWithCommandLineParser() =>
new Parser()
.ParseArguments(Arguments, typeof(CommandLineParserCommand))
.WithParsed<CommandLineParserCommand>(c => c.Execute());
}
}

View File

@@ -0,0 +1,25 @@
using BenchmarkDotNet.Attributes;
using McMaster.Extensions.CommandLineUtils;
namespace CliFx.Benchmarks
{
public partial class Benchmarks
{
public class McMasterCommand
{
[Option("--str|-s")]
public string? StrOption { get; set; }
[Option("--int|-i")]
public int IntOption { get; set; }
[Option("--bool|-b")]
public bool BoolOption { get; set; }
public int OnExecute() => 0;
}
[Benchmark(Description = "McMaster.Extensions.CommandLineUtils")]
public int ExecuteWithMcMaster() => CommandLineApplication.Execute<McMasterCommand>(Arguments);
}
}

View File

@@ -0,0 +1,27 @@
using BenchmarkDotNet.Attributes;
using PowerArgs;
namespace CliFx.Benchmarks
{
public partial class Benchmarks
{
public class PowerArgsCommand
{
[ArgShortcut("--str"), ArgShortcut("-s")]
public string? StrOption { get; set; }
[ArgShortcut("--int"), ArgShortcut("-i")]
public int IntOption { get; set; }
[ArgShortcut("--bool"), ArgShortcut("-b")]
public bool BoolOption { get; set; }
public void Main()
{
}
}
[Benchmark(Description = "PowerArgs")]
public void ExecuteWithPowerArgs() => Args.InvokeMain<PowerArgsCommand>(Arguments);
}
}

View File

@@ -0,0 +1,44 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
namespace CliFx.Benchmarks
{
public partial class Benchmarks
{
public class SystemCommandLineCommand
{
public static int ExecuteHandler(string s, int i, bool b) => 0;
public Task<int> ExecuteAsync(string[] args)
{
var command = new RootCommand
{
new Option(new[] {"--str", "-s"})
{
Argument = new Argument<string?>()
},
new Option(new[] {"--int", "-i"})
{
Argument = new Argument<int>()
},
new Option(new[] {"--bool", "-b"})
{
Argument = new Argument<bool>()
}
};
command.Handler = CommandHandler.Create(
typeof(SystemCommandLineCommand).GetMethod(nameof(ExecuteHandler))!
);
return command.InvokeAsync(args);
}
}
[Benchmark(Description = "System.CommandLine")]
public async Task<int> ExecuteWithSystemCommandLine() =>
await new SystemCommandLineCommand().ExecuteAsync(Arguments);
}
}

View File

@@ -1,52 +1,20 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Order;
using BenchmarkDotNet.Running;
using CliFx.Benchmarks.Commands;
using CommandLine;
namespace CliFx.Benchmarks
{
[SimpleJob]
[RankColumn]
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
public class Benchmarks
public partial class Benchmarks
{
private static readonly string[] Arguments = {"--str", "hello world", "-i", "13", "-b"};
[Benchmark(Description = "CliFx", Baseline = true)]
public async ValueTask<int> ExecuteWithCliFx() =>
await new CliApplicationBuilder().AddCommand<CliFxCommand>().Build().RunAsync(Arguments, new Dictionary<string, string>());
[Benchmark(Description = "System.CommandLine")]
public async Task<int> ExecuteWithSystemCommandLine() =>
await new SystemCommandLineCommand().ExecuteAsync(Arguments);
[Benchmark(Description = "McMaster.Extensions.CommandLineUtils")]
public int ExecuteWithMcMaster() =>
McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute<McMasterCommand>(Arguments);
[Benchmark(Description = "CommandLineParser")]
public void ExecuteWithCommandLineParser() =>
new Parser()
.ParseArguments(Arguments, typeof(CommandLineParserCommand))
.WithParsed<CommandLineParserCommand>(c => c.Execute());
[Benchmark(Description = "PowerArgs")]
public void ExecuteWithPowerArgs() =>
PowerArgs.Args.InvokeMain<PowerArgsCommand>(Arguments);
[Benchmark(Description = "Clipr")]
public void ExecuteWithClipr() =>
clipr.CliParser.Parse<CliprCommand>(Arguments).Execute();
[Benchmark(Description = "Cocona")]
public void ExecuteWithCocona() =>
Cocona.CoconaApp.Run<CoconaCommand>(Arguments);
public static void Main() =>
BenchmarkRunner.Run<Benchmarks>(DefaultConfig.Instance.With(ConfigOptions.DisableOptimizationsValidator));
public static void Main() => BenchmarkRunner.Run<Benchmarks>(
DefaultConfig
.Instance
.With(ConfigOptions.DisableOptimizationsValidator)
);
}
}

View File

@@ -10,9 +10,9 @@
<PackageReference Include="clipr" Version="1.6.1" />
<PackageReference Include="Cocona" Version="1.5.0" />
<PackageReference Include="CommandLineParser" Version="2.8.0" />
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="3.0.0" />
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="3.1.0" />
<PackageReference Include="PowerArgs" Version="3.6.0" />
<PackageReference Include="System.CommandLine.Experimental" Version="0.3.0-alpha.19317.1" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20574.7" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,20 +0,0 @@
using System.Threading.Tasks;
using CliFx.Attributes;
namespace CliFx.Benchmarks.Commands
{
[Command]
public class CliFxCommand : ICommand
{
[CommandOption("str", 's')]
public string? StrOption { get; set; }
[CommandOption("int", 'i')]
public int IntOption { get; set; }
[CommandOption("bool", 'b')]
public bool BoolOption { get; set; }
public ValueTask ExecuteAsync(IConsole console) => default;
}
}

View File

@@ -1,20 +0,0 @@
using clipr;
namespace CliFx.Benchmarks.Commands
{
public class CliprCommand
{
[NamedArgument('s', "str")]
public string? StrOption { get; set; }
[NamedArgument('i', "int")]
public int IntOption { get; set; }
[NamedArgument('b', "bool", Constraint = NumArgsConstraint.Optional, Const = true)]
public bool BoolOption { get; set; }
public void Execute()
{
}
}
}

View File

@@ -1,17 +0,0 @@
using Cocona;
namespace CliFx.Benchmarks.Commands
{
public class CoconaCommand
{
public void Execute(
[Option("str", new []{'s'})]
string? strOption,
[Option("int", new []{'i'})]
int intOption,
[Option("bool", new []{'b'})]
bool boolOption)
{
}
}
}

View File

@@ -1,20 +0,0 @@
using CommandLine;
namespace CliFx.Benchmarks.Commands
{
public class CommandLineParserCommand
{
[Option('s', "str")]
public string? StrOption { get; set; }
[Option('i', "int")]
public int IntOption { get; set; }
[Option('b', "bool")]
public bool BoolOption { get; set; }
public void Execute()
{
}
}
}

View File

@@ -1,18 +0,0 @@
using McMaster.Extensions.CommandLineUtils;
namespace CliFx.Benchmarks.Commands
{
public class McMasterCommand
{
[Option("--str|-s")]
public string? StrOption { get; set; }
[Option("--int|-i")]
public int IntOption { get; set; }
[Option("--bool|-b")]
public bool BoolOption { get; set; }
public int OnExecute() => 0;
}
}

View File

@@ -1,20 +0,0 @@
using PowerArgs;
namespace CliFx.Benchmarks.Commands
{
public class PowerArgsCommand
{
[ArgShortcut("--str"), ArgShortcut("-s")]
public string? StrOption { get; set; }
[ArgShortcut("--int"), ArgShortcut("-i")]
public int IntOption { get; set; }
[ArgShortcut("--bool"), ArgShortcut("-b")]
public bool BoolOption { get; set; }
public void Main()
{
}
}
}

View File

@@ -1,34 +0,0 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Threading.Tasks;
namespace CliFx.Benchmarks.Commands
{
public class SystemCommandLineCommand
{
public static int ExecuteHandler(string s, int i, bool b) => 0;
public Task<int> ExecuteAsync(string[] args)
{
var command = new RootCommand
{
new Option(new[] {"--str", "-s"})
{
Argument = new Argument<string?>()
},
new Option(new[] {"--int", "-i"})
{
Argument = new Argument<int>()
},
new Option(new[] {"--bool", "-b"})
{
Argument = new Argument<bool>()
}
};
command.Handler = CommandHandler.Create(typeof(SystemCommandLineCommand).GetMethod(nameof(ExecuteHandler)));
return command.InvokeAsync(args);
}
}
}

View File

@@ -0,0 +1,22 @@
## CliFx.Benchmarks
All benchmarks below were ran with the following configuration:
```ini
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.14393.3443 (1607/AnniversaryUpdate/Redstone1)
Intel Core i5-4460 CPU 3.20GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
Frequency=3124994 Hz, Resolution=320.0006 ns, Timer=TSC
.NET Core SDK=3.1.100
[Host] : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT
DefaultJob : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT
```
| Method | Mean | Error | StdDev | Ratio | RatioSD | Rank |
| ------------------------------------ | ----------: | --------: | ---------: | ----: | ------: | ---: |
| CommandLineParser | 24.79 us | 0.166 us | 0.155 us | 0.49 | 0.00 | 1 |
| CliFx | 50.27 us | 0.248 us | 0.232 us | 1.00 | 0.00 | 2 |
| Clipr | 160.22 us | 0.817 us | 0.764 us | 3.19 | 0.02 | 3 |
| McMaster.Extensions.CommandLineUtils | 166.45 us | 1.111 us | 1.039 us | 3.31 | 0.03 | 4 |
| System.CommandLine | 170.27 us | 0.599 us | 0.560 us | 3.39 | 0.02 | 5 |
| PowerArgs | 306.12 us | 1.495 us | 1.398 us | 6.09 | 0.03 | 6 |
| Cocona | 1,856.07 us | 48.727 us | 141.367 us | 37.88 | 2.60 | 7 |