Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[DI] Add "container.hot_path" tag to flag the hot path and inline related services#24872

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
fabpot merged 1 commit intosymfony:3.4fromnicolas-grekas:optim
Nov 9, 2017

Conversation

@nicolas-grekas
Copy link
Member

@nicolas-grekasnicolas-grekas commentedNov 8, 2017
edited
Loading

QA
Branch?3.4
Bug fix?no
New feature?yes
BC breaks?no
Deprecations?no
Tests pass?yes
Fixed tickets-
LicenseMIT
Doc PR-

This PR is the result of my quest to squeeze some performance out of 3.4/4.0.

It builds on two ideas:

  • a newcontainer.hot_path tag that identifies the services that arealways needed. This tag is only applied to a very short list of bootstrapping services (router,event_dispatcher,http_kernel andrequest_stack only). Then, it is propagated to all dependencies of these services, with a special case for event listeners, where only listed events are propagated to their related listeners.
  • replacing the PHP autoloader by plain inlinedrequire_once in generated service factories, with the benefit of completely bypassing the autoloader for services and their class hierarchy.

The end result is significant, even on a simple Hello World.
Here is the Blackfire profile, results are consistent withab benchmarks:

https://blackfire.io/profiles/compare/b5fa5ef0-755c-4967-b990-572305f8f381/graph

capture du 2017-11-08 16-54-28

ogizanagi, brpaz, oleg-andreyev, and TomasVotruba reacted with thumbs up emojiplandolt, fancyweb, digitalkaoz, 20uf, lyrixx, dmaicher, linaori, yceruto, shouze, michaelperrin, and 4 more reacted with hooray emoji
@lyrixx
Copy link
Member

I like it.

But i think the namecontainer.inline is misleading. It can be confused with the service inlining ($instance = new A(new B())).

IIUC, here it inlines the factory in the dumped container + it pre-load the PHP Class.

@nicolas-grekas
Copy link
MemberAuthor

container.hot_path?
ppl shouldn't really use that anyway, because propagation is enough most of the time

@lyrixx
Copy link
Member

container.hot_path?

Yes it's better. And like that the name of the tag will be the same as the CompilerPass ;)

ppl shouldn't really use that anyway, because propagation is enough most of the time

It depends. We already use some inlining feature in Blackfire. It could be useful anyway.

20uf reacted with thumbs up emoji

KernelEvents::CONTROLLER_ARGUMENTS,
KernelEvents::RESPONSE,
KernelEvents::FINISH_REQUEST,
KernelEvents::TERMINATE,
Copy link
Member

Choose a reason for hiding this comment

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

I don't think terminate needs to be in the hot path. When using PHP-FPM, this code runs after sending the request.

return;
}
try {
$r =new \ReflectionClass($class);
Copy link
Member

Choose a reason for hiding this comment

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

this might break if a parent class does not exist (ContainerBuilder is using a special autoloader to cover this when getting a tracked ReflectionClass)

return;
}
$file =$r->getFileName();
if (!$file ||$this->doExport($file) ===$file =$this->export($file)) {
Copy link
Member

Choose a reason for hiding this comment

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

reassigning$file in the middle of an expression using it on both side makes the code quite hard to read. Please use a different variable name instead.


<serviceid="request_stack"class="Symfony\Component\HttpFoundation\RequestStack"public="true" />
<serviceid="request_stack"class="Symfony\Component\HttpFoundation\RequestStack"public="true">
<tagname="container.hot_path" />
Copy link
Member

Choose a reason for hiding this comment

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

do we actually need this ? HttpKernel propagates it anyway (and if HttpKernel does not use the stack anymore, it is not hot anymore)

$this->subscriberTag =$subscriberTag;
}

publicfunctionsetHotPathListeners(array$hotPathListeners,$tagName ='container.hot_path')
Copy link
Member

Choose a reason for hiding this comment

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

you are not setting listeners, you are setting events

{
parent::build($container);

$hotPathListeners =array(
Copy link
Member

Choose a reason for hiding this comment

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

these are events, not listeners

@stof
Copy link
Member

stof commentedNov 8, 2017

Tests are missing, for both the compiler pass and the new dumper behavior

@nicolas-grekas
Copy link
MemberAuthor

Now with a newcontainer.dumper.inline_class_loader parameter toopt-in this optimization, so that ppl doing strange things with their autoloader are still fine.

@stof thanks, comments addressed.

@nicolas-grekas
Copy link
MemberAuthor

Just proposed to enable the parameter by default insymfony/recipes#241

if (isset($lineage[$class])) {
return;
}
if (!$r =$this->container->getReflectionClass($class)) {
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

@stof this still throws, but in a more controlled way. Since this is running late, all services should be fine xor the container is broken already. Do we want really to not throw? WDYT?

@nicolas-grekasnicolas-grekas changed the title[DI] Add "container.inline" tag to flag the hot path and inline related services[DI] Add "container.hot_path" tag to flag the hot path and inline related servicesNov 8, 2017
@beberlei
Copy link
Contributor

I feelcontainer.inline is a little misleading, it feels something along the lines ofcontainer.require orcontainer.preload is more correct naming wise. Otherwise i love the idea :)

$code .=sprintf(" require_once %s;\n",$file);
}

if ("\n" ===$code) {
Copy link
Contributor

Choose a reason for hiding this comment

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

how about ternary operator with return?

'namespace' =>'',
'as_files' =>false,
'debug' =>true,
'hot_path_tag' =>null,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does it not have a default?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I don't want it to be enabled by default, so this is opt-in.
This is the way to do it.


privatefunctionaddInlineRequires()
{
if (!$this->hotPathTag || !$this->inlineRequires) {
Copy link
Contributor

@TobionTobionNov 8, 2017
edited
Loading

Choose a reason for hiding this comment

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

Why have two ways to disable this? Cant you just make hotPathTag required?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Because these are two independent settings (that play well together.)

@Tobion
Copy link
Contributor

So therouter is loaded always even in CLI where it is not used?

@nicolas-grekas
Copy link
MemberAuthor

The routerclasses are always loaded yes (not the objects). We don't care about the related CLI perf impact IMHO, it's negligible.

@Tobion
Copy link
Contributor

Can't we preload the CLI classes as well then to speed up the CLI? If the impact of preloading unused classes is negligible, this shouldn't hurt webrequest as well.

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedNov 8, 2017
edited
Loading

There's nothing to optimize for the CLI: the CLI is not called 700 times per second as the web is. Just forking the CLI process is an order of magnitude slower than these optimizations.

dmaicher and beberlei reacted with thumbs up emoji

@dmaicher
Copy link
Contributor

dmaicher commentedNov 8, 2017
edited
Loading

On my biggest monolith app I can also measure a slight performance benefit for one html page that I tested 👍

  • prod, debug=false
  • composer dump --classmap-authoritative && app/console cache:clear --env=prod --no-debug
  • php 7.1, opcache enabled
  • ab -n 10000 -c 1 "http://..."

your branch HEAD~1 (8cd2193):41.112 ms
your commit (44fe030) with enabled feature:40.289 ms

So for me its roughly 2% faster. Not quite as significant as in your benchmarks. Under which conditions did you benchmark@nicolas-grekas ?

@nicolas-grekas
Copy link
MemberAuthor

Now with tests, PR ready for a last (hopefully) round of review.

@dmaicher thanks for the confirmation! My test was on an annotated controller with a Twig-rendered Hello World, and using Blackfire to profile. Usingab, I'm more at 2% also.

@nicolas-grekasnicolas-grekasforce-pushed theoptim branch 4 times, most recently from00e0c23 toe20e523CompareNovember 9, 2017 09:25
@nicolas-grekas
Copy link
MemberAuthor

(failures are false-positives)

'as_files' =>false,
'debug' =>true,
'hot_path_tag' =>null,
'inline_class_loader_parameter' =>'container.dumper.inline_class_loader',
Copy link
Member

Choose a reason for hiding this comment

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

Why is it configurable? Usually we don't want to add new options. IMHO, this is useless here.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I don't like hardcoding a parameter name into the dumper

@fabpot
Copy link
Member

Can we make fabbot happy? Avoiding false-positives in the future would be great.

@nicolas-grekas
Copy link
MemberAuthor

green it is now :)

@fabpot
Copy link
Member

Thank you@nicolas-grekas.

@fabpotfabpot merged commitf7cb559 intosymfony:3.4Nov 9, 2017
fabpot added a commit that referenced this pull requestNov 9, 2017
…nd inline related services (nicolas-grekas)This PR was merged into the 3.4 branch.Discussion----------[DI] Add "container.hot_path" tag to flag the hot path and inline related services| Q             | A| ------------- | ---| Branch?       | 3.4| Bug fix?      | no| New feature?  | yes| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets | -| License       | MIT| Doc PR        | -This PR is the result of my quest to squeeze some performance out of 3.4/4.0.It builds on two ideas:- a new `container.inline` tag that identifies the services that are *always* needed. This tag is only applied to a very short list of bootstrapping services (`router`, `event_dispatcher`, `http_kernel` and `request_stack` only). Then, it is propagated to all dependencies of these services, with a special case for event listeners, where only listed events are propagated to their related listeners.- replacing the PHP autoloader by plain inlined `require_once` in generated service factories, with the benefit of completely bypassing the autoloader for services and their class hierarchy.The end result is significant, even on a simple Hello World.Here is the Blackfire profile, results are consistent with `ab` benchmarks:https://blackfire.io/profiles/compare/b5fa5ef0-755c-4967-b990-572305f8f381/graph![capture du 2017-11-08 16-54-28](https://user-images.githubusercontent.com/243674/32558666-a3f439b2-c4a5-11e7-83a3-db588c3e21e5.png)Commits-------f7cb559 [DI] Add "container.hot_path" tag to flag the hot path and inline related services
@nicolas-grekasnicolas-grekas deleted the optim branchNovember 9, 2017 15:05
OskarStark added a commit to symfony/symfony-docs that referenced this pull requestNov 26, 2019
This PR was merged into the 3.4 branch.Discussion----------Add container.hot_path to built-in service tagsRelated to [symfony/symfony#24872](symfony/symfony#24872)<!--If your pull request fixes a BUG, use the oldest maintained branch that containsthe bug (seehttps://symfony.com/roadmap for the list of maintained branches).If your pull request documents a NEW FEATURE, use the same Symfony branch wherethe feature was introduced (and `master` for features of unreleased versions).-->Commits-------1647b9a Add container.hot_path to built-in service tags
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@lyrixxlyrixxlyrixx left review comments

@stofstofstof left review comments

@fabpotfabpotfabpot approved these changes

@chalasrchalasrchalasr approved these changes

+1 more reviewer

@TobionTobionTobion left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

3.4

Development

Successfully merging this pull request may close these issues.

10 participants

@nicolas-grekas@lyrixx@stof@beberlei@Tobion@dmaicher@fabpot@chalasr@javiereguiluz@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp