Skip to content

Commit 0c06046

Browse files
authored
Merge pull request #56182 from dotnet/merges/release/dev17.0-to-release/dev17.0-vs-deps
Merge release/dev17.0 to release/dev17.0-vs-deps
2 parents cd52244 + d1ba282 commit 0c06046

File tree

8 files changed

+165
-21
lines changed

8 files changed

+165
-21
lines changed

src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,8 @@ private DriverStateTable.Builder GetBuilder(DriverStateTable previous)
408408
ImmutableArray<AdditionalText>.Empty,
409409
ImmutableArray<GeneratorState>.Empty,
410410
previous,
411-
disabledOutputs: IncrementalGeneratorOutputKind.None);
411+
disabledOutputs: IncrementalGeneratorOutputKind.None,
412+
runtime: TimeSpan.Zero);
412413

413414
return new DriverStateTable.Builder(c, state, ImmutableArray<ISyntaxInputNode>.Empty);
414415
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Diagnostics.Tracing;
7+
using Roslyn.Utilities;
8+
9+
namespace Microsoft.CodeAnalysis
10+
{
11+
[EventSource(Name = "Microsoft-CodeAnalysis-General")]
12+
internal sealed class CodeAnalysisEventSource : EventSource
13+
{
14+
public static readonly CodeAnalysisEventSource Log = new CodeAnalysisEventSource();
15+
16+
public static class Keywords
17+
{
18+
public const EventKeywords Performance = (EventKeywords)1;
19+
}
20+
21+
public static class Tasks
22+
{
23+
public const EventTask GeneratorDriverRunTime = (EventTask)1;
24+
public const EventTask SingleGeneratorRunTime = (EventTask)2;
25+
}
26+
27+
private CodeAnalysisEventSource() { }
28+
29+
[Event(1, Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.GeneratorDriverRunTime)]
30+
internal void StartGeneratorDriverRunTime(string id) => WriteEvent(1, id);
31+
32+
[Event(2, Message = "Generators ran for {0} ticks", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.GeneratorDriverRunTime)]
33+
internal void StopGeneratorDriverRunTime(long elapsedTicks, string id) => WriteEvent(2, elapsedTicks, id);
34+
35+
[Event(3, Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.SingleGeneratorRunTime)]
36+
internal void StartSingleGeneratorRunTime(string generatorName, string assemblyPath, string id) => WriteEvent(3, generatorName, assemblyPath, id);
37+
38+
[Event(4, Message = "Generator {0} ran for {2} ticks", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.SingleGeneratorRunTime)]
39+
internal void StopSingleGeneratorRunTime(string generatorName, string assemblyPath, long elapsedTicks, string id) => WriteEvent(4, generatorName, assemblyPath, elapsedTicks, id);
40+
}
41+
}

src/Compilers/Core/Portable/DiagnosticAnalyzer/DefaultAnalyzerAssemblyLoader.Core.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ internal class DefaultAnalyzerAssemblyLoader : AnalyzerAssemblyLoader
4040
"System.Console",
4141
"System.Diagnostics.Debug",
4242
"System.Diagnostics.StackTrace",
43+
"System.Diagnostics.Tracing",
4344
"System.IO.Compression",
4445
"System.IO.FileSystem",
4546
"System.Linq",

src/Compilers/Core/Portable/SourceGeneration/GeneratorDriver.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ internal GeneratorDriver(GeneratorDriverState state)
3636
internal GeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, AnalyzerConfigOptionsProvider optionsProvider, ImmutableArray<AdditionalText> additionalTexts, GeneratorDriverOptions driverOptions)
3737
{
3838
(var filteredGenerators, var incrementalGenerators) = GetIncrementalGenerators(generators, SourceExtension);
39-
_state = new GeneratorDriverState(parseOptions, optionsProvider, filteredGenerators, incrementalGenerators, additionalTexts, ImmutableArray.Create(new GeneratorState[filteredGenerators.Length]), DriverStateTable.Empty, driverOptions.DisabledOutputs);
39+
_state = new GeneratorDriverState(parseOptions, optionsProvider, filteredGenerators, incrementalGenerators, additionalTexts, ImmutableArray.Create(new GeneratorState[filteredGenerators.Length]), DriverStateTable.Empty, driverOptions.DisabledOutputs, runtime: TimeSpan.Zero);
4040
}
4141

4242
public GeneratorDriver RunGenerators(Compilation compilation, CancellationToken cancellationToken = default)
@@ -135,8 +135,9 @@ public GeneratorDriverRunResult GetRunResult()
135135
=> new GeneratorRunResult(generator,
136136
diagnostics: generatorState.Diagnostics,
137137
exception: generatorState.Exception,
138-
generatedSources: getGeneratorSources(generatorState)));
139-
return new GeneratorDriverRunResult(results);
138+
generatedSources: getGeneratorSources(generatorState),
139+
elapsedTime: generatorState.ElapsedTime));
140+
return new GeneratorDriverRunResult(results, _state.RunTime);
140141

141142
static ImmutableArray<GeneratedSourceResult> getGeneratorSources(GeneratorState generatorState)
142143
{
@@ -158,10 +159,11 @@ internal GeneratorDriverState RunGeneratorsCore(Compilation compilation, Diagnos
158159
// with no generators, there is no work to do
159160
if (_state.Generators.IsEmpty)
160161
{
161-
return _state.With(stateTable: DriverStateTable.Empty);
162+
return _state.With(stateTable: DriverStateTable.Empty, runTime: TimeSpan.Zero);
162163
}
163164

164165
// run the actual generation
166+
using var timer = CodeAnalysisEventSource.Log.CreateGeneratorDriverRunTimer();
165167
var state = _state;
166168
var stateBuilder = ArrayBuilder<GeneratorState>.GetInstance(state.Generators.Length);
167169
var constantSourcesBuilder = ArrayBuilder<SyntaxTree>.GetInstance();
@@ -244,21 +246,22 @@ internal GeneratorDriverState RunGeneratorsCore(Compilation compilation, Diagnos
244246
continue;
245247
}
246248

249+
using var generatorTimer = CodeAnalysisEventSource.Log.CreateSingleGeneratorRunTimer(state.Generators[i]);
247250
try
248251
{
249252
var context = UpdateOutputs(generatorState.OutputNodes, IncrementalGeneratorOutputKind.Source | IncrementalGeneratorOutputKind.Implementation, cancellationToken, driverStateBuilder);
250253
(var sources, var generatorDiagnostics) = context.ToImmutableAndFree();
251254
generatorDiagnostics = FilterDiagnostics(compilation, generatorDiagnostics, driverDiagnostics: diagnosticsBag, cancellationToken);
252255

253-
stateBuilder[i] = new GeneratorState(generatorState.Info, generatorState.PostInitTrees, generatorState.InputNodes, generatorState.OutputNodes, ParseAdditionalSources(state.Generators[i], sources, cancellationToken), generatorDiagnostics);
256+
stateBuilder[i] = new GeneratorState(generatorState.Info, generatorState.PostInitTrees, generatorState.InputNodes, generatorState.OutputNodes, ParseAdditionalSources(state.Generators[i], sources, cancellationToken), generatorDiagnostics, generatorTimer.Elapsed);
254257
}
255258
catch (UserFunctionException ufe)
256259
{
257-
stateBuilder[i] = SetGeneratorException(MessageProvider, stateBuilder[i], state.Generators[i], ufe.InnerException, diagnosticsBag);
260+
stateBuilder[i] = SetGeneratorException(MessageProvider, stateBuilder[i], state.Generators[i], ufe.InnerException, diagnosticsBag, generatorTimer.Elapsed);
258261
}
259262
}
260263

261-
state = state.With(stateTable: driverStateBuilder.ToImmutable(), generatorStates: stateBuilder.ToImmutableAndFree());
264+
state = state.With(stateTable: driverStateBuilder.ToImmutable(), generatorStates: stateBuilder.ToImmutableAndFree(), runTime: timer.Elapsed);
262265
return state;
263266
}
264267

@@ -290,7 +293,7 @@ private ImmutableArray<GeneratedSyntaxTree> ParseAdditionalSources(ISourceGenera
290293
return trees.ToImmutableAndFree();
291294
}
292295

293-
private static GeneratorState SetGeneratorException(CommonMessageProvider provider, GeneratorState generatorState, ISourceGenerator generator, Exception e, DiagnosticBag? diagnosticBag, bool isInit = false)
296+
private static GeneratorState SetGeneratorException(CommonMessageProvider provider, GeneratorState generatorState, ISourceGenerator generator, Exception e, DiagnosticBag? diagnosticBag, TimeSpan? runTime = null, bool isInit = false)
294297
{
295298
var errorCode = isInit ? provider.WRN_GeneratorFailedDuringInitialization : provider.WRN_GeneratorFailedDuringGeneration;
296299

@@ -313,7 +316,7 @@ private static GeneratorState SetGeneratorException(CommonMessageProvider provid
313316
var diagnostic = Diagnostic.Create(descriptor, Location.None, generator.GetGeneratorType().Name, e.GetType().Name, e.Message);
314317

315318
diagnosticBag?.Add(diagnostic);
316-
return new GeneratorState(generatorState.Info, e, diagnostic);
319+
return new GeneratorState(generatorState.Info, e, diagnostic, runTime ?? TimeSpan.Zero);
317320
}
318321

319322
private static ImmutableArray<Diagnostic> FilterDiagnostics(Compilation compilation, ImmutableArray<Diagnostic> generatorDiagnostics, DiagnosticBag? driverDiagnostics, CancellationToken cancellationToken)

src/Compilers/Core/Portable/SourceGeneration/GeneratorDriverState.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Collections.Immutable;
67
using System.Diagnostics;
78
using Microsoft.CodeAnalysis.Diagnostics;
@@ -17,7 +18,8 @@ internal GeneratorDriverState(ParseOptions parseOptions,
1718
ImmutableArray<AdditionalText> additionalTexts,
1819
ImmutableArray<GeneratorState> generatorStates,
1920
DriverStateTable stateTable,
20-
IncrementalGeneratorOutputKind disabledOutputs)
21+
IncrementalGeneratorOutputKind disabledOutputs,
22+
TimeSpan runtime)
2123
{
2224
Generators = sourceGenerators;
2325
IncrementalGenerators = incrementalGenerators;
@@ -27,6 +29,7 @@ internal GeneratorDriverState(ParseOptions parseOptions,
2729
OptionsProvider = optionsProvider;
2830
StateTable = stateTable;
2931
DisabledOutputs = disabledOutputs;
32+
RunTime = runtime;
3033
Debug.Assert(Generators.Length == GeneratorStates.Length);
3134
Debug.Assert(IncrementalGenerators.Length == GeneratorStates.Length);
3235
}
@@ -80,6 +83,8 @@ internal GeneratorDriverState(ParseOptions parseOptions,
8083
/// </summary>
8184
internal readonly IncrementalGeneratorOutputKind DisabledOutputs;
8285

86+
internal readonly TimeSpan RunTime;
87+
8388
internal GeneratorDriverState With(
8489
ImmutableArray<ISourceGenerator>? sourceGenerators = null,
8590
ImmutableArray<IIncrementalGenerator>? incrementalGenerators = null,
@@ -88,7 +93,8 @@ internal GeneratorDriverState With(
8893
DriverStateTable? stateTable = null,
8994
ParseOptions? parseOptions = null,
9095
AnalyzerConfigOptionsProvider? optionsProvider = null,
91-
IncrementalGeneratorOutputKind? disabledOutputs = null)
96+
IncrementalGeneratorOutputKind? disabledOutputs = null,
97+
TimeSpan? runTime = null)
9298
{
9399
return new GeneratorDriverState(
94100
parseOptions ?? this.ParseOptions,
@@ -98,7 +104,8 @@ internal GeneratorDriverState With(
98104
additionalTexts ?? this.AdditionalTexts,
99105
generatorStates ?? this.GeneratorStates,
100106
stateTable ?? this.StateTable,
101-
disabledOutputs ?? this.DisabledOutputs
107+
disabledOutputs ?? this.DisabledOutputs,
108+
runTime ?? this.RunTime
102109
);
103110
}
104111
}

src/Compilers/Core/Portable/SourceGeneration/GeneratorState.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,27 @@ public GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> po
3232
/// Creates a new generator state that contains information, constant trees and an execution pipeline
3333
/// </summary>
3434
public GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> postInitTrees, ImmutableArray<ISyntaxInputNode> inputNodes, ImmutableArray<IIncrementalGeneratorOutputNode> outputNodes)
35-
: this(info, postInitTrees, inputNodes, outputNodes, ImmutableArray<GeneratedSyntaxTree>.Empty, ImmutableArray<Diagnostic>.Empty, exception: null)
35+
: this(info, postInitTrees, inputNodes, outputNodes, ImmutableArray<GeneratedSyntaxTree>.Empty, ImmutableArray<Diagnostic>.Empty, exception: null, elapsedTime: TimeSpan.Zero)
3636
{
3737
}
3838

3939
/// <summary>
4040
/// Creates a new generator state that contains an exception and the associated diagnostic
4141
/// </summary>
42-
public GeneratorState(GeneratorInfo info, Exception e, Diagnostic error)
43-
: this(info, ImmutableArray<GeneratedSyntaxTree>.Empty, ImmutableArray<ISyntaxInputNode>.Empty, ImmutableArray<IIncrementalGeneratorOutputNode>.Empty, ImmutableArray<GeneratedSyntaxTree>.Empty, ImmutableArray.Create(error), exception: e)
42+
public GeneratorState(GeneratorInfo info, Exception e, Diagnostic error, TimeSpan elapsedTime)
43+
: this(info, ImmutableArray<GeneratedSyntaxTree>.Empty, ImmutableArray<ISyntaxInputNode>.Empty, ImmutableArray<IIncrementalGeneratorOutputNode>.Empty, ImmutableArray<GeneratedSyntaxTree>.Empty, ImmutableArray.Create(error), exception: e, elapsedTime)
4444
{
4545
}
4646

4747
/// <summary>
4848
/// Creates a generator state that contains results
4949
/// </summary>
50-
public GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> postInitTrees, ImmutableArray<ISyntaxInputNode> inputNodes, ImmutableArray<IIncrementalGeneratorOutputNode> outputNodes, ImmutableArray<GeneratedSyntaxTree> generatedTrees, ImmutableArray<Diagnostic> diagnostics)
51-
: this(info, postInitTrees, inputNodes, outputNodes, generatedTrees, diagnostics, exception: null)
50+
public GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> postInitTrees, ImmutableArray<ISyntaxInputNode> inputNodes, ImmutableArray<IIncrementalGeneratorOutputNode> outputNodes, ImmutableArray<GeneratedSyntaxTree> generatedTrees, ImmutableArray<Diagnostic> diagnostics, TimeSpan elapsedTime)
51+
: this(info, postInitTrees, inputNodes, outputNodes, generatedTrees, diagnostics, exception: null, elapsedTime)
5252
{
5353
}
5454

55-
private GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> postInitTrees, ImmutableArray<ISyntaxInputNode> inputNodes, ImmutableArray<IIncrementalGeneratorOutputNode> outputNodes, ImmutableArray<GeneratedSyntaxTree> generatedTrees, ImmutableArray<Diagnostic> diagnostics, Exception? exception)
55+
private GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> postInitTrees, ImmutableArray<ISyntaxInputNode> inputNodes, ImmutableArray<IIncrementalGeneratorOutputNode> outputNodes, ImmutableArray<GeneratedSyntaxTree> generatedTrees, ImmutableArray<Diagnostic> diagnostics, Exception? exception, TimeSpan elapsedTime)
5656
{
5757
this.Initialized = true;
5858
this.PostInitTrees = postInitTrees;
@@ -62,6 +62,7 @@ private GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> p
6262
this.Info = info;
6363
this.Diagnostics = diagnostics;
6464
this.Exception = exception;
65+
this.ElapsedTime = elapsedTime;
6566
}
6667

6768
internal bool Initialized { get; }
@@ -78,6 +79,8 @@ private GeneratorState(GeneratorInfo info, ImmutableArray<GeneratedSyntaxTree> p
7879

7980
internal Exception? Exception { get; }
8081

82+
internal TimeSpan ElapsedTime { get; }
83+
8184
internal ImmutableArray<Diagnostic> Diagnostics { get; }
8285
}
8386
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Diagnostics.Tracing;
8+
using System.Text;
9+
using Roslyn.Utilities;
10+
using static Microsoft.CodeAnalysis.CodeAnalysisEventSource;
11+
12+
namespace Microsoft.CodeAnalysis
13+
{
14+
internal static class GeneratorTimerExtensions
15+
{
16+
public static RunTimer CreateGeneratorDriverRunTimer(this CodeAnalysisEventSource eventSource)
17+
{
18+
if (eventSource.IsEnabled(EventLevel.Informational, Keywords.Performance))
19+
{
20+
var id = Guid.NewGuid().ToString();
21+
eventSource.StartGeneratorDriverRunTime(id);
22+
return new RunTimer(t => eventSource.StopGeneratorDriverRunTime(t.Ticks, id));
23+
}
24+
else
25+
{
26+
return new RunTimer();
27+
}
28+
}
29+
30+
public static RunTimer CreateSingleGeneratorRunTimer(this CodeAnalysisEventSource eventSource, ISourceGenerator generator)
31+
{
32+
if (eventSource.IsEnabled(EventLevel.Informational, Keywords.Performance))
33+
{
34+
var id = Guid.NewGuid().ToString();
35+
var type = generator.GetGeneratorType();
36+
eventSource.StartSingleGeneratorRunTime(type.FullName!, type.Assembly.Location, id);
37+
return new RunTimer(t => eventSource.StopSingleGeneratorRunTime(type.FullName!, type.Assembly.Location, t.Ticks, id));
38+
}
39+
else
40+
{
41+
return new RunTimer();
42+
}
43+
}
44+
45+
internal readonly struct RunTimer : IDisposable
46+
{
47+
private readonly SharedStopwatch _timer;
48+
private readonly Action<TimeSpan>? _callback;
49+
50+
public TimeSpan Elapsed => _timer.Elapsed;
51+
52+
public RunTimer()
53+
{
54+
// start twice to improve accuracy. See AnalyzerExecutor.ExecuteAndCatchIfThrows for more details
55+
_ = SharedStopwatch.StartNew();
56+
_timer = SharedStopwatch.StartNew();
57+
_callback = null;
58+
}
59+
60+
public RunTimer(Action<TimeSpan> callback)
61+
: this()
62+
{
63+
_callback = callback;
64+
}
65+
66+
public void Dispose()
67+
{
68+
if (_callback is not null)
69+
{
70+
var elapsed = _timer.Elapsed;
71+
_callback(elapsed);
72+
}
73+
}
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)