-
Notifications
You must be signed in to change notification settings - Fork 780
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add short circuit for patching memoized vnodes #378
add short circuit for patching memoized vnodes #378
Conversation
Codecov Report
@@ Coverage Diff @@
## master #378 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 2 2
Lines 148 150 +2
Branches 46 47 +1
=====================================
+ Hits 148 150 +2
Continue to review full report at Codecov.
|
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.
Needs tests and a demo to address #373.
😉🙏
src/app.js
Outdated
@@ -180,6 +180,10 @@ export function app(props) { | |||
} | |||
|
|||
function patch(parent, element, oldNode, node, isSVG, nextSibling) { | |||
if (oldNode === node) { | |||
console.log("memoized...") |
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 love console.log
as much as the next guy, but perhaps it's not needed here?
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.
was just to help me verify that it was actually running that memoize case, trying to rack down the uncovered line 265 in coverage report LOL
test/app.test.js
Outdated
}; | ||
} | ||
|
||
test("skips patching memoized vnodes", done => { |
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.
Does this actually check that the same VNode is returned?
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.
trying to figure out how to write the test for that...
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 another approach to this would be to create a simple demo app with one memoized component and one component not. Then somehow benchmark it, and once we understand the problem well, take another shot at this?
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.
You can call the memoized function twice and check for identity equality.
if anyone can help me see why line 265 is not covered after adding the un-connected conditional at the top of patch, it would be appreciated... gonna have another look in the morning after some coffee. |
src/app.js
Outdated
@@ -181,7 +181,6 @@ export function app(props) { | |||
|
|||
function patch(parent, element, oldNode, node, isSVG, nextSibling) { | |||
if (oldNode === node) { | |||
console.log("memoized...") |
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 so I have screenshots of chrome devtools performance tab with non-memoized, memoized without patch shortcut, and memoized with patch shortcut. You can see the JS (yellow) in the cpu time decreasing between the screenshots with each part of the optimization enabled... This was made via this codepen, https://codepen.io/andyrj/pen/yzzmLo, which is updating state every 16ms to increment a counter with a table that is based on static data below it... If this codepen is not sufficient to demonstrate the js overhead associated with a component that would benefit from memoization I don't really know what's going to satisfy a demo outside of a real app with expensive components. |
What is required to make this approved? |
@pspeter3 Just a little time. 🙏 |
There was a branch missing in coverage last I looked, and I still don't like the test I added... Just couldn't think of a better one at the time. |
4f56858
to
c25a5ae
Compare
Codecov Report
@@ Coverage Diff @@
## master #378 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 1 1
Lines 144 145 +1
Branches 42 43 +1
=====================================
+ Hits 144 145 +1
Continue to review full report at Codecov.
|
I was just going through issues and came from #373 (comment) to here.. when I first read this PR description (and graphs 💯 ) I thought wow this is awesome, but assumed for some reason that we would need to include the memoize function in core.. but this is not the case, right? Just an equality check will suffice. Which will always return false unless you have wrapped your component with memoize in userland. If I am understanding this correctly then what have we got against the idea? |
src/app.js
Outdated
@@ -196,7 +196,9 @@ export function app(props, container) { | |||
} | |||
|
|||
function patchElement(parent, element, oldNode, node, isSVG, nextSibling) { | |||
if (oldNode == null) { | |||
if (oldNode === 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.
@andyrj If this is all we need, we can simplify it as follows. (bytes)
if (oldNode===node){
} else if (oldNode == null) {
...
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.
Good call I wasn't taking the return at bottom into account for bytes.
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.
Okay, please rebase. 🙏
@lukejacksonn ya the memoize doesn't need to be a part of core. I just copy pasted that memoize() in comments above as an example someone could use. |
@andyrj 👌 and although I appreciate not every app/developer will take advantage of this feature nor will you need to memoize most of the time.. it does make sense to enable memoizing for when components get really big (more precisely, when the cost of diffing args and cacheing becomes cheaper than a straight up re-render, right?). If this is all that it takes then I'd say it is worth the minimal extra bytes and added complexity! |
91c5470
to
d3c0b76
Compare
Thanks @andyrj! 🎉 🌮 🎉 |
this adds a short circuit to patch for memoized components...
example memoize:
Users would wrap their components/view with this method to skip patching vnodes which have not changed.
This PR satisifies the following issue: #373