From 923b23cbd380156d688f0010c434966db2cf1704 Mon Sep 17 00:00:00 2001 From: Code Therapist <38962170+CodeTherapist@users.noreply.github.com> Date: Sat, 12 Jan 2019 18:30:33 +0100 Subject: [PATCH] BenchmarkDotNet as global tool (#1006), fixes #213 * BenchmarkDotNet as global tool This resolves #213. * Set TargetFramework to "netcoreapp2.1" * Add import for common build properties. * Docs: BenchmarkDotNet as global dotnet tool --- BenchmarkDotNet.sln | 15 +++- docs/articles/guides/global-dotnet-tool.md | 64 +++++++++++++++ docs/articles/guides/how-to-run.md | 10 +++ docs/articles/guides/nuget.md | 1 + docs/articles/guides/toc.yml | 4 +- .../BenchmarkDotNet.Tool.csproj | 18 +++++ src/BenchmarkDotNet.Tool/Program.cs | 81 +++++++++++++++++++ .../Properties/launchSettings.json | 7 ++ 8 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 docs/articles/guides/global-dotnet-tool.md create mode 100644 src/BenchmarkDotNet.Tool/BenchmarkDotNet.Tool.csproj create mode 100644 src/BenchmarkDotNet.Tool/Program.cs create mode 100644 src/BenchmarkDotNet.Tool/Properties/launchSettings.json diff --git a/BenchmarkDotNet.sln b/BenchmarkDotNet.sln index d723ac5c90..09f65fe8cc 100644 --- a/BenchmarkDotNet.sln +++ b/BenchmarkDotNet.sln @@ -15,11 +15,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.Diagnostics EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.IntegrationTests.CustomPaths", "tests\BenchmarkDotNet.IntegrationTests.CustomPaths\BenchmarkDotNet.IntegrationTests.CustomPaths.csproj", "{0031728E-A5D4-47C1-9C1A-6C859A765C9D}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "BenchmarkDotNet.Samples.FSharp", "samples\BenchmarkDotNet.Samples.FSharp\BenchmarkDotNet.Samples.FSharp.fsproj", "{A329F00E-4B9D-4BC6-B688-92698D773CBF}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "BenchmarkDotNet.Samples.FSharp", "samples\BenchmarkDotNet.Samples.FSharp\BenchmarkDotNet.Samples.FSharp.fsproj", "{A329F00E-4B9D-4BC6-B688-92698D773CBF}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "BenchmarkDotNet.IntegrationTests.FSharp", "tests\BenchmarkDotNet.IntegrationTests.FSharp\BenchmarkDotNet.IntegrationTests.FSharp.fsproj", "{367FAFE1-A1C8-4AA1-9334-F4762E128DBB}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "BenchmarkDotNet.IntegrationTests.FSharp", "tests\BenchmarkDotNet.IntegrationTests.FSharp\BenchmarkDotNet.IntegrationTests.FSharp.fsproj", "{367FAFE1-A1C8-4AA1-9334-F4762E128DBB}" EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BenchmarkDotNet.IntegrationTests.VisualBasic", "tests\BenchmarkDotNet.IntegrationTests.VisualBasic\BenchmarkDotNet.IntegrationTests.VisualBasic.vbproj", "{D8803ECA-4ABF-45B8-BD1D-7C637416C448}" +Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "BenchmarkDotNet.IntegrationTests.VisualBasic", "tests\BenchmarkDotNet.IntegrationTests.VisualBasic\BenchmarkDotNet.IntegrationTests.VisualBasic.vbproj", "{D8803ECA-4ABF-45B8-BD1D-7C637416C448}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.IntegrationTests.DisabledOptimizations", "tests\BenchmarkDotNet.IntegrationTests.DisabledOptimizations\BenchmarkDotNet.IntegrationTests.DisabledOptimizations.csproj", "{AC2188E5-A140-43E2-8A76-4BDABFE30ABA}" EndProject @@ -37,7 +37,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.Disassemble EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.Disassembler.x86", "src\BenchmarkDotNet.Disassembler.x86\BenchmarkDotNet.Disassembler.x86.csproj", "{D189AAB3-46B4-4437-8E9C-72F021AB2B6E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkDotNet.IntegrationTests.ManualRunning", "tests\BenchmarkDotNet.IntegrationTests.ManualRunning\BenchmarkDotNet.IntegrationTests.ManualRunning.csproj", "{9816D316-95C4-42E6-9E7B-A256C7E5D4BF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkDotNet.IntegrationTests.ManualRunning", "tests\BenchmarkDotNet.IntegrationTests.ManualRunning\BenchmarkDotNet.IntegrationTests.ManualRunning.csproj", "{9816D316-95C4-42E6-9E7B-A256C7E5D4BF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkDotNet.Tool", "src\BenchmarkDotNet.Tool\BenchmarkDotNet.Tool.csproj", "{1336CAFF-5321-495E-BAFA-AB4DC6BF791C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -105,6 +107,10 @@ Global {9816D316-95C4-42E6-9E7B-A256C7E5D4BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {9816D316-95C4-42E6-9E7B-A256C7E5D4BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {9816D316-95C4-42E6-9E7B-A256C7E5D4BF}.Release|Any CPU.Build.0 = Release|Any CPU + {1336CAFF-5321-495E-BAFA-AB4DC6BF791C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1336CAFF-5321-495E-BAFA-AB4DC6BF791C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1336CAFF-5321-495E-BAFA-AB4DC6BF791C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1336CAFF-5321-495E-BAFA-AB4DC6BF791C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -125,6 +131,7 @@ Global {E5A0833C-B633-4D62-B645-A927CEBFEEBB} = {D6597E3A-6892-4A68-8E14-042FC941FDA2} {D189AAB3-46B4-4437-8E9C-72F021AB2B6E} = {D6597E3A-6892-4A68-8E14-042FC941FDA2} {9816D316-95C4-42E6-9E7B-A256C7E5D4BF} = {14195214-591A-45B7-851A-19D3BA2413F9} + {1336CAFF-5321-495E-BAFA-AB4DC6BF791C} = {D6597E3A-6892-4A68-8E14-042FC941FDA2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4D9AF12B-1F7F-45A7-9E8C-E4E46ADCBD1F} diff --git a/docs/articles/guides/global-dotnet-tool.md b/docs/articles/guides/global-dotnet-tool.md new file mode 100644 index 0000000000..033a58a38c --- /dev/null +++ b/docs/articles/guides/global-dotnet-tool.md @@ -0,0 +1,64 @@ +--- +uid: docs.dotnet-benchmarkdotnet +name: The global BenchmarkDotNet tool +--- + +# BenchmarkDotNet as global dotnet tool + +BenchmarkDotNet is also available as a global dotnet tool and provides a convenient way to execute your benchmark(s) from the command line interface. + +## How to install the tool + +Download and install the [.NET Core 2.1 SDK](https://www.microsoft.com/net/download) or newer. Once installed, run the following command: + +```log +dotnet tool install BenchmarkDotNet.Tool -g +``` + +If you already have a previous version of installed, you can upgrade to the latest version using the following command: + +```log +dotnet tool update BenchmarkDotNet.Tool -g +``` + +## Usage + +The basic usage syntax is: + +```log +dotnet benchmarkdotnet [arguments] [options] +``` + +### Arguments + +* The **first** argument in `[arguments]` **must** be the path to an assembly file with your benchmarks. +* Further arguments are passed to the the `BenchmarkSwitcher`. + +### Options + +| Option | Description | +| ------ | ----------- | +|--version|Show version information| +|-?, -h or --help|Show help information| + +```log +dotnet benchmarkdotnet -? +``` + +**Note**: This shows also all valid arguments for `BenchmarkSwitcher`. + +## Examples + +The following example scans the `MyAssemblyWithBenchmarks.dll` for benchmarks and lets you select which benchmark(s) to execute: + +```log +dotnet benchmarkdotnet MyAssemblyWithBenchmarks.dll +``` + +To execute all benchmarks use `--filter *`: + +```log +dotnet benchmarkdotnet MyAssemblyWithBenchmarks.dll --filter * +``` + +**Note**: For further arguments for the `BenchmarkSwticher` see also [Console Arguments](console-args.md). diff --git a/docs/articles/guides/how-to-run.md b/docs/articles/guides/how-to-run.md index 78bb3c0690..3a22a1a983 100644 --- a/docs/articles/guides/how-to-run.md +++ b/docs/articles/guides/how-to-run.md @@ -9,6 +9,16 @@ var summary = BenchmarkRunner.Run(); var summary = BenchmarkRunner.Run(typeof(MyBenchmarkClass)); ``` +## Global dotnet tool + +```log +dotnet tool install BenchmarkDotNet.Tool -g +``` + +```log +dotnet benchmarkdotnet MyAssemblyWithBenchmarks.dll --filter * +``` + ## Url You can also run a benchmark directly from the internet: diff --git a/docs/articles/guides/nuget.md b/docs/articles/guides/nuget.md index a075395231..87d042e005 100644 --- a/docs/articles/guides/nuget.md +++ b/docs/articles/guides/nuget.md @@ -11,6 +11,7 @@ We have the following set of NuGet packages (you can install it directly from `n * `BenchmarkDotNet`: Basic BenchmarkDotNet infrastructure and logic. This is all you need to run benchmarks. * `BenchmarkDotNet.Diagnostics.Windows`: an additional optional package that provides a set of Windows diagnosers. +* `BenchmarkDotNet.Tool`: A dotnet tool to execute benchmarks built with BenchmarkDotNet. ## Versioning system and feeds We have 3 kinds of versions: *stable*, *nightly*, and *develop*. diff --git a/docs/articles/guides/toc.yml b/docs/articles/guides/toc.yml index f06dce7db7..2606194852 100644 --- a/docs/articles/guides/toc.yml +++ b/docs/articles/guides/toc.yml @@ -15,4 +15,6 @@ - name: Console Arguments href: console-args.md - name: Troubleshooting - href: troubleshooting.md \ No newline at end of file + href: troubleshooting.md +- name: BenchmarkDotNet as global dotnet tool + href: global-dotnet-tool.md \ No newline at end of file diff --git a/src/BenchmarkDotNet.Tool/BenchmarkDotNet.Tool.csproj b/src/BenchmarkDotNet.Tool/BenchmarkDotNet.Tool.csproj new file mode 100644 index 0000000000..6a63440a10 --- /dev/null +++ b/src/BenchmarkDotNet.Tool/BenchmarkDotNet.Tool.csproj @@ -0,0 +1,18 @@ + + + + Exe + netcoreapp2.1 + true + true + dotnet-BenchmarkDotNet + A dotnet tool to execute BenchmarkDotNet benchmarks. + benchmark;benchmarking;performance;tool + BenchmarkDotNetTool + false + + + + + + diff --git a/src/BenchmarkDotNet.Tool/Program.cs b/src/BenchmarkDotNet.Tool/Program.cs new file mode 100644 index 0000000000..f6c566afd8 --- /dev/null +++ b/src/BenchmarkDotNet.Tool/Program.cs @@ -0,0 +1,81 @@ +using BenchmarkDotNet.ConsoleArguments; +using BenchmarkDotNet.Running; +using CommandLine; +using McMaster.Extensions.CommandLineUtils; +using System; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Reflection; +using System.Text; + +namespace BenchmarkDotNet.Tool +{ + [Command( + Name = "BenchmarkDotNet", + Description = "A dotnet tool to execute benchmarks built with BenchmarkDotNet.")] + [HelpOption()] + [VersionOptionFromMember(MemberName = nameof(GetVersion))] + public sealed class Program + { + public static int Main(string[] args) + { + using (CommandLineApplication app = new CommandLineApplication()) + { + app.Conventions.UseDefaultConventions(); + app.ThrowOnUnexpectedArgument = false; + app.ExtendedHelpText = GenerateExtendedHelpText(); + return app.Execute(args); + } + } + + private IConsole Console => PhysicalConsole.Singleton; + + [Argument(0, Description = "The assembly with the benchmarks (required).")] + [Required] + [FileExists] + public string AssemblyFile { get; set; } + + public string[] RemainingArguments { get; set; } + + public int OnExecute() + { + Assembly assembly; + try + { + assembly = Assembly.LoadFrom(AssemblyFile); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Couldn't load the assembly {AssemblyFile}."); + Console.Error.WriteLine(ex.ToString()); + return 1; + } + + BenchmarkSwitcher benchmarkSwitcher = BenchmarkSwitcher.FromAssembly(assembly); + benchmarkSwitcher.Run(RemainingArguments); + return 0; + } + + private static string GetVersion() + { + return typeof(Program).Assembly.GetCustomAttribute().InformationalVersion; + } + + private static string GenerateExtendedHelpText() + { + StringBuilder sb = new StringBuilder() + .AppendLine() + .AppendLine("The first argument in [arguments] is the benchmark assembly and every following argument is passed to the BenchmarkSwitcher.") + .AppendLine("BenchmarkSwitcher arguments:") + .AppendLine(); + using (StringWriter sw = new StringWriter(sb)) + { + using (Parser p = new Parser((ps) => { ps.HelpWriter = sw; })) + { + p.ParseArguments(new string[] { "--help" }); + } + } + return sb.ToString(); + } + } +} diff --git a/src/BenchmarkDotNet.Tool/Properties/launchSettings.json b/src/BenchmarkDotNet.Tool/Properties/launchSettings.json new file mode 100644 index 0000000000..5940f9e1d3 --- /dev/null +++ b/src/BenchmarkDotNet.Tool/Properties/launchSettings.json @@ -0,0 +1,7 @@ +{ + "profiles": { + "BenchmarkDotNet.Tool": { + "commandName": "Project" + } + } +} \ No newline at end of file