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

Optimize route addition #3

Merged
merged 4 commits into from Jan 6, 2021
Merged

Optimize route addition #3

merged 4 commits into from Jan 6, 2021

Conversation

nightlinus
Copy link
Contributor

Q A
Documentation no
Bugfix no
BC Break yes
New Feature no
RFC no
QA no

Description

This pr optimizes route addition by removing O(n) duplicate check. In case of big monolitic application this starts to bite performance of application initialization. I have moved duplication check to separate class because now it owns hashmap data structure for searching route.

Solves #1

@geerteltink
Copy link
Contributor

Just wondering what router you are using. If you need speed you may want to look into FastRoute and it's caching support: https://docs.mezzio.dev/mezzio/v3/features/router/fast-route/#fastroute-caching-support

@nightlinus
Copy link
Contributor Author

Just wondering what router you are using. If you need speed you may want to look into FastRoute and it's caching support: https://docs.mezzio.dev/mezzio/v3/features/router/fast-route/#fastroute-caching-support

I am using Aura. Thank you for FastRoute caching link, but i should mention that its caching doesn't bypass RouteCollector calls and duplication check. I am working on caching routes in my application and there is some problem that as for now routes collection can be taken only from RouteCollector and getRoutes() is not part of RouterInterface so we have 2 places that actually must contain all routes and 2 places to restore from cache, but this is not the case for this pr.

Copy link
Contributor

@weierophinney weierophinney left a comment

Choose a reason for hiding this comment

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

I rebased for you - please pull before making additional changes.

I've noted one change - if you get that in place, I think this will be ready to merge!

src/RouteCollector.php Outdated Show resolved Hide resolved
@weierophinney
Copy link
Contributor

Also, @nightlinus — check the travis failures.

@nightlinus nightlinus force-pushed the master branch 2 times, most recently from 9da302c to 25c9001 Compare June 17, 2020 12:39
@nightlinus
Copy link
Contributor Author

done

@michalbundyra michalbundyra added the Enhancement New feature or request label Jun 17, 2020
@michalbundyra michalbundyra added this to the 3.2.0 milestone Jun 17, 2020
@michalbundyra michalbundyra linked an issue Jun 17, 2020 that may be closed by this pull request
src/RouteCollector.php Outdated Show resolved Hide resolved
test/RouteCollectorTest.php Outdated Show resolved Hide resolved
test/RouteCollectorTest.php Outdated Show resolved Hide resolved
public function __construct(RouterInterface $router)
{
$this->router = $router;
$this->duplicateRouteDetector = new DuplicateRouteDetector();
Copy link

Choose a reason for hiding this comment

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

Why don't you move this in RouteCollectorFactory ?

Also, I suggest you implement an interface, make it invokable and also create an alias in ConfigProvider.
This would allow any developer to use it as a service and also override it with a local implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is BC break as was suggested by @weierophinney

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, for another reason, about the factory. (I am not sure about the need for an interface for this task, but not against it)
IMO the duplicateRouteDetector instance should also be allowed to be passed in (and to be) null (via factory-(dev|prod)-configuration), thus skipping duplicate checks. Developers should be allowed to control when actually perform it, e.g. in dev-mode only. A default ALWAYS-ON value would not cause any BC break. Kind regards.

Choose a reason for hiding this comment

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

Suggested change
$this->duplicateRouteDetector = new DuplicateRouteDetector();
$this->duplicateRouteDetector = $duplicateRouteDetector ?? new DuplicateRouteDetector();

Copy link
Contributor

Choose a reason for hiding this comment

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

While I agree about the idea of the factory, for BC purposes, it does need to be enabled by default at the constructor level, not at the factory level. If a consumer had decided to create their own factory for the route collector previously, they would not know to pass the DuplicateRouteDetector instance, and would thus end up in a scenario where duplicate detection is disabled after updating the library within the same major version.

What we can do is use a flag here. Since the logic is marked final, we can have a flag that defaults to true, indicating the DuplicateRouteDetector should be used. Users who want to disable it would pass a boolean false for the flag during instantiation of the RouteCollector, which would disable that.

We can then also add a config flag for the factory to consume in order to disable it.

This would address the BC concerns, as well as the concerns that developers have a way to disable it for production.

I'm working on that now, @nightlinus ; no need for you to do more work than you already have on this!

@nightlinus
Copy link
Contributor Author

Is there something else i should fix before merging @weierophinney ?

@samsonasik
Copy link
Member

@geerteltink could you give reason for closing this PR? or it was an accidentally hit close PR button?

@geerteltink
Copy link
Contributor

I did not close it. I'm adding automatic releases according the guide. I guess it got automatically closed when removing develop via cli. If I go over the reopen and comment button it says develop branch was removed.

We should revise the workflow and delete the develop and master branch as last, after rebasing all open PRs.

/cc @weierophinney

@geerteltink
Copy link
Contributor

geerteltink commented Sep 10, 2020

@nightlinus I cannot reopen or rebase your MR. Can you rebase it onto branch 3.2.x and see if you can reopen this MR?

/edit: Fix the issue and reopened and rebased onto 3.2.x

@geerteltink geerteltink reopened this Sep 11, 2020
@geerteltink geerteltink changed the base branch from develop to 3.2.x September 11, 2020 11:50
@boesing boesing removed this from the 3.2.0 milestone Oct 24, 2020
* @var DuplicateRouteDetector
*/
private $duplicateRouteDetector;

public function __construct(RouterInterface $router)

Choose a reason for hiding this comment

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

Suggested change
public function __construct(RouterInterface $router)
public function __construct(RouterInterface $router, DuplicateRouteDetector $duplicateRouteDetector = null)

public function __construct(RouterInterface $router)
{
$this->router = $router;
$this->duplicateRouteDetector = new DuplicateRouteDetector();

Choose a reason for hiding this comment

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

Suggested change
$this->duplicateRouteDetector = new DuplicateRouteDetector();
$this->duplicateRouteDetector = $duplicateRouteDetector ?? new DuplicateRouteDetector();

@nightlinus
Copy link
Contributor Author

Fellows, i dont understand what should i do to help this merged or declined. I have done edits as was suggested by @weierophinney, now i get reviews in different directions. Can someone help me to understand what should i do with this PR please? @geerteltink @samsonasik @boesing

It used to be O(n) to check duplicate, this introduce hashmap structure for route duplicate checks, thus reduce cost of check to O(1)

Signed-off-by: nightlinus <m.a.ogarkov@gmail.com>
@weierophinney weierophinney added this to the 3.3.0 milestone Jan 6, 2021
Duplicate route detection is enabled by default, via a flag in the `RouteCollector` class.
If the flag is set, but no duplicate route detector is present in the instance, one is created on the first request to detect duplicate routes.
If disabled, duplicate route detection is not performed.

The `RouteCollector` factory now also checks for a configuration value, `Mezzio\Router\RouteCollector.detect_duplicates`; when present, the value is passed for the optional second constructor argument of the `RouteCollector`.

Signed-off-by: Matthew Weier O'Phinney <matthew@weierophinney.net>
Signed-off-by: Matthew Weier O'Phinney <matthew@weierophinney.net>
Signed-off-by: Matthew Weier O'Phinney <matthew@weierophinney.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Optimize route addition
9 participants