Affects: 4.3.x and 5.x


When request mapping URLs have path variables (e.g. /api/fetchbyid/{id}) and if a component has thousands of request mapping, Spring handler matching logic loop over all request mappings in the component. Although Spring handler logic breaks loop on first match (rightfully so), it can be pretty costly operation if the incoming url is at the bottom of natural ordering (e.g. /api/z/fetchbyid/{id}).

Due to this, there is atleast 20 to 30% cost added to rest calls with path variables

Although path variable based match has to be dynamic, logic to match request mapping can be improved by maintaining static part of the request mapping url in a lookup map. This is explained below

Say there are 26 urls mappings in a component as shown below

/api/a/fetchbyid/{id} /api/b/fetchbyid/{id} …….. /api/z/fetchbyid/{id}

Current logic loops over all 26 mappings to identify the handler method. Instead a partial match url Map can be maintained which can store mapping for the keys (/api/a/fetchbyid, /api/b/fetchbyid, /api/z/fetchbyid), so when a incoming URL matches the partial keys, use those mappings to identify the actual match. in the above example, it would be 1 URL mapping (/api/z/fetchbyid) to match, instead of 26. Partial lookup url map keys can be identified by chopping first occurrence of path variable and store the static part of the url as key in the new lookup Map.

Comment From: rstoyanchev

Thanks for the suggestion but I don't see how it could work.

Prefix-based patterns like that do look convenient but the full path must also be truncated somehow to perform a lookup. It's not clear how to do this generally given the wide range of patterns possible, see AntPathMatcherTests for example.

PathMatcher works with Strings and manipulating Strings for every pattern match is inefficient. This is why PathPattern and RequestPath were created for WebFlux. They are parsed representations and much more efficient. To integrate them into Spring MVC as an alternative to using PathMatcher would require quite a bit of work but it's something we could consider for 5.3.

Comment From: viswaramamoorthy

In the lookup handler method, I was thinking of using "startsWith" on the incoming uri string to identify potential matches. Once a list of potential matches identified, lookupHandlerMethod can continue with identifying actual match in the same way it does today. Something like below.

In MappingRegistry class, add a partial path match

public List getMappingsByPartialPathUrl(String urlPath) { List matchedPathUrls = new ArrayList(); for (Entry> entry : this.urlPathVariableLookup.entrySet()) { if (urlPath.startsWith(entry.getKey())) { matchedPathUrls.addAll(entry.getValue()); } } return matchedPathUrls; }

Would it work?

On Wed, Apr 15, 2020, 1:32 PM Rossen Stoyanchev notifications@github.com wrote:

Thanks for the suggestion but I don't see how it could work.

Prefix-based patterns like that do look convenient but the full path must also be truncated somehow to perform a lookup. It's not clear how to do this generally given the wide range of patterns possible, see AntPathMatcherTests https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java for example.

PathMatcher works with Strings and manipulating Strings for every pattern match is inefficient. This is why PathPattern and RequestPath were created for WebFlux. They are parsed representations and much more efficient. To integrate them into Spring MVC as an alternative to using PathMatcher would require quite a bit of work but it's something we could consider for 5.3.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-framework/issues/24901#issuecomment-614176558, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF5E7VJP24RFU46IGPWR3ILRMXVUXANCNFSM4MHEK24Q .

Comment From: rstoyanchev

Sure, but that is not a lookup. That is now comparable to what we do currently iterating over mappings and using AntPathMatcher to select or reject patterns.

Comment From: bclozel

I've got a draft implementation of a different approach for WebFlux, using a compressed Trie as a data structure. This shows nice performance properties for many mappings, but it's linked with the request path being in a PathContainer and the ability to break down path patterns segments (PathPattern allows that).

My initial benchmarks showed that a 2-pronged approach with exact matches and a compressed Trie could be interesting.

Comment From: viswaramamoorthy

Sure, but that is not a lookup. That is now comparable to what we do currently iterating over mappings and using AntPathMatcher to select or reject patterns.

I think lookup can be appended to filter out URI mappings that are not relevant by make couple of changes. I can send a PR to show complete changes that I tried.

Comment From: viswaramamoorthy

@rstoyanchev I have raised a PR to show the changes. https://github.com/spring-projects/spring-framework/pull/24942

As I am reading comments, it appears newer Spring framework has other ways to tackle performance issues related to path variable URI mappings. If so, issue/PR closed as invalid.

Comment From: rstoyanchev

Yes that is the case. I have created #24945 so please follow that.