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

Trimming Http in Blazor wasm #44534

Closed
CoffeeFlux opened this issue Nov 11, 2020 · 11 comments
Closed

Trimming Http in Blazor wasm #44534

CoffeeFlux opened this issue Nov 11, 2020 · 11 comments
Assignees
Labels
arch-wasm WebAssembly architecture area-System.Net.Http size-reduction Issues impacting final app size primary for size sensitive workloads
Milestone

Comments

@CoffeeFlux
Copy link
Contributor

CoffeeFlux commented Nov 11, 2020

System.Net.Http is one of the largest libraries in the Blazor sample, taking up 53KB when compressed with Brotli. Most of this space is held in the headers, most of which are not likely to be used. We should investigate some sort of feature flag here to try and get rid of this even if the linker cannot guarantee it will be unused.

The size grew also when http2 and http3 support was added for SocketHttpHandler which is not used and excluded for Browser and still the various caches and static data are populated.

@CoffeeFlux CoffeeFlux added arch-wasm WebAssembly architecture area-System.Net.Http labels Nov 11, 2020
@CoffeeFlux CoffeeFlux added this to the 6.0.0 milestone Nov 11, 2020
@ghost
Copy link

ghost commented Nov 11, 2020

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.


Issue meta data
Issue content: System.Net.Http is one of the largest libraries in the Blazor sample, taking up 53KB when compressed with Brotli. Most of this space is held in the headers, most of which are not likely to be used. We should investigate some sort of feature flag here to try and get rid of this even if the linker cannot guarantee it will be unused.
Issue author: CoffeeFlux
Assignees: -
Milestone: [object Object]

@CoffeeFlux CoffeeFlux added the linkable-framework Issues associated with delivering a linker friendly framework label Nov 16, 2020
@marek-safar marek-safar added size-reduction Issues impacting final app size primary for size sensitive workloads and removed linkable-framework Issues associated with delivering a linker friendly framework labels Dec 9, 2020
@stephentoub
Copy link
Member

The vast majority of that code is around header validation, e.g. when you set HttpRequestHeaders.From on a message, it validating that it's a well-formed email address. I think the flag here will basically need to be "I don't care about header validation at the HttpClient layer", at which point I'd expect a significant portion of the header logic could be trimmable away.

Alternatively, we could simply say that for the Blazor wasm build we don't layer on much special validation, and simply have a different implementation that effectively ifdefs away all of that code. More specifically, much of it ends up being kept because of the parsers defined in the known headers here:
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs
We would tweak that for the wasm build to just always use a generic parser, or something like that.

cc: @geoffkizer

@eerhardt
Copy link
Member

eerhardt commented Apr 6, 2021

@geoffkizer @wfurt @scalablecory @dotnet/ncl - anyone have any thoughts on the above? Would either of these approaches be acceptable in browser-wasm (and potentially mobile) builds?

@geoffkizer
Copy link
Contributor

We can't rip out the header parsers/validators in general without removing strongly typed header properties as well, which I assume we don't want to do....

Is there a way to see details on what methods account for what space, etc?

@eerhardt
Copy link
Member

eerhardt commented Apr 6, 2021

Is there a way to see details on what methods account for what space, etc?

You can use the following steps to trim a default Blazor WASM app:

  1. Get the latest 6.0 SDK and put it on your $PATH
  2. Create a HelloWorld directory and cd into it
  3. dotnet new blazorwasm
  4. dotnet publish -c Release
  5. Inspect the .dlls in HelloWorld\bin\Release\net6.0\publish\wwwroot\_framework. You'll see the System.Net.Http.dll is the 3rd largest after CoreLib and System.Text.Json. Currently around 136 KB. Typically I use ILSpy or similar to inspect what is left in the assembly.

When I do this, here is what is left:

image

Analyze these classes and decide whether each is completely necessary in a browser-wasm app.

@geoffkizer
Copy link
Contributor

The HPACK and QPACK stuff is HTTP2/3 specific and could be removed, though I expect there's some trickiness with the KnownHeaders stuff that makes this a bit painful.

I don't know what TaskToApm is used for; we could investigate this but I doubt it's much code.

As for the rest, I don't see much that can be removed, unfortunately.

@stephentoub
Copy link
Member

We can't rip out the header parsers/validators in general without removing strongly typed header properties as well, which I assume we don't want to do...

I was thinking we could consider weakening the validation. For example, there's a ton of code purely to validate that From headers are properly formatted as email addresses. Do we need all of that for wasm?

@geoffkizer
Copy link
Contributor

I was thinking we could consider weakening the validation. For example, there's a ton of code purely to validate that From headers are properly formatted as email addresses. Do we need all of that for wasm?

Maybe not.

To what extent do we care about behavioral differences here?

Alternatively, to what extent do we really care about validation of From headers even in non-wasm scenarios?

@stephentoub
Copy link
Member

Alternatively, to what extent do we really care about validation of From headers even in non-wasm scenarios?

Personally? Very little 😉

Just for context, changing:

public static readonly KnownHeader From = new KnownHeader("From", HttpHeaderType.Request, GenericHeaderParser.MailAddressParser, null, H2StaticTable.From);

to pass null as the parser, and deleting this line:
internal static readonly GenericHeaderParser MailAddressParser = new GenericHeaderParser(false, ParseMailAddress);

shrinks the size of System.Net.Http.dll in the default blazor wasm template by 7K uncompressed and 2K compressed.

eerhardt added a commit to eerhardt/runtime that referenced this issue May 6, 2021
This allows for HPackEncoder and QPackEncoder to be trimmed in browser wasm.

Contributes to dotnet#44534
eerhardt added a commit that referenced this issue May 10, 2021
* Remove the HTTP2 and HTTP3 implementations on browser-wasm.

This allows for HPackEncoder and QPackEncoder to be trimmed in browser wasm.

Contributes to #44534
eerhardt added a commit to eerhardt/runtime that referenced this issue May 10, 2021
Introduce a new feature switch: System.Net.Http.MinimalHeaderValidation. When set to `true`, this switch will allow for trimming header parsing logic that may not be needed in the app.

Contributes to dotnet#44534
@eerhardt
Copy link
Member

I opened #52572 for @stephentoub's proposal above, in case anyone is interested in taking a look.

After that idea and #52420, I'm not seeing much more than can be trimmed from System.Net.Http, unfortunately.

@eerhardt eerhardt self-assigned this May 11, 2021
eerhardt added a commit to eerhardt/runtime that referenced this issue May 12, 2021
eerhardt added a commit that referenced this issue May 13, 2021
@eerhardt
Copy link
Member

After #52420, #52681, and #52794, I believe all the trimmable code has been removed from System.Net.Http. Closing.

@ghost ghost locked as resolved and limited conversation to collaborators Jun 18, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly architecture area-System.Net.Http size-reduction Issues impacting final app size primary for size sensitive workloads
Projects
None yet
Development

No branches or pull requests

5 participants