diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetApp/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetApp/Program.cs new file mode 100644 index 000000000..9bfc3c72c --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetApp/Program.cs @@ -0,0 +1,11 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main() + { + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetApp/project.json b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetApp/project.json new file mode 100644 index 000000000..89cf3a3bf --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetApp/project.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP0/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP0/Program.cs new file mode 100644 index 000000000..ca05ade7a --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP0/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P1.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP0/project.json b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP0/project.json new file mode 100644 index 000000000..c65037aca --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP0/project.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "SingleTargetP1" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP1/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP1/Program.cs new file mode 100644 index 000000000..ea50de9e8 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP1/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleLibrary.P1 +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P2.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP1/project.json b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP1/project.json new file mode 100644 index 000000000..0f4fee5ad --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP1/project.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "SingleTargetP2" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP2/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP2/Program.cs new file mode 100644 index 000000000..0ae001811 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP2/Program.cs @@ -0,0 +1,11 @@ +using System; + +namespace ConsoleLibrary.P2 +{ + public class Program + { + public static void Main() + { + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP2/project.json b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP2/project.json new file mode 100644 index 000000000..71ae27297 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/SingleTargetGraph/SingleTargetP2/project.json @@ -0,0 +1,12 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetApp/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetApp/Program.cs new file mode 100644 index 000000000..9bfc3c72c --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetApp/Program.cs @@ -0,0 +1,11 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main() + { + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetApp/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetApp/project.json new file mode 100644 index 000000000..5ea926028 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetApp/project.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP0/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP0/Program.cs new file mode 100644 index 000000000..ca05ade7a --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP0/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P1.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP0/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP0/project.json new file mode 100644 index 000000000..2b03279e5 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP0/project.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "TwoTargetP1" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP1/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP1/Program.cs new file mode 100644 index 000000000..ea50de9e8 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP1/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleLibrary.P1 +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P2.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP1/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP1/project.json new file mode 100644 index 000000000..3e279184d --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP1/project.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "TwoTargetP2" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP2/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP2/Program.cs new file mode 100644 index 000000000..0ae001811 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP2/Program.cs @@ -0,0 +1,11 @@ +using System; + +namespace ConsoleLibrary.P2 +{ + public class Program + { + public static void Main() + { + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP2/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP2/project.json new file mode 100644 index 000000000..a1f979cc9 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraph/TwoTargetP2/project.json @@ -0,0 +1,13 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP0/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP0/Program.cs new file mode 100644 index 000000000..ca05ade7a --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP0/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P1.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP0/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP0/project.json new file mode 100644 index 000000000..22689acf8 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP0/project.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "TwoTargetLargeP1" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP1/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP1/Program.cs new file mode 100644 index 000000000..7b1284ad8 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP1/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace ConsoleLibrary.P1 +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P2.Program.Main(); + ConsoleLibrary.P4.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP1/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP1/project.json new file mode 100644 index 000000000..5b080a6f1 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP1/project.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "TwoTargetLargeP2" : { + "target": "project" + }, + "TwoTargetLargeP4" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP2/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP2/Program.cs new file mode 100644 index 000000000..121dbbfb7 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP2/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace ConsoleLibrary.P2 +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P3.Program.Main(); + ConsoleLibrary.P4.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP2/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP2/project.json new file mode 100644 index 000000000..8b7d44b36 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP2/project.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "TwoTargetLargeP3" : { + "target": "project" + }, + "TwoTargetLargeP4" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP3/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP3/Program.cs new file mode 100644 index 000000000..2e779be39 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP3/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleLibrary.P3 +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P4.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP3/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP3/project.json new file mode 100644 index 000000000..e75856ac1 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP3/project.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "TwoTargetLargeP4" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP4/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP4/Program.cs new file mode 100644 index 000000000..71a2f4d72 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP4/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace ConsoleLibrary.P4 +{ + public class Program + { + public static void Main() + { + ConsoleLibrary.P5.Program.Main(); + ConsoleLibrary.P6.Program.Main(); + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP4/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP4/project.json new file mode 100644 index 000000000..ea7cad01d --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP4/project.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "TwoTargetLargeP5" : { + "target": "project" + }, + "TwoTargetLargeP6" : { + "target": "project" + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP5/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP5/Program.cs new file mode 100644 index 000000000..9fc92636d --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP5/Program.cs @@ -0,0 +1,11 @@ +using System; + +namespace ConsoleLibrary.P5 +{ + public class Program + { + public static void Main() + { + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP5/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP5/project.json new file mode 100644 index 000000000..a1f979cc9 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP5/project.json @@ -0,0 +1,13 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP6/Program.cs b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP6/Program.cs new file mode 100644 index 000000000..ae467ffd4 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP6/Program.cs @@ -0,0 +1,11 @@ +using System; + +namespace ConsoleLibrary.P6 +{ + public class Program + { + public static void Main() + { + } + } +} diff --git a/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP6/project.json b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP6/project.json new file mode 100644 index 000000000..a1f979cc9 --- /dev/null +++ b/TestAssets/TestProjects/PerformanceTestProjects/TwoTargetGraphLarge/TwoTargetLargeP6/project.json @@ -0,0 +1,13 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-*" + }, + }, + "frameworks": { + "netcoreapp1.0": { }, + "netstandard1.5": { } + } +} diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 646470c82..9647fe860 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -37,7 +37,8 @@ namespace Microsoft.DotNet.Cli.Build "Microsoft.DotNet.Cli.Utils.Tests", "Microsoft.DotNet.Compiler.Common.Tests", "Microsoft.DotNet.ProjectModel.Tests", - "Microsoft.Extensions.DependencyModel.Tests" + "Microsoft.Extensions.DependencyModel.Tests", + "Performance" }; public static readonly string[] WindowsTestProjects = new[] diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs index 10e138841..6ffd4efe3 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs @@ -29,6 +29,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private readonly bool _noIncremental; private readonly bool _noDependencies; private readonly string _runtime; + private readonly bool _verbose; private string OutputOption { @@ -199,6 +200,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities } } + private string Verbose + { + get + { + return _verbose ? "--verbose" : ""; + } + } + public BuildCommand( string projectPath, string output="", @@ -218,6 +227,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities bool buildProfile=true, bool noIncremental=false, bool noDependencies=false, + bool verbose=true, bool skipLoadProject=false) : base("dotnet") { @@ -245,17 +255,18 @@ namespace Microsoft.DotNet.Tools.Test.Utilities _buildProfile = buildProfile; _noIncremental = noIncremental; _noDependencies = noDependencies; + _verbose = verbose; } public override CommandResult Execute(string args = "") { - args = $"--verbose build {BuildArgs()} {args}"; + args = $"{Verbose} build {BuildArgs()} {args}"; return base.Execute(args); } public override CommandResult ExecuteWithCapturedOutput(string args = "") { - args = $"--verbose build {BuildArgs()} {args}"; + args = $"{Verbose} build {BuildArgs()} {args}"; return base.ExecuteWithCapturedOutput(args); } diff --git a/test/Performance/BuildPerformanceTest.cs b/test/Performance/BuildPerformanceTest.cs new file mode 100644 index 000000000..6b7e28a6b --- /dev/null +++ b/test/Performance/BuildPerformanceTest.cs @@ -0,0 +1,294 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Linq; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Xunit.Performance; +using Microsoft.DotNet.TestFramework; +using System.IO; +using System.Runtime.CompilerServices; +using System; +using System.Collections.Generic; + +namespace Microsoft.DotNet.Tools.Builder.Tests +{ + public class BuildPerformanceTest : TestBase + { + private static string SingleTargetApp = "SingleTargetApp"; + private static string TwoTargetApp = "TwoTargetApp"; + + private static string[] SingleTargetGraph = new[] + { + "SingleTargetGraph/SingleTargetP0", + "SingleTargetGraph/SingleTargetP1", + "SingleTargetGraph/SingleTargetP2" + }; + + private static string[] TwoTargetGraph = new[] + { + "TwoTargetGraph/TwoTargetP0", + "TwoTargetGraph/TwoTargetP1", + "TwoTargetGraph/TwoTargetP2" + }; + + private static string[] TwoTargetGraphLarge = new[] + { + "TwoTargetGraphLarge/TwoTargetLargeP0", + "TwoTargetGraphLarge/TwoTargetLargeP1", + "TwoTargetGraphLarge/TwoTargetLargeP2", + "TwoTargetGraphLarge/TwoTargetLargeP3", + "TwoTargetGraphLarge/TwoTargetLargeP4", + "TwoTargetGraphLarge/TwoTargetLargeP5", + "TwoTargetGraphLarge/TwoTargetLargeP6" + }; + + [Benchmark] + public void BuildSingleProject_SingleTargetApp() => BuildSingleProject(CreateTestInstance(SingleTargetApp)); + [Benchmark] + public void BuildSingleProject_TwoTargetApp() => BuildSingleProject(CreateTestInstance(TwoTargetApp)); + + public void BuildSingleProject(TestInstance instance) + { + foreach (var iteration in Benchmark.Iterations) + { + var buildCommand = new BuildCommand(instance.TestRoot, buildProfile: false); + using (iteration.StartMeasurement()) + { + buildCommand.Execute().Should().Pass(); + } + TouchSource(instance.TestRoot); + } + } + + [Benchmark] + public void IncrementalSkipSingleProject_SingleTargetApp() => IncrementalSkipSingleProject(CreateTestInstance(SingleTargetApp)); + [Benchmark] + public void IncrementalSkipSingleProject_TwoTargetApp() => IncrementalSkipSingleProject(CreateTestInstance(TwoTargetApp)); + + public void IncrementalSkipSingleProject(TestInstance instance) + { + new BuildCommand(instance.TestRoot, buildProfile: false) + .Execute().Should().Pass(); + + foreach (var iteration in Benchmark.Iterations) + { + var buildCommand = new BuildCommand(instance.TestRoot, buildProfile: false); + using (iteration.StartMeasurement()) + { + buildCommand.Execute().Should().Pass(); + } + } + } + + [Benchmark] + public void BuildAllInGraph_SingleTargetGraph() => BuildAllInGraph(CreateTestInstances(SingleTargetGraph)); + [Benchmark] + public void BuildAllInGraph_TwoTargetGraph() => BuildAllInGraph(CreateTestInstances(TwoTargetGraph)); + [Benchmark] + public void BuildAllInGraph_TwoTargetGraphLarge() => BuildAllInGraph(CreateTestInstances(TwoTargetGraphLarge)); + + public void BuildAllInGraph(TestInstance[] instances) + { + var instance = instances[0]; + + foreach (var iteration in Benchmark.Iterations) + { + var buildCommand = new BuildCommand(instance.TestRoot, buildProfile: false); + using (iteration.StartMeasurement()) + { + buildCommand.Execute().Should().Pass(); + } + foreach (var i in instances) + { + TouchSource(i.TestRoot); + } + } + } + + [Benchmark] + public void IncrementalSkipAllInGraph_SingleTargetGraph() => + IncrementalSkipAllInGraph(CreateTestInstances(SingleTargetGraph)); + + [Benchmark] + public void IncrementalSkipAllInGraph_TwoTargetGraph() => + IncrementalSkipAllInGraph(CreateTestInstances(TwoTargetGraph)); + + [Benchmark] + public void IncrementalSkipAllInGraphh_TwoTargetGraphLarge() => + IncrementalSkipAllInGraph(CreateTestInstances(TwoTargetGraphLarge)); + + public void IncrementalSkipAllInGraph(TestInstance[] instances) + { + var instance = instances[0]; + new BuildCommand(instance.TestRoot, buildProfile: false) + .Execute().Should().Pass(); + + foreach (var iteration in Benchmark.Iterations) + { + var buildCommand = new BuildCommand(instance.TestRoot, buildProfile: false); + using (iteration.StartMeasurement()) + { + buildCommand.Execute().Should().Pass(); + } + } + } + + [Benchmark] + public void IncrementalRebuildWithRootChangedInGraph_SingleTargetGraph() => + IncrementalRebuildWithRootChangedInGraph(CreateTestInstances(SingleTargetGraph)); + + [Benchmark] + public void IncrementalRebuildWithRootChangedInGraph_TwoTargetGraph() => + IncrementalRebuildWithRootChangedInGraph(CreateTestInstances(TwoTargetGraph)); + + [Benchmark] + public void IncrementalRebuildWithRootChangedInGraph_TwoTargetGraphLarge() => + IncrementalRebuildWithRootChangedInGraph(CreateTestInstances(TwoTargetGraphLarge)); + + public void IncrementalRebuildWithRootChangedInGraph(TestInstance[] instances) + { + var instance = instances[0]; + new BuildCommand(instance.TestRoot, buildProfile: false) + .Execute().Should().Pass(); + + foreach (var iteration in Benchmark.Iterations) + { + var buildCommand = new BuildCommand(instance.TestRoot, buildProfile: false); + using (iteration.StartMeasurement()) + { + buildCommand.Execute().Should().Pass(); + } + TouchSource(instance.TestRoot); + } + } + + [Benchmark] + public void IncrementalRebuildWithLastChangedInGraph_SingleTargetGraph() => + IncrementalRebuildWithLastChangedInGraph(CreateTestInstances(SingleTargetGraph)); + + [Benchmark] + public void IncrementalRebuildWithLastChangedInGraph_TwoTargetGraph() => + IncrementalRebuildWithLastChangedInGraph(CreateTestInstances(TwoTargetGraph)); + + [Benchmark] + public void IncrementalRebuildWithLastChangedInGraph_TwoTargetGraphLarge() => + IncrementalRebuildWithLastChangedInGraph(CreateTestInstances(TwoTargetGraphLarge)); + + public void IncrementalRebuildWithLastChangedInGraph(TestInstance[] instances) + { + var instance = instances[0]; + new BuildCommand(instance.TestRoot, buildProfile: false) + .Execute().Should().Pass(); + + foreach (var iteration in Benchmark.Iterations) + { + var buildCommand = new BuildCommand(instance.TestRoot, buildProfile: false); + using (iteration.StartMeasurement()) + { + buildCommand.Execute().Should().Pass(); + } + TouchSource(instances.Last().TestRoot); + } + } + + + [Benchmark] + public void IncrementalSkipAllNoDependenciesInGraph_SingleTargetGraph() => + IncrementalSkipAllNoDependenciesInGraph(CreateTestInstances(SingleTargetGraph)); + + [Benchmark] + public void IncrementalSkipAllNoDependenciesInGraph_TwoTargetGraph() => + IncrementalSkipAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraph)); + + [Benchmark] + public void IncrementalSkipAllNoDependenciesInGraph_TwoTargetGraphLarge() => + IncrementalSkipAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraphLarge)); + + public void IncrementalSkipAllNoDependenciesInGraph(TestInstance[] instances) + { + var instance = instances[0]; + new BuildCommand(instance.TestRoot, buildProfile: false) + .Execute().Should().Pass(); + + foreach (var iteration in Benchmark.Iterations) + { + var commands = new List(); + foreach (var i in instances.Reverse()) + { + commands.Add(new BuildCommand(i.TestRoot, + framework: DefaultFramework, + noDependencies: true, + buildProfile: false)); + } + using (iteration.StartMeasurement()) + { + foreach (var buildCommand in commands) + { + buildCommand.Execute().Should().Pass(); + } + } + } + } + [Benchmark] + public void BuildAllNoDependenciesInGraph_SingleTargetGraph() => + BuildAllNoDependenciesInGraph(CreateTestInstances(SingleTargetGraph)); + + [Benchmark] + public void BuildAllNoDependenciesInGraph_TwoTargetGraph() => + BuildAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraph)); + + [Benchmark] + public void BuildAllNoDependenciesInGraph_TwoTargetGraphLarge() => + BuildAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraphLarge)); + + public void BuildAllNoDependenciesInGraph(TestInstance[] instances) + { + foreach (var iteration in Benchmark.Iterations) + { + var commands = new List(); + foreach (var i in instances.Reverse()) + { + commands.Add(new BuildCommand(i.TestRoot, + framework: DefaultFramework, + noDependencies: true, + buildProfile: false)); + } + using (iteration.StartMeasurement()) + { + foreach (var buildCommand in commands) + { + buildCommand.Execute().Should().Pass(); + } + } + foreach (var instance in instances) + { + TouchSource(instance.TestRoot); + } + } + } + + protected void TouchSource(string project) + { + var sourceFile = Directory.GetFiles(project, "*.cs").FirstOrDefault(); + if (sourceFile == null) + { + throw new InvalidOperationException($"'.cs' files not found in {project}"); + } + File.SetLastWriteTime(sourceFile, DateTime.Now); + } + + protected TestInstance[] CreateTestInstances(string[] testProjectNames, [CallerMemberName] string callingMethod = "") + { + return testProjectNames.Select(testProjectName => + { + return CreateTestInstance(testProjectName, callingMethod); + }).ToArray(); + } + + protected TestInstance CreateTestInstance(string testProjectName, [CallerMemberName] string callingMethod = "") + { + return TestAssetsManager.CreateTestInstance(Path.Combine("PerformanceTestProjects", testProjectName), callingMethod) + .WithLockFiles(); + } + } +}