Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Form] addedCallbackChoiceLoader and refactored ChoiceType's children#18332
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
[Form] addedCallbackChoiceLoader and refactored ChoiceType's children#18332
Uh oh!
There was an error while loading.Please reload this page.
Conversation
| protectedfunctionloadChoices() | ||
| { | ||
| return'currency'; | ||
| if (null ===self::$currencies) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
storing them in a static property will increase the memory usage by preventing garbage collection until the end of the process.
What kind of performance gain is there in term of time here, to counter-balance the loss regarding memory perf ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Those types may be used many times in a form or with many forms in one request.
This optimisation is already done inTimeZoneType.
I have no hard feeling about this, just a PoC for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Sure they can be used many times. But any such optimization like this must be backed by numbers (especially when it is expected to improve one side at the expense of a loss on the other side, to know whether the loss can be accepted)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
anyway, I would suggest splitting this caching outside this PR, to discuss it separately (this caching can even be applied without the refactoring done in this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ok. Thanks@stof for the review!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
4caba21 todff2883Comparechoice_filter option toChoiceTypedff2883 tod3f6767Compare6360f60 tofbda538CompareHeahDude commentedMar 29, 2016
Ok so I dropped8298b1d because the I still think this abstract class is good for DX and maintainability. For example introducing the This may be trivial but there is no harm in performance, I've tried this code in SE: $builder =$this->createFormBuilder();for ($i =0;$i <10; ++$i) {$builder->add('country'.$i,FormType\CountryType::class);$builder->add('currency'.$i,FormType\CurrencyType::class);$builder->add('language'.$i,FormType\LanguageType::class);$builder->add('locale'.$i,FormType\LocaleType::class);$builder->add('timezone'.$i,FormType\TimezoneType::class);}$form =$builder->getForm(); From base to8298b1d (try to improve cache with static properties: |
HeahDude commentedMar 30, 2016
ping@webmozart, does it fit with#18368 ? |
webmozart commentedMar 30, 2016
A simpler and more flexible solution would be to add a class CountryTypeextends AbstractType{private$choiceLoader;publicfunction__construct() {$this->choiceLoader =newCallableChoiceLoader(function () {returnarray_flip(Intl::getRegionBundle()->getCountryNames()); }); }publicfunctionconfigureOptions(OptionsResolver$resolver) {$resolver->setDefaults(['choice_loader' =>$this->choiceLoader, ]); }} For each type, we make sure to reuse the same loader instance, then the caching mechanisms in |
HeahDude commentedMar 30, 2016
I thought about it too since it is very easy to do, I'm glad you brought that up, I might be done in time :) Should I go on with it ? |
stof commentedMar 30, 2016
I prefer the solution suggested by@webmozart |
fbda538 to3f8525fCompareHeahDude commentedMar 31, 2016
Rebased. I first thought of using I think this callable choice loader will really improve performances, I will try to profile something today :) Also, I still think of some things:
Concerning choice loaders in general, if this PR is merged, this would be the first one implemented in the form core and in regard of the work I'm trying to do in#18359, I think there is two much caching when using loaders here's a schema: The So I suggest to use the following code in And together with the change of#18359 we can get in 4.0: I think the loader should not know about factories. The What do you think ? Thanks. |
| public function loadChoicesForValues(array $values, $value = null) | ||
| { | ||
| // Optimize | ||
| if (empty($value)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
$values? Is this not tested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Typo...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
The choice loader should not be responsible for$value check or test IMHO.
3f8525f to3aa5442CompareHeahDude commentedMar 31, 2016
When exactly will 3.1 be feature frozen ? |
| * @var ArrayChoiceList | ||
| */ | ||
| private $choiceList; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
please add documentation about what the callable is expected to return (namely an array of choices)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@HeahDude You seemed to agree, but I don't see any documentation here. Can you add a phpdoc? I would then remove the doc on the property above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@fabpot Sorry, I don't understand where you want me to add and remove things.
Back then I had changed the first phpdoc fromThe callable used to load the choices. toThe callable used to load the array of choices. thinking that both phpdocs would be less confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Sorry, I was not very clear. Let me try again. It would be better to add a phpdoc to the constructor:
/** * @param callable $callback The callable used to load the array of choices */publicfunction__construct(callable$callback) {$this->callback =$callback;}
and remove the one on the private property:
private$callback;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Alright, makes sense. I will do it very soon.
8e8bf19 to64d1d9cCompareHeahDude commentedApr 7, 2016
@stof All comments addressed here, plus the optimization by implementing the This one still has a chance. I'm just waiting for the appveyor tests to be green :) |
64d1d9c tod8539aaCompareHeahDude commentedApr 7, 2016
Green :) |
HeahDude commentedApr 7, 2016
I will try to profile again but there's no doubt that they'll be better than above :) |
| /** | ||
| * @author Jules Pietri <jules@heahprod.com> | ||
| */ | ||
| abstract class AbstractChoiceLoaderTest extends \PHPUnit_Framework_TestCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
IMO, there is no need to introduce this abstract class, as you use it only once
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Don't you think it might help to introduce other loaders in the future and test them ?
I did it because it's the first implementation in the form component (the only one before was theDoctrineChoiceLoader) but this part should be re-usable IMHO.
Of courses I can easily integrate it inCallbackChoiceLoaderTest class.
Is this the final blocker ? Thank you again for your review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@HeahDude We can still extract common logic in an abstract base class then if needed. I would remove this class for now too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Fair enough! I do it right away.
d8539aa to8e3b279CompareHeahDude commentedApr 11, 2016
Alright, last comments addressed! Failures are unrelated, I think I'm done here :) |
fabpot commentedApr 11, 2016
👍 |
8e3b279 toec0fa1fCompareHeahDude commentedApr 25, 2016
Rebased. Tests still green. Last comment here is@fabpot approval. Is this still planned for 3.1? If so, it should be merged as soon as possible to be tested during beta. ping@symfony/deciders Thanks. |
8607c56 to72173aaCompareHeahDude commentedApr 30, 2016
Re-re-rebased :) |
72173aa to8a4e164CompareHeahDude commentedJun 13, 2016
Comments addressed and changelog updated to target 3.2. |
fabpot commentedJun 13, 2016
@HeahDude Can you submit a PR for the docs? Thanks. |
fabpot commentedJun 13, 2016
Thank you@HeahDude. |
…iceType's children (HeahDude)This PR was merged into the 3.2-dev branch.Discussion----------[Form] added `CallbackChoiceLoader` and refactored ChoiceType's children| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets | ~| License | MIT| Doc PR | todoTodo====- [ ] Address a doc PR- [x] Update CHANGELOGChanges======= -39e937f added `CallbackChoiceLoader` to lazy load choices with a simple callable. -995dc56 refactored `CountryType`, `CurrencyType`, `LanguageType`, `LocaleType` and `TimezoneType` for better performance by implementing `ChoiceLoaderInterface` for lazy loading.Usage=====```phpuse Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;use Symfony\Component\Form\Extension\Core\Type\ChoiceType;$builder->add('constants', ChoiceType::class, array( 'choice_loader' => new CallbackChoiceLoader(function() { return StaticClass::getConstants(); },));```Commits-------8a4e164 [Form] implemented ChoiceLoaderInterface in children of ChoiceTypeafd7bf8 [Form] added `CallbackChoiceLoader`
HeahDude commentedJun 13, 2016
Will do, thank you@fabpot |


Todo
Changes
CallbackChoiceLoaderto lazy load choices with a simple callable.CountryType,CurrencyType,LanguageType,LocaleTypeandTimezoneTypefor better performance by implementingChoiceLoaderInterfacefor lazy loading.Usage