-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
watch: Debounce all files updates into a single event. #51988
Conversation
@MoLow what do you think about this one ? |
As to my understanding, the issue described in #51954 (comment) isn't caused by the lack of debounce, but from a race condition where |
There are two problems described (although admittedly not very clearly) in issue #51954:
The first one is tackled by your PR #51992 The second problem, which also causes too many un-necessary restarts, is due to the fact that the current behavior does not act as a "debounce" but actually acts more as a "delayed throttle". Here is the definition of Debounce and Throttle
The current behavior is a mix between these two modes: The File watcher will wait X ms before emitting the first event, and will then continue emitting events (if the same file keep being updated) every X ms. In practice, this means that if the same file gets updated every 100ms, the The issue is even worse when multiple files are concerned. Indeed, consider the following scenario (e.g. during a build or git checkout):
As you can see in this example, steps 10 to 13 yield un-necessary restarts. How many un-necessary restarts will depend on the number of file updated, the frequence at which they are updated, and the time the app takes to gracefully exit. But it is safe to say that updating files faster than the expected debounce rate (200ms) causes more restarts than needed. I would expect that only files updated slower than every 200 ms trigger multiple updates, not when updates are fasters than 200 ms. This is probably the main reason why tests are "flacky". Part of the flackyness is due to the behavior of the watcher and not to IO / performance reasons. node/test/parallel/test-watch-mode-files_watcher.mjs Lines 69 to 70 in 73025c4
This PR fixes that by:
|
Grouping all updated in a single event is something that was also suggested by @atlowChemi here |
Wouldn't this be a simpler fix with the same effect? #51986 |
this.emit('changed', { owners }); | ||
this.#debounceOwners = new SafeSet(); |
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.
this.#debounceOwners = new SafeSet(); | |
this.#debounceOwners.clear(); |
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 reason I did that is to allow async processing of the owners
by the listeners. I figured it would be more efficient to swap the Set
rather than doing:
const owners = new Set(this.#debounceOwners);
this.emit('changed', { owners });
this.#debounceOwners.clear();
What do you think ?
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 you think that async processing of the event is not something we should care about here, then I can just implement your change.
Co-authored-by: Yagiz Nizipli <[email protected]>
Hello @MoLow, The changes you suggested in #51986 have several issues:
|
Hey guys, any feedback you'd like to share on this ? |
It might be worth noting that one of the reason why it may have appeared as a single issue before, is that when trying to provide a solution (eg. in main...matthieusieben:node:patch-2), I provided an implementation that fixed both underlying causes by wrapping the |
Partially fixes #51954 by reducing the amount of
changed
events in watch mode.