-
Notifications
You must be signed in to change notification settings - Fork 109
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
Optimise & Refactor Records #214
Conversation
Hey Ronag, Interesting PR. I like the refactor for the path, I done the logic similar for the java client. Just had an interesting conversation about Regarding deepCopy, we have alot of less experienced developers assume that a copy is provided back. If you allow
That's interesting, since yes it makes it faster but it also means listeners would get notified with same data constantly if your setting equal data. Adding another flag would also be beneficial, ie If you could also give some before and after metrics to updates that would interesting. Cheers! |
In our case we have to perform that check anyway upstream in our application. So we basically end up with a lot of unnecessary checks.
Which should be the exception rather than the rule. |
@yasserf: Take a look now. I've made the behaviour configurable. |
64a4627
to
5bd4fe0
Compare
28f38c8
to
9f15a46
Compare
d3e959b
to
2fc9943
Compare
2fc9943
to
d394fb4
Compare
This ended up being a major refactoring & optimisation. |
216e644
to
ee22eb8
Compare
ee22eb8
to
0fd3844
Compare
…ther with the other async races.
Not sure why this is failing all of a sudden. All test pass fine on my local copy.
|
Note that this still has the "bad" conflict resolve behaviour (see #224) from the previous implementation. Otherwise all test don't pass. |
} | ||
|
||
this._sendUpdate( undefined, data ); | ||
this._applyChange( newValue ); |
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.
To fix #224 this should be:
if ( !utils.deepEquals( data, remoteData ) ) {
this._sendUpdate( undefined, data );
}
this._applyChange( jsonPath.set( this._$data, undefined, data, false ) );
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.
Makes sense!
I'm very keen on getting this PR merged and used as a baseline for the other async cases you mentioned. We have been doing some performance tests on deepstream and listening this entire week to ensure things work under heavy load and because of that we haven't been able to look into it yet. I will most likely merge this in once I guarantee tests are passing, and release it under a 1.1RC along side listening while we continue doing stress testing over the next couple of weeks. I apologise for the time mixup / delay, given the amount of new features in 1.1 we want to thoroughly test it with all our internal use cases before we release it into the wild! |
this.whenReady( function () { | ||
this._eventEmitter.on( args.path, args.callback ); | ||
args.callback( this.get( args.path ) ); | ||
}.bind(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.
In order to resolve #229 I think this should be:
this._eventEmitter.on( args.path, args.callback );
if ( this.isReady ) {
args.callback( this.get( args.path ) );
}
Of course this also requires that the initial read invokes callbacks, i.e. initial {}
!== read {}
function patch( oldValue, newValue, deepCopy ) { | ||
var i; | ||
|
||
if ( utils.deepEquals( oldValue, newValue ) ) { |
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'm a little confused, won't this run recursively every time and outweigh the benefit of having the deepCopy flag?
I can see it being an advantage when the flag is false since it will do literal object comparison, but when the flag is true it will have to do this on every object..
return deepCopy !== false ? utils.deepCopy( newValue ) : newValue;
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.
@yasserf: Not sure what you are worried about? The extra comparison? I would expect the performance impact to be negligible due to branch prediction. I would even expect V8 to optimize it when it notices that the parameter is effectively constant.
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 extra comparisonS.
deepEqual does a stringify twice. Since this is a recursive function it will do so on each individual item within the path.
If you compare the disadvantage of that with anyone who uses the deepCopy
as default: true
to the advantage of when it is false
I'm wondering how much more of a hit we are adding to the default usecase as a result.
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 point here is also to maintain reference equality (even if deepCopy is true). patch should maintain references if the new value is equal. This is so we don't need to use deepEquals
in _applyChange
. See, #213.
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.
Essentially, this also allows that any (including _applyChange
) e.g. React component that is backed by a deepstream record can use shallowCompare
.
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.
@yasserf: You mean the overlap of deepEquals. Yes, that is a future improvement I documented somewhere.
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 point here is also to maintain reference equality (even if deepCopy is true). patch should maintain references if the new value is equal.
Gotcha.
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.
@yasserf: It would only be a problem in practice for large deeply nested records...
Done a rebase onto master and added missing documentation. Merging it via #239 |
I know that currently this is not something that will get into deepstream but I would at least ask you to consider it, and possibly give some feedback, since we need it.
Our application is very record heavy and we have some problems with keeping stable 60 fps. We've already improved on this issue with #200 but we still have some performance issues.
A part form general refactoring and simplification:
Optimizations:
Fixes #172, #213
We could make even more use of
Object.create( null )
over{}
for jsonPath. However, jasmine test for types inisEqual
which would make some tests fail.