Skip to content

[StaticWebAssets] Process collection properties with amortized allocation #49682

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

javiercn
Copy link
Member

@javiercn javiercn commented Jul 8, 2025

  • Introduces methods for populating existing collections of values.
  • Reuses well-known values during serialization and deserialization.

Performance Results by Component

1. StaticWebAssetEndpointProperty Benchmarks

.NET 10.0 Results

Method Mean Error StdDev Gen0 Allocated Performance
FromMetadataValue_Current 651.8 ns 4.64 ns 4.12 ns 0.0372 952 B Baseline
PopulateFromMetadataValue_New 285.2 ns 1.48 ns 1.31 ns 0.0067 168 B 56% Faster
ToMetadataValue_Current 254.6 ns 1.07 ns 0.95 ns 0.0105 264 B Baseline
ToMetadataValue_New 211.9 ns 2.78 ns 2.60 ns 0.0105 264 B 17% Faster

.NET Framework 4.8.1 Results

Method Mean Error StdDev Gen0 Allocated Performance
FromMetadataValue_Current 2,493.7 ns 25.82 ns 22.89 ns 0.1564 987 B Baseline
PopulateFromMetadataValue_New 1,486.6 ns 8.64 ns 7.66 ns 0.0267 177 B 40% Faster
ToMetadataValue_Current 1,014.8 ns 5.54 ns 4.91 ns 0.0420 273 B Baseline
ToMetadataValue_New 947.4 ns 18.20 ns 15.19 ns 0.0429 273 B 7% Faster

2. StaticWebAssetEndpointResponseHeader Benchmarks

.NET 10.0 Results

Method Mean Error StdDev Gen0 Allocated Performance
FromMetadataValue_Current 1,929.1 ns 33.32 ns 29.54 ns 0.0725 1896 B Baseline
PopulateFromMetadataValue_New 851.0 ns 10.57 ns 8.82 ns 0.0057 160 B 56% Faster
ToMetadataValue_Current 745.6 ns 2.71 ns 2.53 ns 0.0296 752 B Baseline
ToMetadataValue_New 637.3 ns 2.51 ns 2.35 ns 0.0296 752 B 15% Faster

.NET Framework 4.8.1 Results

Method Mean Error StdDev Gen0 Allocated Performance
FromMetadataValue_Current 8.204 us 0.0517 us 0.0458 us 0.3052 2014 B Baseline
PopulateFromMetadataValue_New 4.922 us 0.0817 us 0.0973 us 0.0229 177 B 40% Faster
ToMetadataValue_Current 2.946 us 0.0271 us 0.0253 us 0.1183 762 B Baseline
ToMetadataValue_New 2.838 us 0.0247 us 0.0231 us 0.1183 762 B 4% Faster

3. StaticWebAssetEndpointSelector Benchmarks

.NET 10.0 Results

Method Mean Error StdDev Gen0 Allocated Performance
FromMetadataValue_Current 845.8 ns 11.52 ns 10.22 ns 0.0410 1040 B Baseline
PopulateFromMetadataValue_New 339.2 ns 1.86 ns 1.65 ns 0.0033 88 B 60% Faster
ToMetadataValue_Current 316.0 ns 2.26 ns 2.00 ns 0.0110 280 B Baseline
ToMetadataValue_New 283.0 ns 2.45 ns 2.29 ns 0.0110 280 B 10% Faster

.NET Framework 4.8.1 Results

Method Mean Error StdDev Gen0 Allocated Performance
FromMetadataValue_Current 3.131 us 0.0616 us 0.0633 us 0.1678 1075 B Baseline
PopulateFromMetadataValue_New 1.838 us 0.0136 us 0.0114 us 0.0134 88 B 41% Faster
ToMetadataValue_Current 1.192 us 0.0048 us 0.0040 us 0.0458 289 B Baseline
ToMetadataValue_New 1.131 us 0.0127 us 0.0112 us 0.0458 289 B 5% Faster

@github-actions github-actions bot added the Area-AspNetCore RazorSDK, BlazorWebAssemblySDK, dotnet-watch label Jul 8, 2025
Copy link
Contributor

Thanks for your PR, @@javiercn.
To learn about the PR process and branching schedule of this repo, please take a look at the SDK PR Guide.


namespace System.Buffers;

internal sealed class PooledArrayBufferWriter<T> : IBufferWriter<T>, IDisposable
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was "lifted" from ASP.NET Core

@javiercn javiercn force-pushed the javiercn/improve-json-allocs branch from 3ab44b5 to bc59fb1 Compare July 8, 2025 16:20
@javiercn javiercn marked this pull request as ready for review July 8, 2025 22:31
@javiercn javiercn requested a review from a team as a code owner July 8, 2025 22:31
@javiercn javiercn force-pushed the javiercn/improve-json-allocs branch 2 times, most recently from 38a718b to 0bbc810 Compare July 8, 2025 22:42
…tions

This change significantly improves performance of static web asset endpoint processing by optimizing JSON serialization and deserialization operations:

Key optimizations:
- Added reusable List<T> collections to eliminate repeated allocations
- Implemented JsonWriterContext for efficient JSON serialization with buffer reuse
- Added string interning for well-known header names, selector names, and property values
- Introduced direct string property setters to bypass expensive array recreations
- Used ArrayPool and stack allocation for UTF-8 encoding buffers
- Added optimized PopulateFromMetadataValue methods that populate existing lists

Performance improvements (typical):
- FromMetadataValue operations: 40-60% faster, 80-90% less memory allocation
- ToMetadataValue operations: 5-17% faster with same memory usage
- StaticWebAssetEndpointProperty: 56% faster deserialization, 17% faster serialization
- StaticWebAssetEndpointResponseHeader: 56% faster deserialization, 15% faster serialization
- StaticWebAssetEndpointSelector: 60% faster deserialization, 10% faster serialization

These optimizations reduce build-time overhead when processing large numbers of static web assets in ASP.NET Core applications.
@javiercn javiercn force-pushed the javiercn/improve-json-allocs branch from 0bbc810 to 67f679f Compare July 8, 2025 22:42
@javiercn javiercn requested a review from MackinnonBuck July 8, 2025 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-AspNetCore RazorSDK, BlazorWebAssemblySDK, dotnet-watch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant