8000 [Routing] Optimised dumped router matcher, prevent unneeded function calls. by frankdejonge · Pull Request #21755 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Routing] Optimised dumped router matcher, prevent unneeded function calls. #21755

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

Closed
wants to merge 12 commits into from
Closed
Prev Previous commit
Next Next commit
Flipped around special GET HEAD handling for less expensive method co…
…mparison.
  • Loading branch information
frankdejonge committed Feb 25, 2017
commit 0425f33a57f55ead17e34dd1edcec14076c05d2c
38 changes: 29 additions & 9 deletions src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ public function match(\$pathinfo)
\$trimmedPathinfo = rtrim(\$pathinfo, '/');
\$context = \$this->context;
\$request = \$this->request;
\$requestMethod = \$context->getMethod();
\$requestMethod = \$isLikeGetMethod = \$context->getMethod();

if (\$requestMethod === 'HEAD') {
Copy link
Contributor

Choose a reason for hiding this comment

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

'HEAD' === 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, thanks!

\$isLikeGetMethod = 'GET';
Copy link
Member

Choose a reason for hiding this comment

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

the $isLikeGetMethod variable name makes me think it is a boolean

Copy link
Member
@javiereguiluz javiereguiluz Feb 28, 2017

Choose a reason for hiding this comment

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

The is prefix in this variable name looks wrong. Maybe it's too late, but what if we rename $isLikeGetMethod = 'GET' to $isSafeMethod = true

We had some discussions about what a "safe method" is in HTTP, but the section 9.1.1 of RFC 2616 mentions GET and HEAD as safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html


Or at least, rename $isLikeGetMethod = 'GET' to $isGetOrHead = true

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, we don't want a boolean, because then we can't perform a meaningful optimisation. We just want to have a interpreted method, which we can check against. Otherwise we'd need to do more check than less.

Copy link
Member

Choose a reason for hiding this comment

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

What about renaming it to $methodAlias or $canonicalMethod or something like that? We "can't" store a string in a $is* variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like conicalMethod, a lot. I had previously opted to use methodWhereHeadMatchesGet instead. Which is a little verbose, but it does make it clear what's going on.

Copy link
Member

Choose a reason for hiding this comment

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

+1 for $canonicalMethod

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've renamed the variable to $canonicalMethod.

}


$code

Expand Down Expand Up @@ -219,11 +224,6 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
$hostMatches = false;
$methods = $route->getMethods();

// GET and HEAD are equivalent
if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
$methods[] = 'HEAD';
}

$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
$regex = $compiledRoute->getRegex();

Expand Down Expand Up @@ -265,20 +265,40 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
EOF;

$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);

if ($methods) {
if (1 === count($methods)) {
$code .= <<<EOF
if (\$requestMethod != '$methods[0]') {
if ($methods[0] === 'HEAD') {
$code .= <<<EOF
if (\$requestMethod != 'HEAD') {
\$allow[] = 'HEAD';
goto $gotoname;
}


EOF;
} else {
$code .= <<<EOF
if (\$isLikeGetMethod != '$methods[0]') {
\$allow[] = '$methods[0]';
goto $gotoname;
}


EOF;
}
} else {
$methodVariable = 'requestMethod';

if (in_array('GET', $methods)) {
// Since we treat HEAD requests like GET requests we don't need to match it.
$methodVariable = 'isLikeGetMethod';
$methods = array_filter($methods, function ($method) { return $method != 'HEAD'; });
}

$methods = implode("', '", $methods);
$code .= <<<EOF
if (!in_array(\$requestMethod, array('$methods'))) {
if (!in_array(\$$methodVariable, array('$methods'))) {
\$allow = array_merge(\$allow, array('$methods'));
goto $gotoname;
}
Expand Down
0