grunt-contrib-watch icon indicating copy to clipboard operation
grunt-contrib-watch copied to clipboard

High CPU usage

Open asolopovas opened this issue 9 years ago • 24 comments

Hi, Grunt Watch consumes about 65-70% CPU Resources.

my devDependencies are as follows.

  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-uglify": "^0.9.1",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-sass": "^0.18.1",
    "load-grunt-tasks": "^3.1.0",
    "node-bourbon": "^4.2.1-beta1"
  }

my gruntfile:

var path = "C:/gdrive/apps/3oak/wp-content/themes/3flooring/";
module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt); // npm install --save-dev load-grunt-tasks
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        // Watch ===========
        watch: {
            // Sass -----
            sass: {
                files: [
                    path + 'components/sass/*.{scss,sass}',
                    path + 'components/sass/styles/*.{scss,sass}',
                    path + 'components/sass/styles/custom/*.{scss,sass}',
                    path + 'components/sass/styles/custom/**/*.{scss,sass}'
                    ],
                tasks: ['sass']
            },
            // Reload -
            livereload: {
                files: [
                    path + '*.php',
                    path + '**/*.php',
                    path + '**/**/*.php',
                    path + 'js/*.{js,json}',
                    path + 'js/**/*.{js,json}',
                    path + 'components/sass/*.{scss,sass}',
                    path + 'components/sass/**/*.{scss,sass}',
                    path + 'components/sass/**/**/*.{scss,sass}'],
                options: {
                    livereload: true
                }
            },
            // Scripts -
            scripts: {
                files: [
                    path + 'components/js/*.{js,json}'
                    ],
                tasks: ['uglify']
            }, // scripts
        },
        sass: {
            dist: {
                options: {
                    sourceMap: true,
                    includePaths: [
                        require('node-bourbon').includePaths,
                        path + 'components/sass/*.{scss,sass}',
                        path + 'components/sass/**/*.{scss,sass}'
                    ],
                    outputStyle: 'nested',
                    lineNumbers: true,
                },
                files: [
                    {src: path + 'components/sass/style.scss', dest: path + 'style.css'}
                ],
            }
        },
        // Uglify 
        uglify: {
            my_target: {
                options: {
                    sourceMap: true,
                    sourceMapName: path + 'scripts.min.map'
                },
                files: [
                    {src: path + 'components/js/*.js', dest: path + 'js/scripts.min.js'}
                ],
            }
        }
    });
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.registerTask('default', 'watch');
};

asolopovas avatar Apr 16 '15 09:04 asolopovas

Same problem here. CPU stays at 50% on my i7 3770. Running on Windows 7.

We are probably watching between 500-1000 files.

acollard avatar Jun 08 '15 16:06 acollard

I am also experiencing this issue on OSX 10.10.4 with grunt v0.4.5 and grunt-contrib-watch 0.6.1.

There are several other issues that seem to be related but apparently the underlying problem has not been fixed: https://github.com/gruntjs/grunt-contrib-watch/issues/35 https://github.com/gruntjs/grunt-contrib-watch/issues/145

I tried everything mentioned in those issues and nothing helped. Grunt is always using about 70% of my CPU and fseventsd is using about 15%.

Stratus3D avatar Jul 23 '15 15:07 Stratus3D

Have to work on few projects (4-5) with grunts running in parallel, CPU usage in total is around 100% all the time .. single process is watching about 2000 files, and CPU goes up to 20-25 % And that is when I don't change files. If I comment out watch task, and leave only express running, CPU goes down to 2% Machine: SSD stripe 240GB, i7 quad cores, 16 GB RAM

kiril-chilingarashvili avatar Aug 18 '15 07:08 kiril-chilingarashvili

I'm also seeing the same issue on OS X 10.10 with node 4.1.0 and grunt-contrib-watch 0.6.1.

yang avatar Sep 25 '15 08:09 yang

Same issue here, but watching just 10 files. Grunt is using 100% of the CPU.

rogeraleite avatar Sep 30 '15 09:09 rogeraleite

Have you tried this

options: { interval: 1000 },

partnuz avatar Nov 13 '15 21:11 partnuz

That increases the latency and hurts the instantly responsive illusion.

yang avatar Nov 22 '15 06:11 yang

I have the same issue with grunt 0.4.5 and grunt-watch 0.6.1 on OSX 10.10.5 Even with the interval option the CPU usage jumps to 100% as soon as I edit a file. And I have only about 10 files to watch!

netzbandit avatar Dec 15 '15 14:12 netzbandit

@partnuz: this worked for me

msierks avatar Jan 25 '16 21:01 msierks

Same problem with grunt 0.4.5 and grunt-watch 0.6.1 windows 7, watching 12 files, 100% CPU usage when editing files

eddyerburgh avatar Feb 29 '16 11:02 eddyerburgh

options: { interval: 1000 },

hurts the instantly responsive illusion, but using a lower number, as 300, reduced my CPU usage from 50% to 3-10%...

Good workaround until we figure something else.

HugoHeneault avatar Mar 03 '16 10:03 HugoHeneault

Switching to https://github.com/JimRobs/grunt-chokidar (forked off of grunt-contrib-watch but uses chokidar instead of gaze for file system watching) drops my CPU usage from ~25% to somewhere near 0% with the same functionality.

@shama @tkellen Would you consider a pull request to switch the underlying lib from gaze to chokidar?

callmevlad avatar May 01 '16 00:05 callmevlad

@callmevlad see https://github.com/gruntjs/grunt-contrib-watch/issues/314

vladikoff avatar May 01 '16 00:05 vladikoff

@vladikoff Thanks for the link! That issue is from a few years ago, and seems to make claims about Gaze >= 0.6 that don't seem to be true today at 1.0.0 (like not using native OS events instead of polling, for example), so I was hoping that decision would be revisited.

It would be great to get @shama's thoughts around which changes in https://github.com/JimRobs/grunt-chokidar/commit/a0f15e748bf8d5f5fcbf56022b0495e351819ff9 are incompatible two years later, or at least start a discussion around why gaze must take up so much CPU as the number of watched files grows.

callmevlad avatar May 01 '16 02:05 callmevlad

@callmevlad [email protected] experimented with going fully to native events. It was certainly faster and consumed far less CPU but it caused a lot of issues. One issue is building the native addon can be challenging for users, especially on Windows. So 1.0.0 is basically an updated 0.5, tabling going full native for now.

I'm not against revisiting chokidar though. It's been awhile since I've evaluated implementing it here. AFAIK, chokidar requires the native addon fsevents to be built on OSX (which isn't too bad) and just uses fs.watch for other platforms. If chokidar is actually passing all the tests here as a drop in replacement for gaze, then they've certainly came a long way and I'd be really open to consider it.

shama avatar May 01 '16 03:05 shama

Hey guys! About this options: { interval: 1000 }, - where do I set this ? I'm working with Magento 2.0 and I'm setting grunt.option('interval', 300); in project's Gruntfile.js but my CPU is still 100% loaded...

Any idea why it doesn't work ?

Below you can see my Gruntfile.js

// For performance use one level down: 'name/{,*/}*.js'
// If you want to recursively match all subfolders, use: 'name/**/*.js'
module.exports = function (grunt) {
    'use strict';

    //grunt.option.init(); // best4u
    grunt.option('interval', 300); // best4u
    grunt.log.write(grunt.option.flags()); // best4u

    var _ = require('underscore'),
        path = require('path'),
        themes = require('./dev/tools/grunt/configs/themes'),
        configDir = './dev/tools/grunt/configs',
        taskDir = './dev/tools/grunt/tasks';

    [
        taskDir + '/mage-minify',
        taskDir + '/deploy',
        taskDir + '/black-list-generator',
        taskDir + '/clean-black-list',
        taskDir + '/static',
        'time-grunt'
    ].forEach(function (task) {
        require(task)(grunt);
    });

    require('load-grunt-config')(grunt, {
        configPath: path.join(__dirname, configDir),
        init: true,
        jitGrunt: {
            staticMappings: {
                usebanner: 'grunt-banner'
            }
        }
    });

    _.each({
        /**
         * Assembling tasks.
         * ToDo: define default tasks.
         */
        default: function () {
            grunt.log.subhead('I\'m default task and at the moment I\'m empty, sorry :/');
        },

        /**
         * Production preparation task.
         */
        prod: function (component) {
            var tasks = [
                'less',
                'autoprefixer',
                'cssmin',
                'usebanner'
            ].map(function(task){
                return task + ':' + component;
            });

            if (typeof component === 'undefined') {
                grunt.log.subhead('Tip: Please make sure that u specify prod subtask. By default prod task do nothing');
            } else {
                grunt.task.run(tasks);
            }
        },

        /**
         * Refresh themes.
         */
        refresh: function () {
            var tasks = [
                'clean',
                'exec:all'
            ];
            _.each(themes, function(theme, name) {
                tasks.push('less:' + name);
            });
            grunt.task.run(tasks);
        },

        /**
         * Documentation
         */
        documentation: [
            'replace:documentation',
            'less:documentation',
            'styledocco:documentation',
            'usebanner:documentationCss',
            'usebanner:documentationLess',
            'usebanner:documentationHtml',
            'clean:var',
            'clean:pub'
        ],

        'legacy-build': [
            'mage-minify:legacy'
        ],

        spec: function (theme) {
            var runner = require('./dev/tests/js/jasmine/spec_runner');

            runner.init(grunt, { theme: theme });

            grunt.task.run(runner.getTasks());
        }
    }, function (task, name) {
        grunt.registerTask(name, task);
    });
};

vasilii-b avatar May 30 '16 08:05 vasilii-b

@vasilii-b grunt.option() is an interface for command line options. So grunt.option('stack', true) in your Gruntfile is effectively the same as grunt --stack.

interval is a grunt-contrib-watch task option that is defined in the options of the task itself: http://gruntjs.com/configuring-tasks#options

Unfortunately your above Gruntfile is hiding the config so I'm not sure where that custom Gruntfile implementation expects watch task options. Typically with Gruntfiles, we recommend being explicit with the config:

grunt.initConfig({
  watch: {
    options: {
      // Options for the watch task go here
      interval: 5000
    },
    stuff: {
      files: ['src/*.js'],
      tasks: ['concat']
    }
  }
});

shama avatar May 30 '16 15:05 shama

This has been bothering me for a while and I finally decided to look around today (my fan was constantly on). I tried the above mentioned chokidar fork and my CPU usage is pretty much unnoticeable. My only concern is that that fork hasn't been actively maintained. It'd be great if that could be integrated into this extension.

I'm on Linux if that makes a difference. Based on this it seems like it works well on a Mac as well.

aiguofer avatar Oct 05 '16 00:10 aiguofer

We ended up switching away from grunt-contrib-watch-based file watching to use pm2 watchers (which use chokidar under the hood) since we had to turn up the AC in the office to compensate for all the warm computers in the room caused by this issue 😬

callmevlad avatar Oct 05 '16 02:10 callmevlad

Any activity planned on this one? Watch is still a problem. Grunt-chokidar solves it but is unmaintained and has few cosmetic issues.

rnemec avatar Mar 17 '17 02:03 rnemec

I'm surprised this issue hasn't gotten more attention. Tons of web developers are at coffee shops with no power and here grunt-watch-contrib is eating up battery.

FWIW chokidar is pretty horrible on Windows and as proof VSCode stopped using it years ago on windows and wrote their own. The do use chokidar on Linux and Mac or did last time I checked. For Windows they wrote some small C# program and read its streamed output

https://github.com/microsoft/vscode/tree/master/src/vs/platform/files/node/watcher/win32

greggman avatar Jul 24 '19 05:07 greggman

I'm still experiencing this on grunt-contrib-watch version 1.1.0

CVertex avatar May 11 '20 06:05 CVertex

So it's almost 9 years now since the issue have been reported. Any progress on this? Is this repo still alive?

meszaros-lajos-gyorgy avatar Dec 29 '23 22:12 meszaros-lajos-gyorgy

Okay, just use nodemon and let this repo die silently.

meszaros-lajos-gyorgy avatar Jan 31 '24 12:01 meszaros-lajos-gyorgy