Fire an ETW event when the background document generator queue is empty, after doing some work

This commit is contained in:
David Wengier 2024-11-20 16:09:52 +11:00
Родитель 7390745dcd
Коммит 69388cdace
3 изменённых файлов: 40 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Diagnostics.Tracing;
namespace Microsoft.AspNetCore.Razor;
[EventSource(Name = "RazorEventSource")]
internal sealed class RazorEventSource : EventSource
{
public static readonly RazorEventSource Instance = new();
private RazorEventSource()
{
}
[Event(1, Level = EventLevel.Informational)]
public void BackgroundDocumentGeneratorIdle() => WriteEvent(1);
}

Просмотреть файл

@ -31,6 +31,15 @@ namespace Microsoft.AspNetCore.Razor.Utilities;
/// </summary>
internal class AsyncBatchingWorkQueue<TItem, TResult>
{
/// <summary>
/// Fired when all batches have finished being processed, and the queue is waiting for an AddWork call.
/// </summary>
/// <remarks>
/// This is a best-effort signal with no guarantee that more work won't be queued, and hence the queue
/// going non-idle, immediately after (or during!) the event firing.
/// </remarks>
public event EventHandler? Idle;
/// <summary>
/// Delay we wait after finishing the processing of one batch and starting up on then.
/// </summary>
@ -210,7 +219,17 @@ internal class AsyncBatchingWorkQueue<TItem, TResult>
// then reset that bool back to false
await Task.Yield().ConfigureAwait(false);
await Task.Delay(_delay, _entireQueueCancellationToken).ConfigureAwait(false);
return await ProcessNextBatchAsync().ConfigureAwait(false);
var result = await ProcessNextBatchAsync().ConfigureAwait(false);
// Not worried about the lock here because we don't want to fire the event under the lock, which means
// there is no effective way to avoid a race. The event doesn't guarantee that there will never be any
// more work anyway, it's merely a best effort.
if (_nextBatch.Count == 0)
{
Idle?.Invoke(this, EventArgs.Empty);
}
return result;
}
}

Просмотреть файл

@ -55,6 +55,7 @@ internal partial class BackgroundDocumentGenerator : IRazorStartupService, IDisp
_disposeTokenSource = new();
_workQueue = new AsyncBatchingWorkQueue<(IProjectSnapshot, IDocumentSnapshot)>(delay, ProcessBatchAsync, _disposeTokenSource.Token);
_workQueue.Idle += (_, _) => RazorEventSource.Instance.BackgroundDocumentGeneratorIdle();
_suppressedDocuments = ImmutableHashSet<string>.Empty.WithComparer(FilePathComparer.Instance);
_projectManager.Changed += ProjectManager_Changed;
}