Skip to content

Conversation

@javiercn
Copy link
Member

Due to the way we construct our DFA tree, several route patterns where there is a variable at the beginning of the route pattern in addition to a large set of different literals as the first segment of the route tree, results in massively large route tables (GB and more) many of them filled with nodes that we don't need.

The reason we don't need those nodes is because the literal they are hanging from won't match the constraint of the parameter or the shape of the complex parameter (or a constraint in a complex parameter part), hence even if we get to a candidate for that pattern, it will be discarded when we check constraints and complex parameters.

Instead of adding those nodes when building the DFA tree and evaluating the constraints and complex parameters on each request we evaluate the constraints and the complex parameters as we are building the DFA by evaluating the parent literal candidate against the constraint/complex parameter.

This results in DFAs with a much smaller number of nodes (several orders of magnitude depending on the case) and improves memory as well as startup time on these cases.

@ghost ghost added the area-runtime label Jun 21, 2021
Comment on lines 12 to 21
public interface ILiteralConstraint : IParameterPolicy
{
/// <summary>
/// Determines whether the given <paramref name="literal"/> can match the constraint.
/// </summary>
/// <param name="parameterName">The parameter name we are currently evaluating.</param>
/// <param name="literal">The literal to test the constraint against.</param>
/// <returns><c>true</c> if the literal contains a valid value; otherwise, <c>false</c>.</returns>
bool MatchLiteral(string parameterName, string literal);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Need to come up with a better name for this, in essence we want to implement this on our constraints and let people implement it too. Other names are IParameterNodeLiteralPolicy or IParameterNodeBuilderPolicy.

The idea here is that we pass literal values when we are building the DFA tree and you get to decide whether they match or not.

We also pass you the parameter name so that you can implement policies based on the parameter name even if you don't know the values ahead of time. For example, if the parameter name is controller or page, you can choose to never add any literal from the tree to mean something like, this parameter will never match any value from the list of literals in the tree.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm going to move this from the abstractions assembly to the implementation assembly, since this is mostly a DFA concern and rename it to IRouteParameterNodeFilterPolicy

@Tratcher
Copy link
Member

Issue #?

Who do you want to review this? I don't think Brennan or I have the context.

@javiercn
Copy link
Member Author

javiercn commented Jun 21, 2021

Issue #?

Who do you want to review this? I don't think Brennan or I have the context.

@Tratcher I've removed you from it. I'll ask James.

Here is the main issue:
#32781
Here are the related ones:
#23850
OData/AspNetCoreOData#160
#30092
#33735

[assembly: TypeForwardedTo(typeof(EndpointMetadataCollection))]
#pragma warning disable RS0016
[assembly: TypeForwardedTo(typeof(RouteValueDictionary))]
#pragma warning restore RS0016
Copy link
Member Author

Choose a reason for hiding this comment

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

VS and the build were complaining about this

Copy link
Member

Choose a reason for hiding this comment

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

Still true?

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.

A review focusing on code.

I'll wait until we've talked through this before thinking about the overall solution.

dougbu
dougbu previously requested changes Jul 23, 2021
Copy link
Contributor

@dougbu dougbu left a comment

Choose a reason for hiding this comment

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

New files need MIT license headers

@davidfowl
Copy link
Member

Is this change going in @javiercn ?

@javiercn
Copy link
Member Author

@davidfowl RC1

@javiercn
Copy link
Member Author

javiercn commented Aug 4, 2021

@davidfowl @JamesNK any further concern here?

I want to go through public API review with this today.

@javiercn javiercn added the api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews label Aug 4, 2021
@ghost
Copy link

ghost commented Aug 4, 2021

Thank you for your API proposal. I'm removing the api-ready-for-review label. API Proposals should be submitted for review through Issues based on this template.

@ghost ghost removed the api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews label Aug 4, 2021
@javiercn javiercn force-pushed the javiercn/routing-dfa-tree-trimming branch from 3bcb6a9 to 89bd1df Compare August 4, 2021 21:55
[assembly: TypeForwardedTo(typeof(EndpointMetadataCollection))]
#pragma warning disable RS0016
[assembly: TypeForwardedTo(typeof(RouteValueDictionary))]
#pragma warning restore RS0016
Copy link
Member

Choose a reason for hiding this comment

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

Still true?

Comment on lines 946 to 948
Copy link
Member

Choose a reason for hiding this comment

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

Record struct now available?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll check for this and try out removing the #pragma

@javiercn javiercn force-pushed the javiercn/routing-dfa-tree-trimming branch from b632ffb to 8fafc9f Compare August 4, 2021 23:01
@javiercn javiercn dismissed dougbu’s stale review August 5, 2021 12:20

Addressed feedback

@javiercn javiercn merged commit 014a284 into main Aug 5, 2021
@javiercn javiercn deleted the javiercn/routing-dfa-tree-trimming branch August 5, 2021 12:27
@ghost ghost added this to the 6.0-rc1 milestone Aug 5, 2021
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Aug 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants