-
Notifications
You must be signed in to change notification settings - Fork 27.4k
perf($compile): only use document fragments and copy data when necessary (replaceWith) #9365
Conversation
8292c21
to
7b9fddf
Compare
// If multiple elements are being replaced they will be placed into a temporary fragment | ||
// so they can still be traversed via .nextSibling or .parent.children while detached. | ||
// This also detaches the elements (index 1+) if they have a parent. | ||
if (1 < removeCount) { |
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.
Easier to read: removeCount > 1
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.
I think putting the (expected to be) smaller value on the left is easier to read, but I think I'm normally the odd one out on that one. Then expressions such as 1 < a && a < 5
read nicely left to right, and you don't have to remember what >
means!
But I'll change it when/if this is closer to being merged, along with any other feedback...
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.
+1 for what @tbosch said. we don't use this style elsewhere in the code base, so we should be consistent.
4dd5a20
to
998c61c
Compare
Do we have a benchmark that shows the impact of this change? |
e3a9ae7
to
0ca44b3
Compare
I don't think any of the benchmarks cover this right now. Just doing a quick profile such as: Or for the templateUrl case something such as: On another note... it looks like both of those cases can be 2x faster when replacing a single node (99.9% of cases?) by using a simple |
@@ -169,6 +169,13 @@ function jqLiteAcceptsData(node) { | |||
return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; | |||
} | |||
|
|||
function jqLiteHasData(node) { |
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.
should we document this in angular.element docs?
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.
I would vote no for now since the other static methods (jqLiteData
, jqLiteRemoveData
) have not been documented. But we easily could, and we can also add the non-static version of hasData
...
fragment.appendChild(firstElementToRemove); | ||
// If multiple elements are being replaced they will be placed into a temporary fragment | ||
// so they can still be traversed via .nextSibling or .parent.children while detached. | ||
// This also detaches the elements (index 1+) if they have a parent. |
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.
"index 1+"? what does that mean?
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.
If the elementsToRemove
have a parent node this what removes them, except the firstElementToRemove
which was removed using replaceWith
above. I'll try to rephrase that...
it would be great if you could add a benchpress benchmark for this scenario so that we don't regress the perf of this in the future. |
patch looks okay to me, but I agree we should see how this impacts benchmarks / applications. I'm not sure that needs to block landing |
0ca44b3
to
cda5241
Compare
Updated the commits. For the benchmarks I'm thinking we'll need a new benchpress app to allow measuring compile, link before templateUrl is resolved, etc. Any objections to a new bp app? Or other ideas? |
2b98ed5
to
ee4adc1
Compare
I've added a new benchpress app to measure specific directive/compile/link features. This is quite different from the other benchpress apps so please take a look and let me know what you think. Basically instead of adding N test cases it has N features that can be turned on/off to test different combos of those features (without having to write N! test cases). The benchmarks seem to follow what I said in my previous comment:
|
ee4adc1
to
2eed4cf
Compare
So is this worth it? I think the code is simpler and explains some TODOs which is worth it on its own. The new benchmark app I'm not so sure about though, has anyone looked at it...? |
These changes (excluding the benchmarks) have been broken up into smaller PRs, closing this... |
This does a few things, all within the internal
replaceWith
...hasData
to avoid creating empty data to copy (a jqLite version ofhasData
was added)