Gradually slower responsiveness to change events on Windows
Closed this issue ยท 32 comments
I use it with gulp and have some time leaking. Looks like the problem in globs.
Also on a bigger project, where I found this problem, for nested files creates nested.css-jds43J.TMP
like files for a few miliseconds. Saw it in sublime sidebar
var gulp = require('gulp');
var chokidar = require('chokidar');
gulp.task('build', function () {
return gulp.src('src/main.css')
.pipe(gulp.dest('dist'));
});
gulp.task('dev', function () {
chokidar.watch('src/**/*.css')
.on('change', function () {
gulp.start('build');
})
})
File structure
src/main.css
src/include/nested.css
Log
[13:07:10] Starting 'dev'...
[13:07:10] Finished 'dev' after 4.38 ms
// A few changes in a row and periodical changes in main.css
[13:07:11] Starting 'build'...
[13:07:11] Finished 'build' after 54 ms
[13:07:11] Starting 'build'...
[13:07:11] Finished 'build' after 27 ms
[13:07:11] Starting 'build'...
[13:07:11] Finished 'build' after 19 ms
[13:07:12] Starting 'build'...
[13:07:12] Finished 'build' after 17 ms
[13:07:12] Starting 'build'...
[13:07:12] Finished 'build' after 23 ms
[13:07:14] Starting 'build'...
[13:07:14] Finished 'build' after 26 ms
[13:07:14] Starting 'build'...
[13:07:14] Finished 'build' after 10 ms
[13:07:14] Starting 'build'...
[13:07:14] Finished 'build' after 19 ms
// Periodical changes in nested.css
[13:07:17] Starting 'build'...
[13:07:18] Finished 'build' after 295 ms
[13:07:19] Starting 'build'...
[13:07:19] Finished 'build' after 321 ms
[13:07:20] Starting 'build'...
[13:07:20] Finished 'build' after 305 ms
[13:07:21] Starting 'build'...
[13:07:22] Finished 'build' after 341 ms
[13:07:24] Starting 'build'...
[13:07:24] Finished 'build' after 387 ms
[13:07:26] Starting 'build'...
[13:07:26] Finished 'build' after 336 ms
[13:07:29] Starting 'build'...
[13:07:29] Finished 'build' after 361 ms
[13:07:31] Starting 'build'...
[13:07:31] Finished 'build' after 397 ms
[13:07:34] Starting 'build'...
[13:07:34] Finished 'build' after 451 ms
[13:07:36] Starting 'build'...
[13:07:37] Finished 'build' after 368 ms
[13:07:38] Starting 'build'...
[13:07:38] Finished 'build' after 425 ms
[13:07:40] Starting 'build'...
[13:07:41] Finished 'build' after 464 ms
[13:07:43] Starting 'build'...
[13:07:43] Finished 'build' after 497 ms
[13:07:45] Starting 'build'...
[13:07:45] Finished 'build' after 429 ms
[13:07:47] Starting 'build'...
[13:07:47] Finished 'build' after 491 ms
[13:07:49] Starting 'build'...
[13:07:49] Finished 'build' after 540 ms
// A few changes in a row in nested.css
[13:07:52] Starting 'build'...
[13:07:55] Finished 'build' after 3.04 s
// Again periodical changes
[13:15:57] Starting 'build'...
[13:15:58] Finished 'build' after 669 ms
[13:15:59] Starting 'build'...
[13:16:00] Finished 'build' after 681 ms
[13:16:03] Starting 'build'...
[13:16:03] Finished 'build' after 725 ms
// Changes in main.css
[13:16:06] Starting 'build'...
[13:16:06] Finished 'build' after 23 ms
[13:16:07] Starting 'build'...
[13:16:07] Finished 'build' after 9.2 ms
[13:16:07] Starting 'build'...
[13:16:07] Finished 'build' after 17 ms
Tried gulp.watch
. It works fine with exception it is gaze :).
Chokidar isn't creating the temp files, something else is.
Based on your log I don't see why you'd be blaming chokidar. The increased times are happening between chokidar emitting a change
event and the completion of build
.
It looks like you've oversimplified your gulpfile example, as something would need to be processing your @import
s rather than just copying main.css
as-is each time. I suspect the answer to this is somewhere in the parts you've left out. What you're showing isn't really that time is leaking, just that build
takes a lot longer whenever you change your nested file.
I don't know why you've observed a difference with with gulp.watch
. Maybe rather than using chokidar directly you could try the gulp-watch
plugin.
@es128 I didn't simplify it. I just removed everything that do not affect on my problem. Will make a repo to reproduce it.
What's the point of watching all css files and then just copying main.css
from src
to dest
? Where do the nested css files come into play?
My builder uses postcss-import for this. And with it and without I have the same problem.
Ok, but nonetheless how is chokidar involved in increased times between starting build and finishing it? By the time you start, chokidar has already emitted its change
event.
Also this problem only on windows.
Hm.. on my home computer everything is fine. Something wrong with that machine
@es128 https://github.com/TrySound/chokidar-leaking-test
I reproduced the problem on my win8 and win7-vm. Also my colleague has the same problem with win7.
Ok, but nonetheless how is chokidar involved in increased times between starting build and finishing it? By the time you start, chokidar has already emitted its change event.
Your evidence indicates slowness in builds, not in watching and responsiveness of change
events.
You made a comment in your repo that you ruled out gulp as the culprit, but you didn't explain how. If you want me to investigate this, please provide evidence that uses only chokidar.
Btw try gulp.watch
with latest gulp 4, which uses chokidar
@es128 I saw chokidar in gulp.watch. It's just chokidar. Gulp doesn't matter. When I use it without gulp i got the same brake. I just don't know how to catch keypress in background and compare it with watch end. I added index.js into repo with only chokidar and hrtime to try. Wihout gulp speed decreases slower, but still decreases.
This still isn't described or demonstrated well enough for there to be anything actionable yet, but ok reopening. Let's keep trying to narrow down what's going on.
I just don't know how to catch keypress in background and compare it with watch end
fs.writeFile
. To better demonstrate this problem, you should create a script that writes to a file on an interval and benchmark the time to detect the event.
Does usePolling: true
have any impact on this phenomenon?
Polling will be slower and consume more CPU - especially if you're watching a lot of files.
Chokidar's algorithms for handling polling vs non-polling on Windows are nearly identical, so it's starting to point toward being a bug in fs.watch
on Windows or the ReadDirectoryChangesW
system API it uses. Or perhaps some combination of using those and doing readdir
calls. I don't know why the glob pattern would make a difference though.
If you can get to the point of reliably demonstrating the issue, we could see if it could still be demonstrated using fs.watch
directly instead of chokidar. And if that proves out, report it to node.
I think I have the same issue here: #405
I'm getting this same problem with Gulp 4 using the following gulp file.
let gulp = require('gulp');
let rename = require('gulp-rename');
function styles() {
return gulp.src('src/**/*.scss')
//Issue happens with or without this rename plugin
.pipe(rename({extname: '.test'}))
//Issue only happens if destination directory is same as source directory
.pipe(gulp.dest('src'));
}
gulp.task('watch', function() {
//only happens if there is a glob here
gulp.watch('src/**/test.html', styles);
});
Running gulp watch
outputs:
If I change the watch statement to use polling the issue doesn't occur
gulp.watch('src/**/test.html', {usePolling: true}, styles);
Attached is a minimal app that reproduces the issue
gulp-issue.zip
I am using the following versions
node: v7.2.0
npm: 3.10.9
OS: Windows 10
Gulp CLI: 1.2.2
Local Gulp: 4.0.0-alpha.2
help please ((
gulpjs/gulp#1903 # @
This is a pretty old issue, but I've noticed that I'm seeing the same problem. Did anyone here ever find a solution other than switching to polling?
Hey @JustMaier - I did a little bit more and switched OS ๐
Anyway... in the last year or so chokidar was quite stable on Windows machines I used.
Perhaps there's something to do with improvements in the core of Node?
Thanks for the great idea @gustavohenke.
I was on node 6.6.2
and I updated to 8.9.0
and now it works great.
If anyone stumbles across this, update your version of node!
@JustMaier, tried node 8.9.0 - same result for me. Guess we stuck with polling.
@anwerso, sorry to hear that. What version of chokidar are you running? I'm just wondering what the difference is between our team setup and yours.
Here's what we're running:
OS: Windows 10 15063.674
Node: 8.9.0
Gulp: 4 Alpha 2
Chokidar: 1.4.3
@JustMaier, I use the latest Gulp from the repo:
OS: Windows 10 15063.674
Node: 8.9.0
Gulp: 4 Alpha 2
Chokidar: 1.7.0
@JustMaier, tried to downgrade chokidar, same results. It seems the problem somewhere else, probably in the task config.
@anwerso Looks like I was incorrect. It seems to still be a problem with files that were pulled into the pipe via globbing (**/*.js
)
What's odd is that in my case, things only slow down if there are globs in the gulp src. If there are only globs on the watch list then everything works fine.
Still the case with node 8.11.4
Using usePolling is intead fixing this issue but dont know if this is a good thing to do.
As the Gulp/watch documentation is saying that
usePolling | boolean | false | When false, the watcher will use fs.watch() (or fsevents on Mac) for watching. If true, use fs.watchFile() polling instead - needed for successfully watching files over a network or other non-standard situations. Overrides the useFsEvents default.This option is passed directly to chokidar.
And the Chokidar documentation also
usePolling (default: false). Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU utilization, consider setting this to false. It is typically necessary to set this to true to successfully watch files over a network, and it may be necessary to successfully watch files in other non-standard situations. Setting to true explicitly on OS X overrides the useFsEvents default. You may also set the CHOKIDAR_USEPOLLING env variable to true (1) or false (0) in order to override this option.
I came to the conclusion that usePolling
is set to true when your files are on a shared network drive or your files are in an other non-standard situations.
I guess i am in the non standard situations category but i don't know why.
Is it because my source files and dest files are in the same root folder ? (sorry can't paste my gulpfile here)
But the gulpfile written above by @robianmcd is quite similar to mine because the source files and dest files are in the same root folder.
let rename = require('gulp-rename'); function styles() { return gulp.src('src/**/*.scss') //Issue happens with or without this rename plugin .pipe(rename({extname: '.test'})) //Issue only happens if destination directory is same as source directory .pipe(gulp.dest('src')); } gulp.task('watch', function() { //only happens if there is a glob here gulp.watch('src/**/test.html', styles); }); ```
Update to Chokidar v3, it should resolve this.