Skip to content

Dipping toes into linker friendliness #24458

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

Merged
merged 8 commits into from
Aug 3, 2020
Merged

Conversation

davidfowl
Copy link
Member

@davidfowl davidfowl commented Jul 31, 2020

Experimenting with linker friendliness in ASP.NET Core. This investigation did lead to a single API change around the new overload of UseStartup that takes a func (it was changed a generic).

  • Annotate a couple of methods that do registration specifying a type or T
  • UseMiddleware
  • UseStartup
  • UseHub
  • MapHub

Here's an example of what this looks like today in aggressive mode https://github.com/rynowak/link-a-thon/blob/master/src/ApiTemplate/Linker.xml

@davidfowl davidfowl changed the title Dipping toes into linkerfriendliness Dipping toes into linker friendliness Jul 31, 2020
Copy link
Member

@JamesNK JamesNK left a comment

Choose a reason for hiding this comment

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

To properly certify asp.net core as linker friendly I think we need functional tests that run with linking enabled. This seems like an easy thing to unknowingly regress.

/// <summary>
/// Configure the connection to host the specified <see cref="Hub"/> type.
/// </summary>
/// <typeparam name="THub">The <see cref="Hub"/> type to host on the connection.</typeparam>
/// <param name="connectionBuilder">The connection to configure.</param>
/// <returns>The same instance of the <see cref="IConnectionBuilder"/> for chaining.</returns>
public static IConnectionBuilder UseHub<THub>(this IConnectionBuilder connectionBuilder) where THub : Hub
public static IConnectionBuilder UseHub<[DynamicallyAccessedMembers(HubAccessibility)]THub>(this IConnectionBuilder connectionBuilder) where THub : Hub
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, this should be done in gRPC.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes

Copy link
Member Author

Choose a reason for hiding this comment

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

@davidfowl
Copy link
Member Author

I think to properly certify asp.net core as linker friendly I think we need functional tests that run with linking enabled. This seems like an easy thing to unknowingly regress.

2 things:

  • I agree in the fullness of time we'll need ways to test this so we don't regress behavior
  • Aggressive mode isn't a default linker option and it's non-trivial to turn on so the stakes are super low.

This doesn't change any defaults but it allows us to make progress in understanding how to make the framework more linkable.

@Pilchie Pilchie added area-hosting area-signalr Includes: SignalR clients and servers labels Jul 31, 2020
@davidfowl davidfowl marked this pull request as ready for review August 2, 2020 03:17
@davidfowl
Copy link
Member Author

UseMiddleware is the most critical because we use it on our own components. The rest is user code which we would probably avoid trimming by default.

Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

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

These changes look good to me. Nice work.

Do you plan on having tests or analysis turned on in your build to ensure these don't get broken in the future?

@davidfowl
Copy link
Member Author

@eerhardt trying to decide if I should add a single test in our end to end tests that already publish bits instead of an individual tests.

@eerhardt
Copy link
Member

eerhardt commented Aug 2, 2020

trying to decide if I should add a single test in our end to end tests that already publish bits instead of an individual tests.

In a perfect world - I'd think both. But if you are choosing one, I'd choose end to end.

- The linker.xml preserves constructors all of the types that are registered in DI. This should be removed once we get the linker friendly DI changes.
@davidfowl
Copy link
Member Author

OK added a test. It uses a Linker.xml file to keep constructors of types in DI. Most of this file should be gone once we get dotnet/runtime#40227. The last thing looks like options dotnet/runtime#40236.

@marek-safar
Copy link
Contributor

@davidfowl it might be useful to enable linker warnings which would print if there are more cases to be fixed

@eerhardt
Copy link
Member

eerhardt commented Aug 3, 2020

it might be useful to enable linker warnings which would print if there are more cases to be fixed

For library authors (like ASP.NET here - and any library in dotnet/runtime that isn't part of the runtimepack) it would be useful to have an official linker option that runs the analysis/warnings on the whole library using the public surface area as the roots (like -r assembly does today).

That way library authors can easily tell which parts of their library aren't linker safe, and need to be fixed.

@davidfowl davidfowl merged commit 404d817 into master Aug 3, 2020
@davidfowl davidfowl deleted the davidfowl/linker-friendly branch August 3, 2020 13:54
@davidfowl
Copy link
Member Author

I'll submit a follow up PR with any remaining warnings. I really want to try this with @eerhardt 's DI changes to see how close we are to no annotations.

@@ -38,7 +38,7 @@ public virtual Task<PublishedApplication> Publish(DeploymentParameters deploymen
// avoids triggering builds of dependencies of the test app which could cause issues like https://github.com/dotnet/arcade/issues/2941
+ $" --no-dependencies"
+ $" /p:TargetArchitecture={deploymentParameters.RuntimeArchitecture}"
+ " --no-restore";
+ (deploymentParameters.RestoreDependencies ? "" : " --no-restore");
Copy link
Member

Choose a reason for hiding this comment

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

I recall no-restore is required for all tests on Helix because the test assets need to be pre-built before publishing to helix.

Copy link
Member Author

Choose a reason for hiding this comment

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

Works fine on helix as far as I could tell.

HaoK pushed a commit that referenced this pull request Aug 7, 2020
- Annotated UseMiddleware and UseStartup to preserve constructors and public methods.
- Annotated UseHub and MapHub preserve constructors and public methods.
- Added a test to verify UseStartup and UseMiddleware works
- The linker.xml preserves constructors all of the types that are registered in DI. This should be removed once we get the linker friendly DI changes.
@amcasey amcasey added area-hosting Includes Hosting area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Jun 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-hosting Includes Hosting area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions area-signalr Includes: SignalR clients and servers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants