Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permformance issue with StaticAssetDevelopmentRuntimeHandler.EnableSupport. #59673

Open
maliming opened this issue Jan 1, 2025 · 0 comments
Open
Labels
area-blazor Includes: Blazor, Razor Components

Comments

@maliming
Copy link

maliming commented Jan 1, 2025

When StaticAssetDevelopmentRuntimeHandler.EnableSupport is enabled in the development environment, websites with many static resources may experience significant delays.

The delay occurs primarily during the first request due to an O(n^2) loop in the UpdateEndpoints process.

Each static resource endpoint builder invokes the AttachRuntimePatching method and then the FindOriginalAsset method to iterate through all descriptors.

If there are 10,000 static files(js/css/images) under the wwwroot folder, this leads to 10,000 x 10,000 iterations on the first request.

Thanks.

if (StaticAssetDevelopmentRuntimeHandler.IsEnabled(result.IsBuildManifest, endpoints.ServiceProvider))
{
StaticAssetDevelopmentRuntimeHandler.EnableSupport(endpoints, result, environment, result.Descriptors);
}

private void UpdateEndpoints()
{
lock (_lock)
{
var endpoints = new List<Endpoint>();
foreach (var asset in _descriptors)
{
// At this point the descriptor becomes immutable.
asset.Freeze();
endpoints.Add(_endpointFactory.Create(asset, _conventions, _finallyConventions));
}
var oldCancellationTokenSource = _cancellationTokenSource;
_endpoints = endpoints;
_cancellationTokenSource = new CancellationTokenSource();
_changeToken = new CancellationChangeToken(_cancellationTokenSource.Token);
oldCancellationTokenSource?.Cancel();
oldCancellationTokenSource?.Dispose();
}
}

public void AttachRuntimePatching(EndpointBuilder builder)
{
var original = builder.RequestDelegate!;
var asset = builder.Metadata.OfType<StaticAssetDescriptor>().Single();
if (asset.HasContentEncoding())
{
// This is a compressed asset, which might get out of "sync" with the original uncompressed version.
// We are going to find the original by using the weak etag from this compressed asset and locating an asset with the same etag.
var eTag = asset.GetWeakETag();
asset = FindOriginalAsset(eTag.Tag.Value!, descriptors);

private static StaticAssetDescriptor FindOriginalAsset(string tag, List<StaticAssetDescriptor> descriptors)
{
for (var i = 0; i < descriptors.Count; i++)
{
if (descriptors[i].HasETag(tag))
{
return descriptors[i];
}
}
throw new InvalidOperationException("The original asset was not found.");
}

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Jan 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

No branches or pull requests

1 participant