-
Notifications
You must be signed in to change notification settings - Fork 27.4k
perf(ngForm,ngModel): move initial addClass to the compile phase #8268
Conversation
Thanks for the PR! Please check the items below to help us merge this faster. See the contributing docs for more information.
If you need to make changes to your pull request, you can update the commit with Thanks again for your help! |
what exactly is the performance benefit of this? this is unclear to me |
If a form or model is linked more then once it only adds the classes once at compile time (before cloning the element). Or am I missing something that makes this case different then other directives? My use case is ng-model within ng-repeat, such as a list of items with a checkbox each... |
right but, is something happening that you're not expecting to happen? adding/removing classes isn't a particularly expensive operation usually, so I'm wondering if you're really noticing this |
oops, didn't mean to close that |
I think adding/removing classes is particularly expensive since it touches the DOM, and especially when it modifies the DOM. If it is done at compile time then it is done once and cloned where at link time it is done N times. This is basically what @IgorMinar has been doing to many directives, however this removes 3 calls to add/removeClass per link instead of just 1, but with the potential side effect of not going through In the plunker below the NgModelController is about 25% of the bootstrapping, and half that is calling add/remove class 3 times... |
Classes aren't being added/removed all that frequently, so this is much less of a hit than it would be otherwise. Even in a list of 2000 form controls, it's pretty negligible. Even when it comes to bootstrap time, I'm not sure that this is a real bottleneck in any real application --- I may be wrong, but I'd need to see proof to come to that conclusion. I think if it is a significant bottleneck, the application design probably needs to be re-worked, because it really shouldn't be. Anyways, I'm pretty sure this is not right, but see what matias or igor think about it, really. |
Does the plunker not show add/removeClass being 10%+ of the link time? I thought that was pretty significant for something that can easily be avoided... Do you have an example of how an app such as the plunker example can be re-worked to avoid this? Or do you mean 2000 checkboxes is just bad UI? (Which I'd agree with, but that much data is rare enough in my case so it wouldn't be worth changing the UI.) |
@@ -410,7 +406,10 @@ var formDirectiveFactory = function(isNgForm) { | |||
name: 'form', | |||
restrict: isNgForm ? 'EAC' : 'E', | |||
controller: FormController, | |||
compile: function() { | |||
compile: function(formElement) { |
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.
name anonymous fns
@caitp I think that for ngModel used in a repeater this change could be significant. I'll review this and get it in as part of rc2 |
d89922b
to
376dcca
Compare
I've added the compile/link function names. |
02dc2aa
to
fd2d6c0
Compare
compile: function() { | ||
compile: function ngFormCompile(formElement) { | ||
// Setup initial state of the control | ||
formElement.addClass(PRISTINE_CLASS + ' ' + VALID_CLASS); |
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.
do addClass(PRISTINE_CLASS).addClass(VALID_CLASS)
in order to avoid extra string concat and splitting
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.
Performance wise I assume the extra string concat here is actually better because each addClass will do split+forEach+regex+get/setAttribute. But this is compile time so I don't think it matters much, and calling addClass
twice looks more readable so I'll go ahead with that for now...
376dcca
to
64ac177
Compare
@IgorMinar I've made the suggested changes to the |
can you rebase this on top of master please? it looks good otherwise. |
e8d176e
to
effc9dd
Compare
Rebased. Note that in the rebase I added a |
merged. thanks |
Other then moving from link to compile time the only difference (which unit tests didn't seem to care about) is that
$animate.addClass(VALID_CLASS)
and$animate.removeClass(INVALID_CLASS)
are no longer called at link time since VALID_CLASS is added at compile and INVALID_CLASS shouldn't exist. If anyone depends on the initial animation calls or on the.removeClass(INVALID_CLASS)
then this change won't work, at least in its current form...