From 949b17e5695340e8cce3d04566e7a2ecb39ba742 Mon Sep 17 00:00:00 2001 From: tpodolak Date: Thu, 12 Sep 2019 23:39:58 +0200 Subject: [PATCH] [GH-35] - Making benchmarks usable for compilation analyzers --- .../AbstractDiagnosticAnalyzersBenchmarks.cs | 3 +- .../Shared/AnalyzerBenchmark.cs | 71 ++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AbstractDiagnosticAnalyzersBenchmarks.cs b/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AbstractDiagnosticAnalyzersBenchmarks.cs index 4ffd5cc1..e69ebd31 100644 --- a/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AbstractDiagnosticAnalyzersBenchmarks.cs +++ b/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AbstractDiagnosticAnalyzersBenchmarks.cs @@ -4,11 +4,12 @@ using System.Linq; using System.Reflection; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Engines; using Microsoft.CodeAnalysis; namespace NSubstitute.Analyzers.Benchmarks.Shared { - [CoreJob] + [SimpleJob(RunStrategy.ColdStart, launchCount: 50, invocationCount: 50)] [MemoryDiagnoser] public abstract class AbstractDiagnosticAnalyzersBenchmarks { diff --git a/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AnalyzerBenchmark.cs b/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AnalyzerBenchmark.cs index 1382927a..2552c6e9 100644 --- a/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AnalyzerBenchmark.cs +++ b/benchmarks/NSubstitute.Analyzers.Benchmarks/Shared/AnalyzerBenchmark.cs @@ -17,6 +17,7 @@ private AnalyzerBenchmark( DiagnosticAnalyzer analyzer, IReadOnlyList> syntaxNodeActions, IReadOnlyList> compilationStartActions, + IReadOnlyList> compilationEndActions, IReadOnlyList> compilationActions, IReadOnlyList> semanticModelActions, IReadOnlyList> symbolActions, @@ -30,6 +31,7 @@ private AnalyzerBenchmark( Analyzer = analyzer; SyntaxNodeActions = syntaxNodeActions; CompilationStartActions = compilationStartActions; + CompilationEndActions = compilationEndActions; CompilationActions = compilationActions; SemanticModelActions = semanticModelActions; SymbolActions = symbolActions; @@ -52,6 +54,8 @@ public interface IContextAndAction public IReadOnlyList> CompilationStartActions { get; } + public IReadOnlyList> CompilationEndActions { get; } + public IReadOnlyList> CompilationActions { get; } public IReadOnlyList> SemanticModelActions { get; } @@ -80,6 +84,7 @@ public static async Task CreateBenchmarkAsync(Solution soluti analyzer, benchmarkAnalyzer.SyntaxNodeActions, benchmarkAnalyzer.CompilationStartActions, + benchmarkAnalyzer.CompilationEndActions, benchmarkAnalyzer.CompilationActions, benchmarkAnalyzer.SemanticModelActions, benchmarkAnalyzer.SymbolActions, @@ -147,6 +152,11 @@ public void Run() { contextAndAction.Run(); } + + foreach (var contextAndAction in CompilationEndActions) + { + contextAndAction.Run(); + } } public static async Task>> GetDiagnosticsAsync(Solution solution, DiagnosticAnalyzer analyzer) @@ -192,6 +202,8 @@ private class BenchmarkAnalyzer : DiagnosticAnalyzer internal List> CompilationStartActions { get; } = new List>(); + internal List> CompilationEndActions { get; } = new List>(); + internal List> CompilationActions { get; } = new List>(); internal List> SemanticModelActions { get; } = new List>(); @@ -254,7 +266,11 @@ public override void RegisterSyntaxNodeAction(Action action) { _context.RegisterCompilationStartAction( - x => _analyzer.CompilationStartActions.Add(new ContextAndAction(x, action))); + x => + { + _analyzer.CompilationStartActions.Add(new ContextAndAction(x, action)); + action(new BenchmarkCompilationStartAnalysisContext(_analyzer, x)); + }); } public override void RegisterCompilationAction(Action action) @@ -313,6 +329,59 @@ public override void RegisterOperationBlockStartAction(Action _analyzer.OperationBlockStartActions.Add(new ContextAndAction(x, action))); } } + + private class BenchmarkCompilationStartAnalysisContext : CompilationStartAnalysisContext + { + private readonly BenchmarkAnalyzer _analyzer; + private readonly CompilationStartAnalysisContext _inner; + +#pragma warning disable RS1012 // Start action has no registered actions + public BenchmarkCompilationStartAnalysisContext(BenchmarkAnalyzer analyzer, CompilationStartAnalysisContext inner) + : base(inner.Compilation, inner.Options, inner.CancellationToken) + { + _analyzer = analyzer; + _inner = inner; + } +#pragma warning restore RS1012 + + public override void RegisterCompilationEndAction(Action action) + { + _inner.RegisterCompilationEndAction(x => _analyzer.CompilationEndActions.Add(new ContextAndAction(x, action))); + } + + public override void RegisterSemanticModelAction(Action action) + { + _inner.RegisterSemanticModelAction(x => _analyzer.SemanticModelActions.Add(new ContextAndAction(x, action))); + } + + public override void RegisterSymbolAction(Action action, ImmutableArray symbolKinds) + { + _inner.RegisterSymbolAction( + x => _analyzer.SymbolActions.Add(new ContextAndAction(x, action)), symbolKinds); + } + + public override void RegisterCodeBlockStartAction(Action> action) + { + _inner.RegisterCodeBlockStartAction(x => + _analyzer.CodeBlockStartActions.Add( + new ContextAndAction>(x, action))); + } + + public override void RegisterCodeBlockAction(Action action) + { + _inner.RegisterCodeBlockAction(x => _analyzer.CodeBlockActions.Add(new ContextAndAction(x, action))); + } + + public override void RegisterSyntaxTreeAction(Action action) + { + _inner.RegisterSyntaxTreeAction(x => _analyzer.SyntaxTreeActions.Add(new ContextAndAction(x, action))); + } + + public override void RegisterSyntaxNodeAction(Action action, ImmutableArray syntaxKinds) + { + _inner.RegisterSyntaxNodeAction(x => _analyzer.SyntaxNodeActions.Add(new ContextAndAction(x, action)), syntaxKinds); + } + } } } }