Skip to content
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

Apply Partial Update to Virtual Stores #100

Merged
merged 4 commits into from
Oct 8, 2017
Merged

Conversation

jdolle
Copy link
Contributor

@jdolle jdolle commented Sep 18, 2017

Rather than replacing the entire state on content scripts every time a change occurs, this change will create patch messages, containing only the updated fields. This has a number of benefits.

  • Brings behavior in line with standard redux store (expected behavior).
  • More efficient because less data is being transferred over the messaging pipeline.

Resolves #98

});
let prevState = store.getState();

const patchState = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is where I was getting things wrong in my head. I like how you're doing the shallow diffing on the background page so the content script doesn't have to check equality at all (since all things serialized down will be new). Good shit. I need to make sure to grab a cup of ☕️ before talking in GH issues. :-P

type: PATCH_STATE_TYPE,
payload: diff,
});
}
};

// Send new state down connected port on every redux store state change
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we change this comment to read // Send patched state down...?

@@ -0,0 +1,39 @@
// import should from 'should';
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nix

@@ -0,0 +1,36 @@
const STATUS_UPDATED = 'updated';
Copy link
Collaborator

Choose a reason for hiding this comment

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

Love this direction. Let's put these in a shared src/constants file and reference them here and in Store.js above.

const state = Object.assign({}, this.state);

difference.forEach(({change, key, value}) => {
if (change === 'updated') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Love this. I like what you did before with the switch/case ladder - mind doing that here?

// send initial state
sendState();
// Send store's initial state through port
port.postMessage({
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice. Thanks for the cleanup by removing sendState!

{
key: 'a',
value: 2,
change: 'updated',
Copy link
Collaborator

Choose a reason for hiding this comment

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

Loving these tests. When you extract out that constants file, could you reference the constants here as well?

@jdolle
Copy link
Contributor Author

jdolle commented Sep 19, 2017

@vhmth Great feedback! I'm very glad you like the change. Please let me know if there is anything else I can do.

@tshaddix
Copy link
Owner

@jdolle @vhmth Hey guys - sorry I've been so out of the game. Had a family emergency I've been dealing with the last couple weeks.

@jdolle - really excited to look through this and see what you're proposing. I'm planning on diving in tomorrow morning. Thanks again for thinking through this!

@vhmth
Copy link
Collaborator

vhmth commented Sep 25, 2017

@tshaddix after you leave your feedback, I'll integrate into the Loom chrome extension repo locally to test out and see if there are any hiccups. I would say this is probably good to merge before then if we can get a more trivial example verified working.

@tshaddix
Copy link
Owner

@vhmth @jdolle Looking through this, this looks good to me. I do have some clarifying questions on the "root" problem we are trying to solve. Consider it devil's advocate and due diligence:

  • More efficient because less data is being transferred over the messaging pipeline. We have had this claim numerous times before. From a purely logical standpoint, you can say "sure that makes sense". That said, every time we have tried to quantify the impact it turns out to be negligible. Are we sure that sending state messages across the channel every time is more costly than a shallow diff every time? Not sure...

I would feel really confident in this change if we had some quantified proof of the performance issue. That said, I really don't see this change as having an earth shattering impact on perf either. So then we go back to "this brings us closer to Redux" which is true. I'm happy to move forward with testing it in Loom's extension, @vhmth . We won't be able to do that at GG right now, I'm afraid, or I would offer.

@jdolle
Copy link
Contributor Author

jdolle commented Sep 26, 2017

@tshaddix I am new to browser extensions and haven't done any performance tests, so I can't quantify the gains.

It seems logical that copying less data over the messaging API would improve performance, but I think the major performance gain will be because of the simplification to prop comparisons. Overriding the entire state every time causes components, that might not otherwise, to be flagged as dirty and therefore re-render. React.PureComponent does === comparisons to avoid the performance hit from deep comparisons. By replacing state you replace the reference and therefore === will be false. It is true that you could override shouldComponentUpdate to compare someValue.id or whatever unique identifier there exists, but this is an extra step and adds complexity.

@tshaddix
Copy link
Owner

@jdolle Ah - great point. Don't know how we missed that in #10 and #12. Good call.

Copy link
Collaborator

@vhmth vhmth left a comment

Choose a reason for hiding this comment

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

@jdolle did a round of sanity checking and things look good to go on my end. I would wait up for @tshaddix to also give a thumbs up on his end.

@tshaddix
Copy link
Owner

tshaddix commented Oct 8, 2017

@vhmth Alrighty - let's move this forward!

@tshaddix tshaddix merged commit 3e84d7f into tshaddix:master Oct 8, 2017
@tshaddix
Copy link
Owner

tshaddix commented Oct 8, 2017

@vhmth I don't believe this warrants a major release semver-wise - thoughts? This seems to land under a minor release unless we consider the port-messages to be part of our package's public "API"

@vhmth
Copy link
Collaborator

vhmth commented Oct 8, 2017

🎉🎉🎉🎉 great stuff @jdolle!

@tshaddix roger roger - seems fit for a minor release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants