-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
angularfire2@5.0.0-rc.7.0-next Change Detection Irregularities #1583
Comments
Commendable research job you've done looking into this issue. |
Hey @byrondover! Thank you so much for the in depth work on this issue. I wish they all were like this! I'm going to page @jamesdaniels who was the implementer of |
Does this means its not emitting events when it should be? I've had the opposite experience (emitting double events when nothing has changed). In order to solve, use a hash function on the object and distinctUntilChanged operator. |
Just cut a new https://stackblitz.com/edit/angular-fau5ia?file=app/example/example.component.ts Really appreciate the time you spent diagnosing this, it allowed me to zero in on the bad spot in the code immediately. |
I can confirm Thank you, @jamesdaniels! I hate to drop this on you without more concrete details, but upon further testing, I am also noticing a significant drop in application performance under production workloads after upgrading Here's a summary of the behavior I'm seeing. Before
https://stackblitz.com/edit/angular-bqw1xv After
https://stackblitz.com/edit/angular-gjyz3e In the contrived StackBlitz examples above, this may not have much impact. But in a large Angular application with dozens of active, concurrent Firebase queries, this behavior change results in a significant drop in page performance prior to Angular stability (empty task queue). I'm seeing one large production Angular app I contribute to freeze completely for several seconds when users route to the dashboard component, as FPS drops to 0 and the CPU pegs on I know this is a nebulous issue to raise without source code to demonstrate the impact (unfortunately I'm not at liberty to share source code from the aforementioned app's private repo), but I'd be happy to share production Chrome Dev Tools performance profiles privately with you and @davideast, if they could be of any help. If nothing else, I'd just like to put this on your radar, in case performance issues surface with any other AngularFire users. I have no doubt we can find ways to work around the performance impact in production; if I have time to dig into this and come up with any more pertinent details, I'll open a new issue. Thank you again for the quick fix, James! Please feel free to close this issue, at your discretion. |
We're aware of the blocking before It should not however drop your frames, I'll look into that. I'm going to be working with a Zone.js maintainer to make sure that we're doing this the "right" way in the future. |
Thank you for the clarification, James! If I can help or provide anything further, please let me know. |
@byrondover I just cut a new |
@jamesdaniels Surprisingly, upgrading to It helped a bit on the initial delay before interactivity, but for whatever reason, passing Firebase object references through I was able to dramatically improve performance in the browser by reverting export function createObjectReference<T>(query: DatabaseQuery, afDatabase: AngularFireDatabase): AngularFireObject<T> {
return {
query,
+ snapshotChanges: createObjectSnapshotChanges(query),
- snapshotChanges<T>() {
- const snapshotChanges$ = createObjectSnapshotChanges(query)();
- return afDatabase.scheduler.keepUnstableUntilFirst(
- afDatabase.scheduler.runOutsideAngular(
- snapshotChanges$
- )
- );
- },
update(data: Partial<T>) { return query.ref.update(data as any) as Promise<void>; },
set(data: T) { return query.ref.set(data) as Promise<void>; },
remove() { return query.ref.remove() as Promise<void>; },
valueChanges<T>() {
+ return createObjectSnapshotChanges(query)()
+ .map(action => action.payload.exists() ? action.payload.val() as T : null);
- const snapshotChanges$ = createObjectSnapshotChanges(query)();
- return afDatabase.scheduler.keepUnstableUntilFirst(
- afDatabase.scheduler.runOutsideAngular(
- snapshotChanges$
- )
- ).map(action => action.payload.exists() ? action.payload.val() as T : null)
},
}
} Obviously this defeats the purpose, and I've since abandoned these reversions, but for whatever it's worth this did clear up the performance issues entirely. Further investigation revealed a discrepancy between the number of events emitted by Adding debug logging to database/observable/fromRef.ts confirmed Firebase references emitting the expected number of Strange. And unfortunately, as of right now, not reproducible in StackBlitz (I'll keep poking at it). Good news is, we were able to work around the issue in production without much hassle by adding |
That's just bizarre... sounds like maybe the scan isn't collapsing things as expected. I'll call this good for now and keep an eye on this :/ if you are able to repro let me know. I'll sync up with the zone folks too and review after Google I/O. |
You know maybe it's because I dropped the observeOn queue... that's the only other thing I changed since it only seems to create bottlenecks and false assurances (at least in my test apps). Maybe dropping it is losing some magic at the larger scale that I'm not immediately thinking of. |
@byrondover would you mind shooting me an email at jamesdaniels@google.com so we can setup a meeting RE your use of the lib + the performance issues. My calendar is pretty full for the next week and a half but after that we can see if I can find out what exactly is wrong. Thank you very much for all your help in diagnosing these issues. |
@jamesdaniels Just sent you an email! I think you may be onto something with the scan not collapsing idea. One thing I noticed is the Side note—I submitted a PR (#1588) with the changes I alluded to earlier. It feels more like a workaround at this point than a proper fix, so feel free to close if you think it's not the right direction, but I figured I should at least show my work so you can see what's functioning for me in production right now. 🙂 |
I'm experiencing a reproducible change detection issue with
angularfire2@5.0.0-rc.7.0-next
, where the first emissions fromsnapshotChanges()
andvalueChanges()
are not triggering Angular change detection appropriately.https://stackblitz.com/edit/angular-nkqyhq
As demonstrated in the StackBlitz example above, the first values emitted by AngularFireDatabase
valueChanges()
Observables are being populated as expected, but UI is not redrawing automatically (unless triggered manually, or by something else). SubsequentvalueChanges()
emissions appear to trigger change detection as expected, reproducible in the above example by navigating away from and back to the example routed component.This issue first appears with the merging of #1454 (commit e343f13).
I haven't had a chance to dig into it, but this behavior appears to be related to the new
FirebaseZoneScheduler
; the current implementation of thekeepUnstableUntilFirst()
method in particular has me a bit puzzled.https://github.com/angular/angularfire2/blob/master/src/core/angularfire2.ts#L25-L33
Version info
Angular: 5.2.10
Firebase: 4.12.1
AngularFire: 5.0.0-rc.7.0-next
Browser: Chrome OS v66.0.3359.139
Operating system: macOS Sierra v10.12.6
How to reproduce these conditions
Failing test unit, Plunkr, or JSFiddle demonstrating the problem
https://stackblitz.com/edit/angular-nkqyhq
Steps to set up and reproduce
AngularFireDatabase
valueChanges()
ObservableDebug output
** Errors in the JavaScript console **
None.
** Output from
firebase.database().enableLogging(true);
**Not sure how to enable this.
** Screenshots **
N/A
Expected behavior
First value emitted from
AngularFireDatabase.valueChanges()
Observable consistently triggers change detection.Actual behavior
First value emitted from
AngularFireDatabase.valueChanges()
Observable does not consistently trigger change detection.The text was updated successfully, but these errors were encountered: