未验证 提交 aefd1312 编写于 作者: G Gen Lu 提交者: GitHub

Merge pull request #44027 from genlu/CoreBenchmarks

Add IDE benchmark project targeting .NET Core
......@@ -148,8 +148,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Scri
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Package", "src\NuGet\Microsoft.CodeAnalysis.Package.csproj", "{2483917E-7024-4D10-99C6-2BEF338FF53B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompilerBenchmarks", "src\Tools\CompilerBenchmarks\CompilerBenchmarks.csproj", "{B446E771-AB52-41C9-ACFC-FDF8EACAF291}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildBoss", "src\Tools\BuildBoss\BuildBoss.csproj", "{8A02AFAF-F622-4E3E-9E1A-8CFDACC7C7E1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Compilers.Toolset.Package", "src\NuGet\Microsoft.Net.Compilers.Toolset\Microsoft.Net.Compilers.Toolset.Package.csproj", "{6D407402-CC4A-4125-9B00-C70562A636A5}"
......@@ -423,10 +421,6 @@ Global
{2483917E-7024-4D10-99C6-2BEF338FF53B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2483917E-7024-4D10-99C6-2BEF338FF53B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2483917E-7024-4D10-99C6-2BEF338FF53B}.Release|Any CPU.Build.0 = Release|Any CPU
{B446E771-AB52-41C9-ACFC-FDF8EACAF291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B446E771-AB52-41C9-ACFC-FDF8EACAF291}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B446E771-AB52-41C9-ACFC-FDF8EACAF291}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B446E771-AB52-41C9-ACFC-FDF8EACAF291}.Release|Any CPU.Build.0 = Release|Any CPU
{8A02AFAF-F622-4E3E-9E1A-8CFDACC7C7E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A02AFAF-F622-4E3E-9E1A-8CFDACC7C7E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A02AFAF-F622-4E3E-9E1A-8CFDACC7C7E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
......@@ -506,7 +500,6 @@ Global
{E0756C89-603F-4B48-8E64-1D53E62654C8} = {274B96B7-F815-47E3-9CA4-4024A57A478F}
{7F8057D9-F70F-4EA7-BD64-AB2D0DD8057B} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B}
{2483917E-7024-4D10-99C6-2BEF338FF53B} = {274B96B7-F815-47E3-9CA4-4024A57A478F}
{B446E771-AB52-41C9-ACFC-FDF8EACAF291} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC}
{8A02AFAF-F622-4E3E-9E1A-8CFDACC7C7E1} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC}
{6D407402-CC4A-4125-9B00-C70562A636A5} = {274B96B7-F815-47E3-9CA4-4024A57A478F}
{706CFC25-B6E0-4DAA-BCC4-F6FAAFEEDF87} = {3FF38FD4-DF16-44B0-924F-0D5AE155495B}
......
......@@ -352,8 +352,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteractiveHost64", "src\In
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.IntegrationTest.IntegrationService", "src\VisualStudio\IntegrationTest\IntegrationService\Microsoft.VisualStudio.IntegrationTest.IntegrationService.csproj", "{764D2C19-0187-4837-A2A3-96DDC6EF4CE2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompilerBenchmarks", "src\Tools\CompilerBenchmarks\CompilerBenchmarks.csproj", "{9860FCF7-3111-4C12-A16F-ACEBA42D930F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Compilers.Package", "src\NuGet\Microsoft.Net.Compilers\Microsoft.Net.Compilers.Package.csproj", "{9102ECF3-5CD1-4107-B8B7-F3795A52D790}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NETCore.Compilers.Package", "src\NuGet\Microsoft.NETCore.Compilers\Microsoft.NETCore.Compilers.Package.csproj", "{50CF5D8F-F82F-4210-A06E-37CC9BFFDD49}"
......@@ -466,6 +464,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Edit
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.CodeStyle.LegacyTestFramework.UnitTestUtilities", "src\CodeStyle\Core\Tests\Microsoft.CodeAnalysis.CodeStyle.LegacyTestFramework.UnitTestUtilities.csproj", "{2D5E2DE4-5DA8-41C1-A14F-49855DCCE9C5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdeCoreBenchmarks", "src\Tools\IdeCoreBenchmarks\IdeCoreBenchmarks.csproj", "{CEA80C83-5848-4FF6-B4E8-CEEE9482E4AA}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Analyzers\VisualBasic\CodeFixes\VisualBasicCodeFixes.projitems*{0141285d-8f6c-42c7-baf3-3c0ccd61c716}*SharedItemsImports = 5
......@@ -1097,10 +1097,6 @@ Global
{764D2C19-0187-4837-A2A3-96DDC6EF4CE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{764D2C19-0187-4837-A2A3-96DDC6EF4CE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{764D2C19-0187-4837-A2A3-96DDC6EF4CE2}.Release|Any CPU.Build.0 = Release|Any CPU
{9860FCF7-3111-4C12-A16F-ACEBA42D930F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9860FCF7-3111-4C12-A16F-ACEBA42D930F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9860FCF7-3111-4C12-A16F-ACEBA42D930F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9860FCF7-3111-4C12-A16F-ACEBA42D930F}.Release|Any CPU.Build.0 = Release|Any CPU
{9102ECF3-5CD1-4107-B8B7-F3795A52D790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9102ECF3-5CD1-4107-B8B7-F3795A52D790}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9102ECF3-5CD1-4107-B8B7-F3795A52D790}.Release|Any CPU.ActiveCfg = Release|Any CPU
......@@ -1225,6 +1221,10 @@ Global
{2D5E2DE4-5DA8-41C1-A14F-49855DCCE9C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D5E2DE4-5DA8-41C1-A14F-49855DCCE9C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D5E2DE4-5DA8-41C1-A14F-49855DCCE9C5}.Release|Any CPU.Build.0 = Release|Any CPU
{CEA80C83-5848-4FF6-B4E8-CEEE9482E4AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CEA80C83-5848-4FF6-B4E8-CEEE9482E4AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CEA80C83-5848-4FF6-B4E8-CEEE9482E4AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CEA80C83-5848-4FF6-B4E8-CEEE9482E4AA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -1388,7 +1388,6 @@ Global
{037F06F0-3BE8-42D0-801E-2F74FC380AB8} = {55A62CFA-1155-46F1-ADF3-BEEE51B58AB5}
{2F11618A-9251-4609-B3D5-CE4D2B3D3E49} = {5CA5F70E-0FDB-467B-B22C-3CD5994F0087}
{764D2C19-0187-4837-A2A3-96DDC6EF4CE2} = {CC126D03-7EAC-493F-B187-DCDEE1EF6A70}
{9860FCF7-3111-4C12-A16F-ACEBA42D930F} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC}
{9102ECF3-5CD1-4107-B8B7-F3795A52D790} = {C52D8057-43AF-40E6-A01B-6CDBB7301985}
{50CF5D8F-F82F-4210-A06E-37CC9BFFDD49} = {C52D8057-43AF-40E6-A01B-6CDBB7301985}
{CFA94A39-4805-456D-A369-FC35CCC170E9} = {C52D8057-43AF-40E6-A01B-6CDBB7301985}
......@@ -1442,6 +1441,7 @@ Global
{9C1BE25C-5926-4E56-84AE-D2242CB0627E} = {DF17AF27-AA02-482B-8946-5CA8A50D5A2B}
{B64766CD-1A1F-4C1B-B11F-C30F82B8E41E} = {EE97CB90-33BB-4F3A-9B3D-69375DEC6AC6}
{2D5E2DE4-5DA8-41C1-A14F-49855DCCE9C5} = {DC014586-8D07-4DE6-B28E-C0540C59C085}
{CEA80C83-5848-4FF6-B4E8-CEEE9482E4AA} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29}
......
......@@ -40,7 +40,7 @@
-->
<PropertyGroup>
<BasicUndoVersion>0.9.3</BasicUndoVersion>
<BenchmarkDotNetVersion>0.11.4</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.12.1</BenchmarkDotNetVersion>
<DiffPlexVersion>1.4.4</DiffPlexVersion>
<DropAppVersion>17.144.28413-buildid7983345</DropAppVersion>
<EnvDTEVersion>8.0.2</EnvDTEVersion>
......@@ -188,6 +188,7 @@
<RoslynMicrosoftVisualStudioExtensionManagerVersion>0.0.4</RoslynMicrosoftVisualStudioExtensionManagerVersion>
<SourceBrowserVersion>1.0.21</SourceBrowserVersion>
<SystemBuffersVersion>4.5.1</SystemBuffersVersion>
<SystemCodeDomVersion>4.7.0</SystemCodeDomVersion>
<SystemCommandLineExperimentalVersion>0.3.0-alpha.19577.1</SystemCommandLineExperimentalVersion>
<SystemComponentModelCompositionVersion>4.5.0</SystemComponentModelCompositionVersion>
<SystemDrawingCommonVersion>4.5.0</SystemDrawingCommonVersion>
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.MSBuild;
namespace AnalyzerRunner
{
public static class AnalyzerRunnerHelper
{
static AnalyzerRunnerHelper()
{
// QueryVisualStudioInstances returns Visual Studio installations on .NET Framework, and .NET Core SDK
// installations on .NET Core. We use the one with the most recent version.
var msBuildInstance = MSBuildLocator.QueryVisualStudioInstances().OrderByDescending(x => x.Version).First();
#if NETCOREAPP
// Since we do not inherit msbuild.deps.json when referencing the SDK copy
// of MSBuild and because the SDK no longer ships with version matched assemblies, we
// register an assembly loader that will load assemblies from the msbuild path with
// equal or higher version numbers than requested.
LooseVersionAssemblyLoader.Register(msBuildInstance.MSBuildPath);
#endif
MSBuildLocator.RegisterInstance(msBuildInstance);
}
public static MSBuildWorkspace CreateWorkspace()
{
var properties = new Dictionary<string, string>
{
#if NETCOREAPP
// This property ensures that XAML files will be compiled in the current AppDomain
// rather than a separate one. Any tasks isolated in AppDomains or tasks that create
// AppDomains will likely not work due to https://github.com/Microsoft/MSBuildLocator/issues/16.
{ "AlwaysCompileMarkupFilesInSeparateDomain", bool.FalseString },
#endif
// Use the latest language version to force the full set of available analyzers to run on the project.
{ "LangVersion", "latest" },
};
return MSBuildWorkspace.Create(properties, AnalyzerRunnerMefHostServices.DefaultServices);
}
}
}
......@@ -5,11 +5,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
......@@ -22,14 +20,16 @@
namespace AnalyzerRunner
{
internal sealed class CodeRefactoringRunner
public sealed class CodeRefactoringRunner
{
private readonly Workspace _workspace;
private readonly Options _options;
private readonly ImmutableDictionary<string, ImmutableArray<CodeRefactoringProvider>> _refactorings;
private readonly ImmutableDictionary<string, ImmutableHashSet<int>> _syntaxKinds;
public CodeRefactoringRunner(Options options)
public CodeRefactoringRunner(Workspace workspace, Options options)
{
_workspace = workspace;
_options = options;
var refactorings = GetCodeRefactoringProviders(options.AnalyzerPath);
......@@ -40,21 +40,14 @@ public CodeRefactoringRunner(Options options)
public bool HasRefactorings => _refactorings.Any(pair => pair.Value.Any());
public async Task RunAsync(Workspace workspace, CancellationToken cancellationToken)
public async Task RunAsync(CancellationToken cancellationToken)
{
if (!HasRefactorings)
{
return;
}
if (!string.IsNullOrEmpty(_options.ProfileRoot))
{
ProfileOptimization.StartProfile(nameof(CodeRefactoringRunner));
}
var solution = workspace.CurrentSolution;
var stopwatch = PerformanceTracker.StartNew();
var solution = _workspace.CurrentSolution;
var updatedSolution = solution;
foreach (var project in solution.Projects)
......@@ -73,7 +66,7 @@ public async Task RunAsync(Workspace workspace, CancellationToken cancellationTo
if (_options.ApplyChanges)
{
workspace.TryApplyChanges(updatedSolution);
_workspace.TryApplyChanges(updatedSolution);
}
}
......
......@@ -5,10 +5,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
......@@ -19,13 +17,15 @@
namespace AnalyzerRunner
{
internal sealed class DiagnosticAnalyzerRunner
public sealed class DiagnosticAnalyzerRunner
{
private readonly Workspace _workspace;
private readonly Options _options;
private readonly ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> _analyzers;
public DiagnosticAnalyzerRunner(Options options)
public DiagnosticAnalyzerRunner(Workspace workspace, Options options)
{
_workspace = workspace;
_options = options;
var analyzers = GetDiagnosticAnalyzers(options.AnalyzerPath);
......@@ -34,20 +34,8 @@ public DiagnosticAnalyzerRunner(Options options)
public bool HasAnalyzers => _analyzers.Any(pair => pair.Value.Any());
public async Task RunAsync(Workspace workspace, CancellationToken cancellationToken)
private static Solution SetOptions(Solution solution)
{
if (!HasAnalyzers)
{
return;
}
if (!string.IsNullOrEmpty(_options.ProfileRoot))
{
ProfileOptimization.StartProfile(nameof(DiagnosticAnalyzerRunner));
}
var solution = workspace.CurrentSolution;
// Make sure AD0001 and AD0002 are reported as errors
foreach (var projectId in solution.ProjectIds)
{
......@@ -62,6 +50,34 @@ public async Task RunAsync(Workspace workspace, CancellationToken cancellationTo
solution = solution.WithProjectCompilationOptions(projectId, modifiedCompilationOptions);
}
return solution;
}
public async Task RunAsync(CancellationToken cancellationToken)
{
if (!HasAnalyzers)
{
return;
}
var solution = _workspace.CurrentSolution;
solution = SetOptions(solution);
await GetAnalysisResultAsync(solution, _analyzers, _options, cancellationToken).ConfigureAwait(false);
}
// Also runs per document analysis, used by AnalyzerRunner CLI tool
internal async Task RunAllAsync(CancellationToken cancellationToken)
{
if (!HasAnalyzers)
{
return;
}
var solution = _workspace.CurrentSolution;
solution = SetOptions(solution);
var stopwatch = PerformanceTracker.StartNew();
var analysisResult = await GetAnalysisResultAsync(solution, _analyzers, _options, cancellationToken).ConfigureAwait(false);
......@@ -387,7 +403,7 @@ private static IEnumerable<DiagnosticAnalyzer> FilterAnalyzers(IEnumerable<Diagn
}
}
private static void WriteTelemetry(ImmutableDictionary<ProjectId, AnalysisResult> dictionary)
internal static void WriteTelemetry(ImmutableDictionary<ProjectId, AnalysisResult> dictionary)
{
if (dictionary.IsEmpty)
{
......
......@@ -5,7 +5,6 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
......@@ -19,18 +18,20 @@
namespace AnalyzerRunner
{
internal class IncrementalAnalyzerRunner
public sealed class IncrementalAnalyzerRunner
{
private readonly Workspace _workspace;
private readonly Options _options;
public IncrementalAnalyzerRunner(Options options)
public IncrementalAnalyzerRunner(Workspace workspace, Options options)
{
_workspace = workspace;
_options = options;
}
public bool HasAnalyzers => _options.IncrementalAnalyzerNames.Any();
internal async Task RunAsync(Workspace workspace, CancellationToken cancellationToken)
public async Task RunAsync(CancellationToken cancellationToken)
{
if (!HasAnalyzers)
{
......@@ -39,49 +40,41 @@ internal async Task RunAsync(Workspace workspace, CancellationToken cancellation
var usePersistentStorage = _options.UsePersistentStorage;
workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options
_workspace.TryApplyChanges(_workspace.CurrentSolution.WithOptions(_workspace.Options
.WithChangedOption(SolutionCrawlerOptions.BackgroundAnalysisScopeOption, LanguageNames.CSharp, _options.AnalysisScope)
.WithChangedOption(SolutionCrawlerOptions.BackgroundAnalysisScopeOption, LanguageNames.VisualBasic, _options.AnalysisScope)
.WithChangedOption(StorageOptions.Database, usePersistentStorage ? StorageDatabase.SQLite : StorageDatabase.None)));
if (!string.IsNullOrEmpty(_options.ProfileRoot))
{
ProfileOptimization.StartProfile(nameof(IIncrementalAnalyzer));
}
var exportProvider = (IMefHostExportProvider)workspace.Services.HostServices;
var exportProvider = (IMefHostExportProvider)_workspace.Services.HostServices;
var solutionCrawlerRegistrationService = (SolutionCrawlerRegistrationService)workspace.Services.GetRequiredService<ISolutionCrawlerRegistrationService>();
solutionCrawlerRegistrationService.Register(workspace);
var solutionCrawlerRegistrationService = (SolutionCrawlerRegistrationService)_workspace.Services.GetRequiredService<ISolutionCrawlerRegistrationService>();
solutionCrawlerRegistrationService.Register(_workspace);
if (usePersistentStorage)
{
var persistentStorageService = workspace.Services.GetRequiredService<IPersistentStorageService>();
using var persistentStorage = persistentStorageService.GetStorage(workspace.CurrentSolution);
var persistentStorageService = _workspace.Services.GetRequiredService<IPersistentStorageService>();
using var persistentStorage = persistentStorageService.GetStorage(_workspace.CurrentSolution);
if (persistentStorage is NoOpPersistentStorage)
{
throw new InvalidOperationException("Benchmark is not configured to use persistent storage.");
}
}
Console.WriteLine("Pausing 5 seconds before continuing analysis...");
await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
var incrementalAnalyzerProviders = exportProvider.GetExports<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>();
foreach (var incrementalAnalyzerName in _options.IncrementalAnalyzerNames)
{
var incrementalAnalyzerProvider = incrementalAnalyzerProviders.Where(x => x.Metadata.Name == incrementalAnalyzerName).SingleOrDefault(provider => provider.Metadata.WorkspaceKinds?.Contains(workspace.Kind) ?? false)?.Value;
var incrementalAnalyzerProvider = incrementalAnalyzerProviders.Where(x => x.Metadata.Name == incrementalAnalyzerName).SingleOrDefault(provider => provider.Metadata.WorkspaceKinds?.Contains(_workspace.Kind) ?? false)?.Value;
incrementalAnalyzerProvider ??= incrementalAnalyzerProviders.Where(x => x.Metadata.Name == incrementalAnalyzerName).SingleOrDefault(provider => provider.Metadata.WorkspaceKinds?.Contains(WorkspaceKind.Host) ?? false)?.Value;
incrementalAnalyzerProvider ??= incrementalAnalyzerProviders.Where(x => x.Metadata.Name == incrementalAnalyzerName).SingleOrDefault(provider => provider.Metadata.WorkspaceKinds?.Contains(WorkspaceKind.RemoteWorkspace) ?? false)?.Value;
incrementalAnalyzerProvider ??= incrementalAnalyzerProviders.Where(x => x.Metadata.Name == incrementalAnalyzerName).Single(provider => provider.Metadata.WorkspaceKinds is null).Value;
var incrementalAnalyzer = incrementalAnalyzerProvider.CreateIncrementalAnalyzer(workspace);
solutionCrawlerRegistrationService.WaitUntilCompletion_ForTestingPurposesOnly(workspace, ImmutableArray.Create(incrementalAnalyzer));
var incrementalAnalyzer = incrementalAnalyzerProvider.CreateIncrementalAnalyzer(_workspace);
solutionCrawlerRegistrationService.WaitUntilCompletion_ForTestingPurposesOnly(_workspace, ImmutableArray.Create(incrementalAnalyzer));
switch (incrementalAnalyzerName)
{
case nameof(SymbolTreeInfoIncrementalAnalyzerProvider):
var symbolTreeInfoCacheService = workspace.Services.GetRequiredService<ISymbolTreeInfoCacheService>();
var symbolTreeInfo = await symbolTreeInfoCacheService.TryGetSourceSymbolTreeInfoAsync(workspace.CurrentSolution.Projects.First(), cancellationToken).ConfigureAwait(false);
var symbolTreeInfoCacheService = _workspace.Services.GetRequiredService<ISymbolTreeInfoCacheService>();
var symbolTreeInfo = await symbolTreeInfoCacheService.TryGetSourceSymbolTreeInfoAsync(_workspace.CurrentSolution.Projects.First(), cancellationToken).ConfigureAwait(false);
if (symbolTreeInfo is null)
{
throw new InvalidOperationException("Benchmark failed to calculate symbol tree info.");
......
......@@ -10,7 +10,7 @@
namespace AnalyzerRunner
{
internal sealed class Options
public sealed class Options
{
public readonly string AnalyzerPath;
public readonly string SolutionPath;
......@@ -20,22 +20,62 @@ internal sealed class Options
public readonly bool RunConcurrent;
public readonly bool ReportSuppressedDiagnostics;
public readonly bool ApplyChanges;
public readonly bool ShowStats;
public readonly bool ShowCompilerDiagnostics;
public readonly bool UseAll;
public readonly int Iterations;
public readonly bool TestDocuments;
public readonly Func<string, bool> TestDocumentMatch;
public readonly int TestDocumentIterations;
public readonly string LogFileName;
public readonly string ProfileRoot;
// Options specific to incremental analyzers
public readonly bool UsePersistentStorage;
public readonly BackgroundAnalysisScope AnalysisScope;
public readonly ImmutableList<string> IncrementalAnalyzerNames;
public readonly ImmutableArray<string> IncrementalAnalyzerNames;
public readonly bool FullSolutionAnalysis;
// Options used by AnalyzerRunner CLI only
internal readonly bool ShowStats;
internal readonly bool ShowCompilerDiagnostics;
internal readonly bool TestDocuments;
internal readonly Func<string, bool> TestDocumentMatch;
internal readonly int TestDocumentIterations;
internal readonly string LogFileName;
internal readonly string ProfileRoot;
internal BackgroundAnalysisScope AnalysisScope
=> FullSolutionAnalysis ? BackgroundAnalysisScope.FullSolution : BackgroundAnalysisScope.Default;
public Options(
string analyzerPath,
string solutionPath,
ImmutableHashSet<string> analyzerIds,
ImmutableHashSet<string> refactoringNodes,
bool runConcurrent,
bool reportSuppressedDiagnostics,
bool applyChanges,
bool useAll,
int iterations,
bool usePersistentStorage,
bool fullSolutionAnalysis,
ImmutableArray<string> incrementalAnalyzerNames)
: this(analyzerPath,
solutionPath,
analyzerIds,
refactoringNodes,
runConcurrent,
reportSuppressedDiagnostics,
applyChanges,
showStats: false,
showCompilerDiagnostics: false,
useAll,
iterations,
testDocuments: false,
testDocumentMatch: _ => false,
testDocumentIterations: 0,
logFileName: null,
profileRoot: null,
usePersistentStorage,
fullSolutionAnalysis,
incrementalAnalyzerNames)
{ }
private Options(
internal Options(
string analyzerPath,
string solutionPath,
ImmutableHashSet<string> analyzerIds,
......@@ -53,8 +93,8 @@ internal sealed class Options
string logFileName,
string profileRoot,
bool usePersistentStorage,
BackgroundAnalysisScope analysisScope,
ImmutableList<string> incrementalAnalyzerNames)
bool fullSolutionAnalysis,
ImmutableArray<string> incrementalAnalyzerNames)
{
AnalyzerPath = analyzerPath;
SolutionPath = solutionPath;
......@@ -73,7 +113,7 @@ internal sealed class Options
LogFileName = logFileName;
ProfileRoot = profileRoot;
UsePersistentStorage = usePersistentStorage;
AnalysisScope = analysisScope;
FullSolutionAnalysis = fullSolutionAnalysis;
IncrementalAnalyzerNames = incrementalAnalyzerNames;
}
......@@ -96,8 +136,8 @@ internal static Options Create(string[] args)
string logFileName = null;
string profileRoot = null;
var usePersistentStorage = false;
var analysisScope = BackgroundAnalysisScope.Default;
var incrementalAnalyzerNames = ImmutableList.CreateBuilder<string>();
var fullSolutionAnalysis = false;
var incrementalAnalyzerNames = ImmutableArray.CreateBuilder<string>();
int i = 0;
while (i < args.Length)
......@@ -155,7 +195,7 @@ internal static Options Create(string[] args)
usePersistentStorage = true;
break;
case "/fsa":
analysisScope = BackgroundAnalysisScope.FullSolution;
fullSolutionAnalysis = true;
break;
case "/ia":
incrementalAnalyzerNames.Add(ReadValue());
......@@ -207,7 +247,7 @@ internal static Options Create(string[] args)
logFileName: logFileName,
profileRoot: profileRoot,
usePersistentStorage: usePersistentStorage,
analysisScope: analysisScope,
fullSolutionAnalysis: fullSolutionAnalysis,
incrementalAnalyzerNames: incrementalAnalyzerNames.ToImmutable());
}
}
......
......@@ -6,13 +6,11 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.MSBuild;
......@@ -39,7 +37,7 @@ public static async Task Main(string[] args)
return;
}
CancellationTokenSource cts = new CancellationTokenSource();
var cts = new CancellationTokenSource();
Console.CancelKeyPress +=
(sender, e) =>
{
......@@ -47,23 +45,20 @@ public static async Task Main(string[] args)
cts.Cancel();
};
// QueryVisualStudioInstances returns Visual Studio installations on .NET Framework, and .NET Core SDK
// installations on .NET Core. We use the one with the most recent version.
var msBuildInstance = MSBuildLocator.QueryVisualStudioInstances().OrderByDescending(x => x.Version).First();
var cancellationToken = cts.Token;
if (!string.IsNullOrEmpty(options.ProfileRoot))
{
Directory.CreateDirectory(options.ProfileRoot);
ProfileOptimization.SetProfileRoot(options.ProfileRoot);
}
#if NETCOREAPP
// Since we do not inherit msbuild.deps.json when referencing the SDK copy
// of MSBuild and because the SDK no longer ships with version matched assemblies, we
// register an assembly loader that will load assemblies from the msbuild path with
// equal or higher version numbers than requested.
LooseVersionAssemblyLoader.Register(msBuildInstance.MSBuildPath);
#endif
using var workspace = AnalyzerRunnerHelper.CreateWorkspace();
MSBuildLocator.RegisterInstance(msBuildInstance);
var incrementalAnalyzerRunner = new IncrementalAnalyzerRunner(workspace, options);
var diagnosticAnalyzerRunner = new DiagnosticAnalyzerRunner(workspace, options);
var codeRefactoringRunner = new CodeRefactoringRunner(workspace, options);
var incrementalAnalyzerRunner = new IncrementalAnalyzerRunner(options);
var diagnosticAnalyzerRunner = new DiagnosticAnalyzerRunner(options);
var codeRefactoringRunner = new CodeRefactoringRunner(options);
if (!incrementalAnalyzerRunner.HasAnalyzers && !diagnosticAnalyzerRunner.HasAnalyzers && !codeRefactoringRunner.HasRefactorings)
{
WriteLine("No analyzers found", ConsoleColor.Red);
......@@ -71,113 +66,126 @@ public static async Task Main(string[] args)
return;
}
var cancellationToken = cts.Token;
var stopwatch = PerformanceTracker.StartNew();
if (!string.IsNullOrEmpty(options.ProfileRoot))
{
Directory.CreateDirectory(options.ProfileRoot);
ProfileOptimization.SetProfileRoot(options.ProfileRoot);
ProfileOptimization.StartProfile(nameof(MSBuildWorkspace.OpenSolutionAsync));
}
var stopwatch = PerformanceTracker.StartNew();
var properties = new Dictionary<string, string>
await workspace.OpenSolutionAsync(options.SolutionPath, progress: null, cancellationToken).ConfigureAwait(false);
foreach (var workspaceDiagnostic in workspace.Diagnostics)
{
#if NETCOREAPP
// This property ensures that XAML files will be compiled in the current AppDomain
// rather than a separate one. Any tasks isolated in AppDomains or tasks that create
// AppDomains will likely not work due to https://github.com/Microsoft/MSBuildLocator/issues/16.
{ "AlwaysCompileMarkupFilesInSeparateDomain", bool.FalseString },
#endif
// Use the latest language version to force the full set of available analyzers to run on the project.
{ "LangVersion", "latest" },
};
if (workspaceDiagnostic.Kind == WorkspaceDiagnosticKind.Failure)
{
Console.WriteLine(workspaceDiagnostic.Message);
}
}
if (!string.IsNullOrEmpty(options.ProfileRoot))
Console.WriteLine($"Loaded solution in {stopwatch.GetSummary(preciseMemory: true)}");
if (options.ShowStats)
{
ProfileOptimization.StartProfile(nameof(MSBuildWorkspace.OpenSolutionAsync));
stopwatch = PerformanceTracker.StartNew();
ShowSolutionStatistics(workspace.CurrentSolution, cancellationToken);
Console.WriteLine($"Statistics gathered in {stopwatch.GetSummary(preciseMemory: true)}");
}
using (MSBuildWorkspace workspace = MSBuildWorkspace.Create(properties, AnalyzerRunnerMefHostServices.DefaultServices))
if (options.ShowCompilerDiagnostics)
{
Solution solution = await workspace.OpenSolutionAsync(options.SolutionPath, progress: null, cancellationToken).ConfigureAwait(false);
var projectIds = solution.ProjectIds;
await ShowCompilerDiagnosticsAsync(workspace.CurrentSolution, cancellationToken).ConfigureAwait(false);
}
Console.WriteLine("Pausing 5 seconds before starting analysis...");
await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
foreach (var workspaceDiagnostic in workspace.Diagnostics)
if (incrementalAnalyzerRunner.HasAnalyzers)
{
if (!string.IsNullOrEmpty(options.ProfileRoot))
{
if (workspaceDiagnostic.Kind == WorkspaceDiagnosticKind.Failure)
{
Console.WriteLine(workspaceDiagnostic.Message);
}
ProfileOptimization.StartProfile(nameof(Microsoft.CodeAnalysis.SolutionCrawler.IIncrementalAnalyzer));
}
foreach (var projectId in projectIds)
await incrementalAnalyzerRunner.RunAsync(cancellationToken).ConfigureAwait(false);
}
if (diagnosticAnalyzerRunner.HasAnalyzers)
{
if (!string.IsNullOrEmpty(options.ProfileRoot))
{
solution = solution.WithProjectAnalyzerReferences(projectId, ImmutableArray<AnalyzerReference>.Empty);
ProfileOptimization.StartProfile(nameof(DiagnosticAnalyzerRunner));
}
Console.WriteLine($"Loaded solution in {stopwatch.GetSummary(preciseMemory: true)}");
await diagnosticAnalyzerRunner.RunAllAsync(cancellationToken).ConfigureAwait(false);
}
if (options.ShowStats)
if (codeRefactoringRunner.HasRefactorings)
{
if (!string.IsNullOrEmpty(options.ProfileRoot))
{
stopwatch = PerformanceTracker.StartNew();
List<Project> projects = solution.Projects.Where(project => project.Language == LanguageNames.CSharp || project.Language == LanguageNames.VisualBasic).ToList();
ProfileOptimization.StartProfile(nameof(CodeRefactoringRunner));
}
Console.WriteLine("Number of projects:\t\t" + projects.Count);
Console.WriteLine("Number of documents:\t\t" + projects.Sum(x => x.DocumentIds.Count));
await codeRefactoringRunner.RunAsync(cancellationToken).ConfigureAwait(false);
}
}
var statistics = GetSolutionStatistics(projects, cancellationToken);
private static async Task ShowCompilerDiagnosticsAsync(Solution solution, CancellationToken cancellationToken)
{
var projectIds = solution.ProjectIds;
Console.WriteLine("Number of syntax nodes:\t\t" + statistics.NumberofNodes);
Console.WriteLine("Number of syntax tokens:\t" + statistics.NumberOfTokens);
Console.WriteLine("Number of syntax trivia:\t" + statistics.NumberOfTrivia);
foreach (var projectId in projectIds)
{
solution = solution.WithProjectAnalyzerReferences(projectId, ImmutableArray<AnalyzerReference>.Empty);
}
Console.WriteLine($"Statistics gathered in {stopwatch.GetSummary(preciseMemory: true)}");
}
var projects = solution.Projects.Where(project => project.Language == LanguageNames.CSharp || project.Language == LanguageNames.VisualBasic).ToList();
if (options.ShowCompilerDiagnostics)
var diagnosticStatistics = new Dictionary<string, (string description, DiagnosticSeverity severity, int count)>();
foreach (var project in projects)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
foreach (var diagnostic in compilation.GetDiagnostics(cancellationToken))
{
var projects = solution.Projects.Where(project => project.Language == LanguageNames.CSharp || project.Language == LanguageNames.VisualBasic).ToList();
var diagnosticStatistics = new Dictionary<string, (string description, DiagnosticSeverity severity, int count)>();
foreach (var project in projects)
diagnosticStatistics.TryGetValue(diagnostic.Id, out var existing);
var description = existing.description;
if (string.IsNullOrEmpty(description))
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
foreach (var diagnostic in compilation.GetDiagnostics(cancellationToken))
description = diagnostic.Descriptor?.Title.ToString();
if (string.IsNullOrEmpty(description))
{
diagnosticStatistics.TryGetValue(diagnostic.Id, out var existing);
var description = existing.description;
if (string.IsNullOrEmpty(description))
{
description = diagnostic.Descriptor?.Title.ToString();
if (string.IsNullOrEmpty(description))
{
description = diagnostic.Descriptor?.MessageFormat.ToString();
}
}
diagnosticStatistics[diagnostic.Id] = (description, diagnostic.Descriptor.DefaultSeverity, existing.count + 1);
description = diagnostic.Descriptor?.MessageFormat.ToString();
}
}
foreach (var pair in diagnosticStatistics)
{
Console.WriteLine($" {pair.Value.severity} {pair.Key}: {pair.Value.count} instances ({pair.Value.description})");
}
diagnosticStatistics[diagnostic.Id] = (description, diagnostic.Descriptor.DefaultSeverity, existing.count + 1);
}
}
Console.WriteLine("Pausing 5 seconds before starting analysis...");
await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
await incrementalAnalyzerRunner.RunAsync(workspace, cancellationToken).ConfigureAwait(false);
await diagnosticAnalyzerRunner.RunAsync(workspace, cancellationToken).ConfigureAwait(false);
await codeRefactoringRunner.RunAsync(workspace, cancellationToken).ConfigureAwait(false);
foreach (var pair in diagnosticStatistics)
{
Console.WriteLine($" {pair.Value.severity} {pair.Key}: {pair.Value.count} instances ({pair.Value.description})");
}
}
private static void ShowSolutionStatistics(Solution solution, CancellationToken cancellationToken)
{
var projects = solution.Projects.Where(project => project.Language == LanguageNames.CSharp || project.Language == LanguageNames.VisualBasic).ToList();
Console.WriteLine("Number of projects:\t\t" + projects.Count);
Console.WriteLine("Number of documents:\t\t" + projects.Sum(x => x.DocumentIds.Count));
var statistics = GetSolutionStatistics(projects, cancellationToken);
Console.WriteLine("Number of syntax nodes:\t\t" + statistics.NumberofNodes);
Console.WriteLine("Number of syntax tokens:\t" + statistics.NumberOfTokens);
Console.WriteLine("Number of syntax trivia:\t" + statistics.NumberOfTrivia);
}
private static Statistic GetSolutionStatistics(IEnumerable<Project> projects, CancellationToken cancellationToken)
{
ConcurrentBag<Statistic> sums = new ConcurrentBag<Statistic>();
var sums = new ConcurrentBag<Statistic>();
Parallel.ForEach(projects.SelectMany(project => project.Documents), document =>
{
......@@ -185,7 +193,7 @@ private static Statistic GetSolutionStatistics(IEnumerable<Project> projects, Ca
sums.Add(documentStatistics);
});
Statistic sum = sums.Aggregate(new Statistic(0, 0, 0), (currentResult, value) => currentResult + value);
var sum = sums.Aggregate(new Statistic(0, 0, 0), (currentResult, value) => currentResult + value);
return sum;
}
......@@ -193,15 +201,15 @@ private static Statistic GetSolutionStatistics(IEnumerable<Project> projects, Ca
// https://github.com/dotnet/roslyn/issues/23108
private static async Task<Statistic> GetSolutionStatisticsAsync(Document document, CancellationToken cancellationToken)
{
SyntaxTree tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
SyntaxNode root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);
var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);
var tokensAndNodes = root.DescendantNodesAndTokensAndSelf(descendIntoTrivia: true);
int numberOfNodes = tokensAndNodes.Count(x => x.IsNode);
int numberOfTokens = tokensAndNodes.Count(x => x.IsToken);
int numberOfTrivia = root.DescendantTrivia(descendIntoTrivia: true).Count();
var numberOfNodes = tokensAndNodes.Count(x => x.IsNode);
var numberOfTokens = tokensAndNodes.Count(x => x.IsToken);
var numberOfTrivia = root.DescendantTrivia(descendIntoTrivia: true).Count();
return new Statistic(numberOfNodes, numberOfTokens, numberOfTrivia);
}
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
namespace CompilerBenchmarks
{
internal static class Helpers
{
public const string TestProjectEnvVarName = "ROSLYN_TEST_PROJECT_DIR";
public static Compilation CreateReproCompilation()
{
var projectDir = Environment.GetEnvironmentVariable(TestProjectEnvVarName);
var cmdLineParser = new CSharpCommandLineParser();
var responseFile = Path.Combine(projectDir, "repro.rsp");
var compiler = new MockCSharpCompiler(responseFile, projectDir, Array.Empty<string>());
var output = new StringWriter();
return compiler.CreateCompilation(output, null, null);
}
}
}

This project contains a set of "micro" benchmarks for the compiler, focused on measuring
the time spent in specific phases of the compiler, e.g. Emit, metadata serialization, binding,
parsing, etc.
To run all benchmarks, simply run the `run-perf.ps1` file on your machine, which should produce
a simple output table containing the results. To compare the results of your change, you can
run the script before and after and attempt to compare the results. Calculating statistical
significance is beyond the scope of this document, but you can get a general idea of whether
or not your changes are significant if the different is substantially larger than the "error"
value reported in the results summary.
\ No newline at end of file
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO;
using BenchmarkDotNet.Attributes;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Emit;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.Compilation;
namespace CompilerBenchmarks
{
public class StageBenchmarks
{
private Compilation _comp;
private CommonPEModuleBuilder _moduleBeingBuilt;
private EmitOptions _options;
private MemoryStream _peStream;
[Benchmark]
public object Parsing()
{
return Helpers.CreateReproCompilation();
}
[GlobalSetup(Target = nameof(CompileMethodsAndEmit))]
public void LoadCompilation()
{
_peStream = new MemoryStream();
_comp = Helpers.CreateReproCompilation();
// Call GetDiagnostics to force declaration symbol binding to finish
_ = _comp.GetDiagnostics();
}
[Benchmark]
public object CompileMethodsAndEmit()
{
_peStream.Position = 0;
return _comp.Emit(_peStream);
}
[GlobalSetup(Target = nameof(SerializeMetadata))]
public void CompileMethods()
{
LoadCompilation();
_options = EmitOptions.Default.WithIncludePrivateMembers(true);
bool embedPdb = _options.DebugInformationFormat == DebugInformationFormat.Embedded;
var diagnostics = DiagnosticBag.GetInstance();
_moduleBeingBuilt = _comp.CheckOptionsAndCreateModuleBuilder(
diagnostics,
manifestResources: null,
_options,
debugEntryPoint: null,
sourceLinkStream: null,
embeddedTexts: null,
testData: null,
cancellationToken: default);
bool success = false;
success = _comp.CompileMethods(
_moduleBeingBuilt,
emittingPdb: embedPdb,
emitMetadataOnly: _options.EmitMetadataOnly,
emitTestCoverageData: _options.EmitTestCoverageData,
diagnostics: diagnostics,
filterOpt: null,
cancellationToken: default);
_comp.GenerateResourcesAndDocumentationComments(
_moduleBeingBuilt,
xmlDocumentationStream: null,
win32ResourcesStream: null,
_options.OutputNameOverride,
diagnostics,
cancellationToken: default);
_comp.ReportUnusedImports(null, diagnostics, default);
_moduleBeingBuilt.CompilationFinished();
diagnostics.Free();
}
[Benchmark]
public object SerializeMetadata()
{
var diagnostics = DiagnosticBag.GetInstance();
_comp.SerializeToPeStream(
_moduleBeingBuilt,
new SimpleEmitStreamProvider(_peStream),
metadataPEStreamProvider: null,
pdbStreamProvider: null,
testSymWriterFactory: null,
diagnostics,
metadataOnly: _options.EmitMetadataOnly,
includePrivateMembers: _options.IncludePrivateMembers,
emitTestCoverageData: _options.EmitTestCoverageData,
pePdbFilePath: _options.PdbFilePath,
privateKeyOpt: null,
cancellationToken: default);
diagnostics.Free();
return _peStream;
}
}
}
# Licensed to the .NET Foundation under one or more agreements.
# The .NET Foundation licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
[CmdletBinding(PositionalBinding=$false)]
param (
# By default, the Roslyn dir is expected to be next to this dir
[string]$roslynDir = "$PSScriptRoot/../../.."
)
Set-Variable -Name LastExitCode 0
Set-StrictMode -Version 2.0
$ErrorActionPreference = "Stop"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
. (Join-Path $roslynDir "eng/build-utils.ps1")
# Download dotnet if it isn't already available
Ensure-DotnetSdk
$reproPath = Join-Path $ArtifactsDir "CodeAnalysisRepro"
if (-not (Test-Path $reproPath)) {
$tmpFile = [System.IO.Path]::GetTempFileName()
Invoke-WebRequest -Uri "https://roslyninfra.blob.core.windows.net/perf-artifacts/CodeAnalysisRepro.zip" -UseBasicParsing -OutFile $tmpFile
Unzip $tmpFile $ArtifactsDir
}
Exec-Command "dotnet" "run -c Release $reproPath"
}
catch {
Write-Host $_
Write-Host $_.Exception
exit 1
}
......@@ -11,7 +11,7 @@ public class MemoryDiagnoserConfig : ManualConfig
{
public MemoryDiagnoserConfig()
{
Add(MemoryDiagnoser.Default);
AddDiagnoser(MemoryDiagnoser.Default);
}
}
}

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30030.7
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis", "..\..\..\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj", "{7B3C638D-D43E-4346-ACAC-56ACCE13B500}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\..\..\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{7b3c638d-d43e-4346-acac-56acce13b500}*SharedItemsImports = 5
..\..\..\Dependencies\CodeAnalysis.Debugging\Microsoft.CodeAnalysis.Debugging.projitems*{7b3c638d-d43e-4346-acac-56acce13b500}*SharedItemsImports = 5
..\..\..\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems*{7b3c638d-d43e-4346-acac-56acce13b500}*SharedItemsImports = 5
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7B3C638D-D43E-4346-ACAC-56ACCE13B500}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B3C638D-D43E-4346-ACAC-56ACCE13B500}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B3C638D-D43E-4346-ACAC-56ACCE13B500}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B3C638D-D43E-4346-ACAC-56ACCE13B500}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1A659683-1C0B-4A31-93C6-08B9E9D97170}
EndGlobalSection
EndGlobal
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using AnalyzerRunner;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;
namespace IdeCoreBenchmarks
{
[MemoryDiagnoser]
[RyuJitX64Job]
public class CSharpIdeAnalyzerBenchmarks
{
private readonly string _solutionPath;
private Options _options;
private MSBuildWorkspace _workspace;
private DiagnosticAnalyzerRunner _diagnosticAnalyzerRunner;
[Params("CSharpAddBracesDiagnosticAnalyzer")]
public string AnalyzerName { get; set; }
public CSharpIdeAnalyzerBenchmarks()
{
var roslynRoot = Environment.GetEnvironmentVariable(Program.RoslynRootPathEnvVariableName);
_solutionPath = Path.Combine(roslynRoot, @"src\Tools\IdeCoreBenchmarks\Assets\Microsoft.CodeAnalysis.sln");
if (!File.Exists(_solutionPath))
{
throw new ArgumentException();
}
}
[GlobalSetup]
public void Setup()
{
var analyzerAssemblyPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Microsoft.CodeAnalysis.CSharp.Features.dll");
_options = new Options(
analyzerPath: analyzerAssemblyPath,
solutionPath: _solutionPath,
analyzerIds: ImmutableHashSet.Create(AnalyzerName),
refactoringNodes: ImmutableHashSet<string>.Empty,
runConcurrent: true,
reportSuppressedDiagnostics: true,
applyChanges: false,
useAll: false,
iterations: 1,
usePersistentStorage: false,
fullSolutionAnalysis: false,
incrementalAnalyzerNames: ImmutableArray<string>.Empty);
_workspace = AnalyzerRunnerHelper.CreateWorkspace();
_diagnosticAnalyzerRunner = new DiagnosticAnalyzerRunner(_workspace, _options);
_ = _workspace.OpenSolutionAsync(_solutionPath, progress: null, CancellationToken.None).Result;
}
[GlobalCleanup]
public void Cleanup()
{
_workspace?.Dispose();
_workspace = null;
}
[Benchmark]
public async Task RunAnalyzer()
{
await _diagnosticAnalyzerRunner.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.IO;
using System.Threading;
using BenchmarkDotNet.Attributes;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
namespace IdeCoreBenchmarks
{
[MemoryDiagnoser]
public class FormatterBenchmarks
{
private readonly int _iterationCount = 5;
private Document _document;
private OptionSet _options;
[GlobalSetup]
public void GlobalSetup()
{
var roslynRoot = Environment.GetEnvironmentVariable(Program.RoslynRootPathEnvVariableName);
var csFilePath = Path.Combine(roslynRoot, @"src\Compilers\CSharp\Portable\Generated\Syntax.xml.Syntax.Generated.cs");
if (!File.Exists(csFilePath))
{
throw new ArgumentException();
}
// Remove some newlines
var text = File.ReadAllText(csFilePath).Replace("<auto-generated />", "")
.Replace($"{{{Environment.NewLine}{Environment.NewLine}", "{")
.Replace($"}}{Environment.NewLine}{Environment.NewLine}", "}")
.Replace($"{{{Environment.NewLine}", "{")
.Replace($"}}{Environment.NewLine}", "}")
.Replace($";{Environment.NewLine}", ";");
var projectId = ProjectId.CreateNewId();
var documentId = DocumentId.CreateNewId(projectId);
var solution = new AdhocWorkspace(MefHostServices.Create(MefHostServices.DefaultAssemblies)).CurrentSolution
.AddProject(projectId, "ProjectName", "AssemblyName", LanguageNames.CSharp)
.AddDocument(documentId, "DocumentName", text);
var document = solution.GetDocument(documentId);
var root = document.GetSyntaxRootAsync(CancellationToken.None).Result.WithAdditionalAnnotations(Formatter.Annotation);
solution = solution.WithDocumentSyntaxRoot(documentId, root);
_document = solution.GetDocument(documentId);
_options = _document.GetOptionsAsync().Result
.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInTypes, true)
.WithChangedOption(CSharpFormattingOptions.WrappingKeepStatementsOnSingleLine, false)
.WithChangedOption(CSharpFormattingOptions.WrappingPreserveSingleLine, false);
}
[Benchmark]
public void FormatSyntaxNode()
{
for (int i = 0; i < _iterationCount; ++i)
{
var formattedDoc = Formatter.FormatAsync(_document, Formatter.Annotation, _options, CancellationToken.None).Result;
var formattedRoot = formattedDoc.GetSyntaxRootAsync(CancellationToken.None).Result;
_ = formattedRoot.DescendantNodesAndSelf().ToImmutableArray();
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(RepositoryEngineeringDir)targets\GenerateCompilerExecutableBindingRedirects.targets" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFrameworks>$(RoslynPortableTargetFrameworks)</TargetFrameworks>
<IsShipping>false</IsShipping>
<PlatformTarget>AnyCPU</PlatformTarget>
<!-- Automatically generate the necessary assembly binding redirects -->
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" />
<None Include="run-perf.ps1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetVersion)" />
<!-- This is to avoid a version conflict during build -->
<PackageReference Include="System.CodeDom" Version="$(SystemCodeDomVersion)" />
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkVersion)" ExcludeAssets="Runtime" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj" />
<ProjectReference Include="..\..\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj" />
<ProjectReference Include="..\..\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj" />
<ProjectReference Include="..\..\Scripting\Core\Microsoft.CodeAnalysis.Scripting.csproj" />
<ProjectReference Include="..\..\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj" />
<ProjectReference Include="..\..\Workspaces\Core\MSBuild\Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj" />
<ProjectReference Include="..\..\Workspaces\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Workspaces.csproj" />
<ProjectReference Include="..\..\Workspaces\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj" />
<ProjectReference Include="..\..\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj" />
<ProjectReference Include="..\..\EditorFeatures\Text\Microsoft.CodeAnalysis.EditorFeatures.Text.csproj" />
<ProjectReference Include="..\..\Compilers\Test\Resources\Core\Microsoft.CodeAnalysis.Compiler.Test.Resources.csproj" />
<ProjectReference Include="..\..\Compilers\Test\Utilities\CSharp\Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj" />
<ProjectReference Include="..\..\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj" />
<ProjectReference Include="..\..\Test\PdbUtilities\Roslyn.Test.PdbUtilities.csproj" />
<ProjectReference Include="..\..\Test\Utilities\Portable\Roslyn.Test.Utilities.csproj" />
<ProjectReference Include="..\..\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj" />
<ProjectReference Include="..\..\Features\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Features.vbproj" />
<ProjectReference Include="..\AnalyzerRunner\AnalyzerRunner.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
<!-- These aren't used by the build, but it allows the tool to locate dependencies of the built-in analyzers. -->
<ProjectReference Include="..\..\EditorFeatures\Core\Microsoft.CodeAnalysis.EditorFeatures.csproj" />
<ProjectReference Include="..\..\EditorFeatures\CSharp\Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj" />
<ProjectReference Include="..\..\EditorFeatures\VisualBasic\Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.vbproj" />
</ItemGroup>
</Project>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using AnalyzerRunner;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using Microsoft.CodeAnalysis.MSBuild;
namespace IdeCoreBenchmarks
{
[MemoryDiagnoser]
public class IncrementalAnalyzerBenchmarks
{
private readonly string _solutionPath;
private Options _options;
private MSBuildWorkspace _workspace;
private IncrementalAnalyzerRunner _incrementalAnalyzerRunner;
[Params("SymbolTreeInfoIncrementalAnalyzerProvider", "SyntaxTreeInfoIncrementalAnalyzerProvider")]
public string AnalyzerName { get; set; }
public IncrementalAnalyzerBenchmarks()
{
var roslynRoot = Environment.GetEnvironmentVariable(Program.RoslynRootPathEnvVariableName);
_solutionPath = Path.Combine(roslynRoot, @"src\Tools\IdeCoreBenchmarks\Assets\Microsoft.CodeAnalysis.sln");
if (!File.Exists(_solutionPath))
{
throw new ArgumentException();
}
}
[IterationSetup]
public void Setup()
{
var analyzerAssemblyPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Microsoft.CodeAnalysis.Features.dll");
_options = new Options(
analyzerPath: analyzerAssemblyPath,
solutionPath: _solutionPath,
analyzerIds: ImmutableHashSet<string>.Empty,
refactoringNodes: ImmutableHashSet<string>.Empty,
runConcurrent: true,
reportSuppressedDiagnostics: true,
applyChanges: false,
useAll: false,
iterations: 1,
usePersistentStorage: false,
fullSolutionAnalysis: true,
incrementalAnalyzerNames: ImmutableArray.Create(AnalyzerName));
_workspace = AnalyzerRunnerHelper.CreateWorkspace();
_incrementalAnalyzerRunner = new IncrementalAnalyzerRunner(_workspace, _options);
_ = _workspace.OpenSolutionAsync(_solutionPath, progress: null, CancellationToken.None).Result;
}
[IterationCleanup]
public void Cleanup()
{
_workspace?.Dispose();
_workspace = null;
}
[Benchmark]
public async Task RunIncrementalAnalyzer()
{
await _incrementalAnalyzerRunner.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
......@@ -5,43 +5,40 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Validators;
namespace CompilerBenchmarks
namespace IdeCoreBenchmarks
{
public class Program
internal class Program
{
private class IgnoreReleaseOnly : ManualConfig
{
public IgnoreReleaseOnly()
{
Add(JitOptimizationsValidator.DontFailOnError);
Add(DefaultConfig.Instance.GetLoggers().ToArray());
Add(DefaultConfig.Instance.GetExporters().ToArray());
Add(DefaultConfig.Instance.GetColumnProviders().ToArray());
Add(MemoryDiagnoser.Default);
Add(Job.Core.WithGcServer(true));
AddValidator(JitOptimizationsValidator.DontFailOnError);
AddLogger(DefaultConfig.Instance.GetLoggers().ToArray());
AddExporter(DefaultConfig.Instance.GetExporters().ToArray());
AddColumnProvider(DefaultConfig.Instance.GetColumnProviders().ToArray());
AddDiagnoser(MemoryDiagnoser.Default);
}
}
public static void Main(string[] args)
{
var projectPath = args[0];
var artifactsPath = Path.Combine(projectPath, "../BenchmarkDotNet.Artifacts");
var config = new IgnoreReleaseOnly();
var artifactsDir = Directory.CreateDirectory(artifactsPath);
config.ArtifactsPath = artifactsDir.FullName;
public const string RoslynRootPathEnvVariableName = "ROSLYN_SOURCE_ROOT_PATH";
// Benchmark.NET creates a new process to run the benchmark, so the easiest way
// to communicate information is pass by environment variable
Environment.SetEnvironmentVariable(Helpers.TestProjectEnvVarName, projectPath);
public static string GetRoslynRootLocation([CallerFilePath] string sourceFilePath = "")
{
//This file is located at [Roslyn]\src\Tools\IdeCoreBenchmarks\Program.cs
return Path.Combine(Path.GetDirectoryName(sourceFilePath), @"..\..\..");
}
_ = BenchmarkRunner.Run<StageBenchmarks>(config);
private static void Main(string[] args)
{
Environment.SetEnvironmentVariable(RoslynRootPathEnvVariableName, GetRoslynRootLocation());
new BenchmarkSwitcher(typeof(Program).Assembly).Run(args);
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.IO;
using BenchmarkDotNet.Attributes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace IdeCoreBenchmarks
{
[MemoryDiagnoser]
public class SerializationBenchmarks
{
private CompilationUnitSyntax _root;
private MemoryStream _stream;
private readonly int _iterationCount = 10;
[GlobalSetup]
public void GlobalSetup()
{
var roslynRoot = Environment.GetEnvironmentVariable(Program.RoslynRootPathEnvVariableName);
var csFilePath = Path.Combine(roslynRoot, @"src\Compilers\CSharp\Portable\Generated\Syntax.xml.Syntax.Generated.cs");
if (!File.Exists(csFilePath))
{
throw new ArgumentException();
}
var text = File.ReadAllText(csFilePath);
var tree = SyntaxFactory.ParseSyntaxTree(text);
_root = tree.GetCompilationUnitRoot();
}
[IterationCleanup]
public void SerializationCleanup()
{
_stream?.Dispose();
}
[IterationSetup(Target = nameof(SerializeSyntaxNode))]
public void SerializationSetup()
{
_stream = new MemoryStream();
}
[Benchmark]
public void SerializeSyntaxNode()
{
for (var i = 0; i < _iterationCount; ++i)
{
_root.SerializeTo(_stream);
}
}
[IterationSetup(Target = nameof(DeserializeSyntaxNode))]
public void DeserializationSetup()
{
_stream = new MemoryStream();
for (var i = 0; i < _iterationCount; ++i)
{
_root.SerializeTo(_stream);
}
_stream.Position = 0;
}
[Benchmark]
public void DeserializeSyntaxNode()
{
for (var i = 0; i < _iterationCount; ++i)
{
var droot = CSharpSyntaxNode.DeserializeFrom(_stream);
_ = droot.DescendantNodesAndSelf().ToImmutableArray();
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册