Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(routing): add regex chunking to route regex #714

Merged
merged 3 commits into from
Nov 15, 2024

Conversation

blackshadev
Copy link
Contributor

@blackshadev blackshadev commented Nov 10, 2024

What

Add regex chunking to route regex. When loading in massive amounts of routes a singular regex can become to large for PCRE to process. A solution for this is to split it up in multiple separate regexes, this is called chunking. With this PR is should be possible to load in as many routes as you like, as long as your memory can hold it.

In order to facilitate this I needed to rework how we build up the regex, instead of using recursion and having the stack implicitly as a php call stack. I needed to implement it manually such that, when it is detected we require a new chunk, we could rebuild the regex prefix based on the stack and also finish it based on it.

Outstanding debates

RouteMatchingRegexesBuilder performance considerations

I isolated the regex buildin into src/Tempest/Http/src/Routing/Construction/RouteMatchingRegexesBuilder.php and one singular function. This is mostly because of performance reasons. The inner part of the loop is called so many times, every function call needed to count. So there is a trade-off between readability and performance. Currently I opted to go slightly more towards the performance side. If you think it should be implemented into multiple methods, do know it comes at a cost. (If needed, we can use the benchmarks to signify the cost of alterations).

This is also the reason for using null as a end marker instead of wrapping all nodes into a VO which also would translate to an end-marker. I saw a performance drop of arround 60%, I went from 120μs to 190μs

PHPunit memory limit

I bumped the phpunit memory limit. I couldn't find a "leak" in the newly added code. And it mainly breaks on the integration part. My expectation is the integration tests are already quite hefty on memory and my changes tipped it over the limit. I used memprof to find any culprits, but I couldn't find any glaring issues, most memory consumption is not in "my" code or even near it.

@blackshadev blackshadev force-pushed the feat/route-regex-chunking branch from c28affe to 9ed28c0 Compare November 10, 2024 15:49
@blackshadev blackshadev marked this pull request as ready for review November 10, 2024 16:01
@blackshadev blackshadev force-pushed the feat/route-regex-chunking branch from 9ed28c0 to 3e57646 Compare November 10, 2024 16:04
@brendt
Copy link
Member

brendt commented Nov 12, 2024

Great PR 👍

@coveralls
Copy link

Pull Request Test Coverage Report for Build 11799155234

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 71 of 73 (97.26%) changed or added relevant lines in 5 files are covered.
  • 19 unchanged lines in 2 files lost coverage.
  • Overall coverage increased (+0.1%) to 82.551%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/Tempest/Http/src/Routing/Matching/MatchingRegex.php 11 13 84.62%
Files with Coverage Reduction New Missed Lines %
src/Tempest/Console/src/ConsoleApplication.php 7 10.0%
src/Tempest/Http/src/HttpApplication.php 12 0.0%
Totals Coverage Status
Change from base Build 11770148738: 0.1%
Covered Lines: 7333
Relevant Lines: 8883

💛 - Coveralls

@blackshadev blackshadev force-pushed the feat/route-regex-chunking branch 2 times, most recently from 6aaab7b to 61cc31c Compare November 12, 2024 14:22
@blackshadev blackshadev requested a review from brendt November 12, 2024 14:24
@blackshadev blackshadev force-pushed the feat/route-regex-chunking branch 2 times, most recently from b13bf7d to f9ead7f Compare November 12, 2024 15:49
@brendt
Copy link
Member

brendt commented Nov 15, 2024

Do you wanna take a look at the merge conflict? Other than that I'm fine merging this 👍

It's not a blocker for me, but I do like for null to have meaning. So to me it makes more sense that RouteMatch can be nullable instead being notFound.

Look at it from a language perspective: "I have a route match" — that always means that there is a matching route. When you say "I don't have a route match", it means there is no matching route (ie. null).

- Renamed Regexes to Regex as it is already plural
- Make Regex limit a power of 2.. because it should be
- Make RouteMatch isFound a computed method based on routeMark
@blackshadev blackshadev force-pushed the feat/route-regex-chunking branch from f9ead7f to 4cc26e3 Compare November 15, 2024 12:04
@blackshadev
Copy link
Contributor Author

blackshadev commented Nov 15, 2024

Do you wanna take a look at the merge conflict? Other than that I'm fine merging this 👍

Done

It's not a blocker for me, but I do like for null to have meaning. So to me it makes more sense that RouteMatch can be nullable instead being notFound.

Look at it from a language perspective: "I have a route match" — that always means that there is a matching route. When you say "I don't have a route match", it means there is no matching route (ie. null).

done

It is a matter of opinion I changed it to null. I do not like null because you end up with allot of null checks everywhere. While not all nulls are equal. So in our case the Route match was not found. Which is something different than an error (maybe a case for later) or a route that is missing (as in, not completely loaded in). By returning null you will be missing these cases. But as state, it is a matter of opinion, and I do not see any harm in going your way on this. More so because it is a bit more in the "tempest" style.

@brendt brendt merged commit 3eb0c59 into tempestphp:main Nov 15, 2024
57 checks passed
@brendt
Copy link
Member

brendt commented Nov 15, 2024

Thanks! Great PR 💪

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants