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

[EventDispatcher][VarDumper] optimize perf by leveraging Closure::fromCallable()#29245

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:masterfromnicolas-grekas:callable-optim
Dec 10, 2018

Conversation

@nicolas-grekas
Copy link
Member

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

Callables are notably slower than closures. Let's turn then to closures thanks toClosure::fromCallable().

This doesn't affect performance for run-once listeners.
And improves performance for events that are dispatched several times.

Same for VarDumper's casters.

Copy link
Contributor

@ostroluckyostrolucky left a comment

Choose a reason for hiding this comment

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

Why is this not incorporated inside sortListeners function? Instead it repeats the logic but ignores sort marking and is used only during dispatching

This doesn't affect performance for run-once listeners.

How come? It makes extra operations (new closure, Closure::fromCallable call)

@nicolas-grekas
Copy link
MemberAuthor

@ostrolucky thanks for the review!

Why is this not incorporated inside sortListeners function? Instead it repeats the logic but ignores sort marking and is used only during dispatching

Because sortListeners has public side effect: it drive the return value ofgetListeners().
Changing would mean breaking BC.

How come? It makes extra operations (new closure, Closure::fromCallable call)

and removes some. I did benchmark this, there is no measurable difference.

@ostrolucky
Copy link
Contributor

it drive the return value of getListeners()

getListeners() should continue returning the exact listeners that where added

I didn't mean to to imply you should save the optimization result intosorted property, you can still put it tooptimized, but from inside sortListeners. That wouldn't change anything on public side.

@nicolas-grekas
Copy link
MemberAuthor

you can still put it to optimized, but from inside sortListeners

that could defeat the extra laziness added here (not instantiating lazy listeners when propagation is stopped before them)

@nicolas-grekasnicolas-grekasforce-pushed thecallable-optim branch 2 times, most recently from5a9ac14 to5bc59f1CompareNovember 18, 2018 10:29
@ostrolucky
Copy link
Contributor

that could defeat the extra laziness added here (not instantiating lazy listeners when propagation is stopped before them)

I don't see how would it defeat it 🤔 Only way that closure is replaced with delegated one is when it's executed, which will happen only during dispatching.

@nicolas-grekas
Copy link
MemberAuthor

Because of the$listener[0] = $listener[0](); line, which is the one that is made lazy here.

@ostrolucky
Copy link
Contributor

I get that, but that line is executed only when outer closure is executed. I don't see why would moving construction of this closure to different place change when is it executed

@nicolas-grekas
Copy link
MemberAuthor

Because we have to call that line to populate the sortedListeners property.

ostrolucky reacted with thumbs up emoji

@ostrolucky
Copy link
Contributor

ostrolucky commentedNov 19, 2018
edited
Loading

This closure trick increases speed by 0.6μs aggregated (8%). 0.15μs from that is just thanks to inlining getListeners call. So closure trick alone is 0.45μs. Measured with phpbench, 100 listeners attached (and all of them executed). Correlation on number of listeners is very linear.

I don't think this is worth increased complexity and number of untested paths. Also, is there a PHP bug report? I think this is something better to be improved on language level.

Koc reacted with thumbs up emoji

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedNov 20, 2018
edited
Loading

We made current Symfony versions really fast because we made such changes. Small improvements for your bench can be a significant one for a specific use case. And it's already been proven that many small improvements aggregate to significant general ones.

The real issue is having EventDispatcher mutable. We should inspect existing use cases where this is needed (if any) and consider deprecating if possible IMHO. But that shouldn't block this one.

jvasseur reacted with thumbs up emoji

@ostrolucky
Copy link
Contributor

Well if we decide it's worth it, can you at least properly comment this code, cover it by tests and notify upstream about workarounds we need to do to increase performance so there is at least some chance we can eventually remove them? This was proven successful with eg inlining constants in DI Container. Performance tweaks like this are killing readability and hence ability to debug and contribute a lot. As you can see from my questions there are lot of non-obvious things for other people.

I still don't know in what case wouldif ($listener[0] instanceof \Closure) { condition be needed, because it's not covered by tests. And there is no longer even coverage for calling getListeners() call from dispatch().

@stof
Copy link
Member

I still don't know in what case wouldif ($listener[0] instanceof \Closure) { condition be needed, because it's not covered by tests.

that part is the lazy-loading of the listener object.

@ostrolucky
Copy link
Contributor

I see that, I just don't see how can be listener modified outside of this proxy closure. But testcase would help me with thatwink wink

@nicolas-grekasnicolas-grekasforce-pushed thecallable-optim branch 3 times, most recently from446270e to68f3b51CompareNovember 21, 2018 14:31
@nicolas-grekas
Copy link
MemberAuthor

The discussed code path is now tested@ostrolucky, testMutatingWhilePropagationIsStopped.

Don't be fooled by the diff stat, I just renamedAbstractEventDispatcherTest toEventDispatcherTest and added this test case.

ostrolucky reacted with thumbs up emoji

@ostrolucky
Copy link
Contributor

Thanks. I can see now that same closure is evaluated by sortListeners and optimizeListeners might not re-triggered after that happens.

fabpot added a commit that referenced this pull requestDec 10, 2018
…ariables (ostrolucky)This PR was merged into the 4.1 branch.Discussion----------Optimize perf by replacing call_user_func with dynamic variables| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets || License       | MIT| Doc PR        |This provides similar boost as in#29245, but on more places and without complexity increase. Check eg.https://github.com/fab2s/call_user_func for proofFabpot failure unrelatedCommits-------0c6ef01 Optimize perf by replacing call_user_func with dynamic vars
symfony-splitter pushed a commit to symfony/cache that referenced this pull requestDec 10, 2018
…ariables (ostrolucky)This PR was merged into the 4.1 branch.Discussion----------Optimize perf by replacing call_user_func with dynamic variables| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets || License       | MIT| Doc PR        |This provides similar boost as insymfony/symfony#29245, but on more places and without complexity increase. Check eg.https://github.com/fab2s/call_user_func for proofFabpot failure unrelatedCommits-------0c6ef01713 Optimize perf by replacing call_user_func with dynamic vars
symfony-splitter pushed a commit to symfony/validator that referenced this pull requestDec 10, 2018
…ariables (ostrolucky)This PR was merged into the 4.1 branch.Discussion----------Optimize perf by replacing call_user_func with dynamic variables| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets || License       | MIT| Doc PR        |This provides similar boost as insymfony/symfony#29245, but on more places and without complexity increase. Check eg.https://github.com/fab2s/call_user_func for proofFabpot failure unrelatedCommits-------0c6ef01713 Optimize perf by replacing call_user_func with dynamic vars
symfony-splitter pushed a commit to symfony/serializer that referenced this pull requestDec 10, 2018
…ariables (ostrolucky)This PR was merged into the 4.1 branch.Discussion----------Optimize perf by replacing call_user_func with dynamic variables| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets || License       | MIT| Doc PR        |This provides similar boost as insymfony/symfony#29245, but on more places and without complexity increase. Check eg.https://github.com/fab2s/call_user_func for proofFabpot failure unrelatedCommits-------0c6ef01713 Optimize perf by replacing call_user_func with dynamic vars
symfony-splitter pushed a commit to symfony/form that referenced this pull requestDec 10, 2018
…ariables (ostrolucky)This PR was merged into the 4.1 branch.Discussion----------Optimize perf by replacing call_user_func with dynamic variables| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets || License       | MIT| Doc PR        |This provides similar boost as insymfony/symfony#29245, but on more places and without complexity increase. Check eg.https://github.com/fab2s/call_user_func for proofFabpot failure unrelatedCommits-------0c6ef01713 Optimize perf by replacing call_user_func with dynamic vars
symfony-splitter pushed a commit to symfony/http-kernel that referenced this pull requestDec 10, 2018
…ariables (ostrolucky)This PR was merged into the 4.1 branch.Discussion----------Optimize perf by replacing call_user_func with dynamic variables| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets || License       | MIT| Doc PR        |This provides similar boost as insymfony/symfony#29245, but on more places and without complexity increase. Check eg.https://github.com/fab2s/call_user_func for proofFabpot failure unrelatedCommits-------0c6ef01 Optimize perf by replacing call_user_func with dynamic vars
@fabpot
Copy link
Member

Thank you@nicolas-grekas.

@fabpotfabpot merged commitd6a594b intosymfony:masterDec 10, 2018
fabpot added a commit that referenced this pull requestDec 10, 2018
… Closure::fromCallable() (nicolas-grekas)This PR was merged into the 4.3-dev branch.Discussion----------[EventDispatcher][VarDumper] optimize perf by leveraging Closure::fromCallable()| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets | -| License       | MIT| Doc PR        | -Callables are notably slower than closures. Let's turn then to closures thanks to `Closure::fromCallable()`.This doesn't affect performance for run-once listeners.And improves performance for events that are dispatched several times.Same for VarDumper's casters.Commits-------d6a594b [EventDispatcher][VarDumper] optimize perf by leveraging Closure::fromCallable()
@nicolas-grekasnicolas-grekas deleted the callable-optim branchJanuary 25, 2019 14:27
@nicolas-grekasnicolas-grekas modified the milestones:next,4.3Apr 30, 2019
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@fabpotfabpotfabpot approved these changes

+1 more reviewer

@ostroluckyostroluckyostrolucky requested changes

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

4.3

Development

Successfully merging this pull request may close these issues.

5 participants

@nicolas-grekas@ostrolucky@stof@fabpot@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp