Skip to content
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

Very high CPU usage using pnpm #63

Closed
flayks opened this issue Jan 22, 2020 · 21 comments
Closed

Very high CPU usage using pnpm #63

flayks opened this issue Jan 22, 2020 · 21 comments

Comments

@flayks
Copy link

flayks commented Jan 22, 2020

Maybe I've done something wrong but even with the dumbest config ever I feel like I have an error while running nollup in order to get HMR working for my CSS and Javascript.

I always get this output in the terminal whatever config I'm using (tried many, from some other repos, etc). The only way for me to get it working is by using the examples as it from the examples folder of this repo, which calls the cli from a javascript file. When I try to use the nollup -c command, that's when issues are coming by.

> npm run dev

> test-nollup@1.0.0 dev /Users/user/Desktop/Rollup
> nollup -c --hot --port 3000

Listening on http://localhost:3000
Compiled in 944ms.
Compiled in 441ms.
^C%

Also the node process in my Activity monitor goes off the roof with at least 300% CPU.

This is my package.json

{
  "name": "test-nollup",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "build": "cross-env NODE_ENV=development nollup -c nollup.config.js -w --hot --content-base build --port 3000 --verbose",
    "dev": "nollup -c --hot --port 3000"
  },
  "dependencies": {
    "normalize.css": "^8.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.8.3",
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@babel/plugin-transform-runtime": "^7.8.3",
    "@babel/preset-env": "^7.8.3",
    "@babel/runtime": "^7.8.3",
    "@rollup/plugin-commonjs": "^11.0.1",
    "@rollup/plugin-node-resolve": "^7.0.0",
    "@rollup/plugin-replace": "^2.3.0",
    "autoprefixer": "^9.7.4",
    "cross-env": "^6.0.3",
    "eslint-config-standard": "^14.1.0",
    "eslint-plugin-import": "^2.20.0",
    "eslint-plugin-node": "^11.0.0",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.1",
    "node-sass": "^4.13.1",
    "nollup": "^0.10.2",
    "postcss": "^7.0.26",
    "postcss-banner": "^3.0.1",
    "postcss-preset-env": "^6.7.0",
    "rollup": "^1.29.0",
    "rollup-plugin-babel": "^4.3.3",
    "rollup-plugin-banner": "^0.2.1",
    "rollup-plugin-browsersync": "^1.1.0",
    "rollup-plugin-bundle-html": "^0.2.2",
    "rollup-plugin-clear": "^2.0.7",
    "rollup-plugin-dev": "^1.1.1",
    "rollup-plugin-eslint": "^7.0.0",
    "rollup-plugin-hot-css": "^0.0.6",
    "rollup-plugin-postcss": "^2.0.3",
    "rollup-plugin-serve": "^1.0.1",
    "rollup-plugin-terser": "^5.2.0"
  },
  "browserslist": [
    "> 0.5%",
    "last 2 versions",
    "not dead"
  ]
}

and my rollup.config.js

import resolve from '@rollup/plugin-node-resolve'
import replace from '@rollup/plugin-replace'
import commonjs from '@rollup/plugin-commonjs'
import babel from 'rollup-plugin-babel'
import devserver from 'rollup-plugin-dev'
import browsersync from 'rollup-plugin-browsersync'
import postcss from 'rollup-plugin-postcss'
import clear from 'rollup-plugin-clear'
import html from 'rollup-plugin-bundle-html'
import banner from 'rollup-plugin-banner'
import { terser } from 'rollup-plugin-terser'
import { eslint } from 'rollup-plugin-eslint'
import pkg from './package.json'
// import settings from './settings.json'

// Define environment and things
const mode = process.env.NODE_ENV
const watch = process.env.ROLLUP_WATCH
const dev = mode === 'development'
const workdir = dev ? 'build' : 'dist'

// Rollup config
export default {
	input: 'src/main.js',
	output: {
		dir: dev ? 'build' : 'dist',
		entryFileNames: '[name]-[hash].js',
		chunkFileNames: '[name]-[hash].js',
		sourcemap: dev,
		format: 'cjs'
	},

	// Plugins
	plugins: [
		// Clean
		// clear({
		// 	targets: [ workdir ],
		// 	watch: true
		// }),

		// Serve
		// dev && watch && devserver({
		// 	port: 3100,
		// 	dirs: [ workdir ],
		// 	basePath: '/'
		// }),
		// dev && watch && browsersync({
		// 	port: 3000,
		// 	proxy: 'http://localhost:3100',
		// 	open: false,
		// 	notify: false
		// }),

		// PostCSS with SASS/SCSS/Stylus
		// postcss({
		// 	extract: true,
		// 	sourceMap: dev
		// }),

		// Javascript
		// replace({
		// 	'process.browser': true,
		// 	'process.env.NODE_ENV': JSON.stringify(mode)
		// }),
		// resolve({
		// 	browser: true
		// }),
		// commonjs(),
		// eslint({
		// 	exclude: ['**/*.scss', 'node_modules/**']
		// }),
		// babel({
		// 	extensions: ['.js', '.mjs', '.html'],
		// 	exclude: ['node_modules/**'],
		// 	runtimeHelpers: true
		// }),

		// Build
		// html({
		// 	template: 'src/template.html',
		// 	dest: workdir,
		// 	filename: 'index.html'
		// }),
		// !dev && terser({
		// 	module: true,
		// 	output: {
		// 		comments: false
		// 	}
		// }),
		// !dev && banner(`${pkg.name} v${pkg.version}\nBy ${pkg.author.name}\n${pkg.author.url}`)
	]
}

Am I missing something ? 🤪

@PepsRyuu
Copy link
Owner

PepsRyuu commented Jan 22, 2020

Hey @flayks!

If no error is being thrown in the terminal, it means that the bundle should be accessible.

What happens if you open http://localhost:3000? Is there an index.html file being served? I noticed in your dev command that ---content-base isn't pointing to anything. Are you able to open http://localhost:3000/main.[hash].js?

CPU usage is very concerning. My initial guess is that there's potentially an infinite loop happening when parsing the files. Is there anything note-worthy or unusual in the code like circular dependencies or any big libraries that you're using?

@flayks
Copy link
Author

flayks commented Jan 22, 2020

I made some tweaks to follow pretty much exactly what the examples are (public folder with an index.html including the script to /main.js file), but it seems that I have the same issues, 440% CPU.

This way, the page loads and I have a result but the fans of my laptop are not happy about it haha

"scripts": {
   "dev": "cross-env NODE_ENV=development nollup -c nollup.config.js --content-base public --port 3000 --hot"
}

I also changed my rollup config to minimum in order to track issues but that's pretty much the best I could do I'm afraid

import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'

// Rollup config
export default {
	input: './src/main.js',
	output: {
		dir: 'dist',
		format: 'esm',
		entryFileNames: '[name].js'
	},

	// Plugins
	plugins: [
		// Javascript
		resolve({
			browser: true
		})
	]
}

Terminal output:

> npm run dev

> test-nollup@1.0.0 dev /Users/user/Desktop/Rollup
> cross-env NODE_ENV=development nollup -c nollup.config.js --content-base public --port 3000 --hot

Listening on http://localhost:3000
Compiled in 2ms.
Compiled in 1ms.
Compiled in 0ms.
Compiled in 1ms.
Compiled in 0ms.
Compiled in 0ms.
^C%

Screen Shot 2020-01-22 at 11 25 52

@PepsRyuu
Copy link
Owner

Do the examples also cause the CPU to spike to 440% or just the project you're trying to use Nollup in?

Would it be possible to send a minimal reproducible example that triggers the high CPU usage?

@flayks
Copy link
Author

flayks commented Jan 22, 2020

Do the examples also cause the CPU to spike to 440% or just the project you're trying to use Nollup in?

Would it be possible to send a minimal reproducible example that triggers the high CPU usage?

It seems that, at least the nollup/examples/example-react-hot-loader example works without CPU usage which means that it might come from my setup, but I hardly see why it could be that way considering how minimal my setup is :/ Is it about package versions or something?

@PepsRyuu
Copy link
Owner

I'm not seeing anything obvious that would be the culprit. As for package versions, it seems unlikely. Are there directories (excluding node_modules) that contain a huge number of files? If you replace the plugins with the ones that the example uses, does that solve the problem?

@flayks
Copy link
Author

flayks commented Jan 22, 2020

I'm not seeing anything obvious that would be the culprit. As for package versions, it seems unlikely. Are there directories (excluding node_modules) that contain a huge number of files? If you replace the plugins with the ones that the example uses, does that solve the problem?

Alright, so I did some other tests.

  1. Copy an example
    Apart from copying the example-dynamic-import and using nollup from the npm package instead of the cli file, I still have some serious CPU issues. That's all I changed in the package.json script.
  2. Run the example from the repo
    It all runs pretty smoothly, almost no CPU usage, just works. I just had to install some express/chokidar dependencies in order to make it work but that's pretty much it

I don't really know what could be the issue here but there is apparently one. Maybe my node environment? I use node v13.7.0 via n (homebrew - macOS 10.15.2) 🤷

@PepsRyuu
Copy link
Owner

Thanks for the update!

I tried to replicate by copying the example and installing Nollup from the package using Node 13.7.0, but still not able to reproduce. Dependencies should be all of their latest as well. I'm using Windows so I can't confirm if it's a Mac specific thing.

I'm not sure what else it could be. Are they running in the same directory on your system both the copy and the repo?

@flayks
Copy link
Author

flayks commented Jan 22, 2020

Hm that is strange! I do, they are both in my ~/Desktop folder. Would it affect the performance and usage if it's anywhere else? I just feel running the nollup command as an npm package is causing the trouble here

@PepsRyuu
Copy link
Owner

There shouldn't be any performance drop based on where it is, but it could affect chokidar potentially if there's a lot of files being watched, but it doesn't sound like that is the case if they're both in the same location. The npm package doesn't go through any compilation, and would be the same as running the code directly from the repo which makes the whole thing even weirder.

Can you try comment out lines 117 to 143 in nollup/dev-middleware.js? https://github.com/PepsRyuu/nollup/blob/master/lib/dev-middleware.js#L117

@flayks
Copy link
Author

flayks commented Jan 22, 2020

I think I found the bad guy, it's pnpm. I use it over npm or yarn because it allows you to symlink already downloaded node modules to your project and then work offline or setup your modules faster on top of saving lots of disk space.

I think Chokidar/some library doesn't really like that boy, it worked smoothly without CPU usage with npm and yarn. So I suppose it's not really a nollup concern, more of a third party module used by nollup? What do you think?

@flayks
Copy link
Author

flayks commented Jan 22, 2020

That said I haven't found any issue mentioning pnpm on the Chokidar github project, so it might be something else?

@PepsRyuu
Copy link
Owner

There's definitely something wrong with pnpm and chokidar. While I can't fully replicate the same issue, when I use pnpm I get extremely long build times and high CPU usage. Commenting out chokidar solves the problem. I found a couple of issues that probably hint at what's going on:

paulmillr/chokidar#773
pnpm/pnpm#119

Can you try this change directly in your node_modules in the dev middleware:

let watcher = chokidar.watch(options.watch || process.cwd(), {
    // ignored:  ['**/node_modules/**/*', '**/.git/**/*'],
    ignored: (path => path.includes('node_modules') || path.includes('.git'))
});

@flayks
Copy link
Author

flayks commented Jan 23, 2020

Yoohoo! I think we have a winner here 🎉
That totally fixes the problem. I guess they changed their ignored file checking in the meantime?


I still have some issues with BrowserSync but this is something else 🙈

WebSocket connection to 'ws://localhost:3000/__hmr' failed: Connection closed before receiving a handshake response
> (anonymous) | @ | main.[hash].js:174
> (anonymous) | @ | main.[hash].js:316
> (anonymous) | @ | main.[hash].js:322
const nollup = process.env.NOLLUP
const port = (process.argv[process.argv.indexOf('--port') + 1]) || 3000
...
// BrowerSync
nollup && browsersync({
    port: 3000,
    proxy: 'http://localhost:' + port,
    open: false,
    notify: false
}),

@flayks flayks changed the title Impossible to run nollup Very high CPU usage using pnpm Jan 23, 2020
@PepsRyuu
Copy link
Owner

Thanks for testing! I'll have a look into this in more detail later this evening, just to make sure there's no consequences in terms of general performance and no oversights that might break compatibility with existing projects.

Not sure I understand why browsersync is being used. That could cause a conflict because Nollup is already running a web server. Is there a use case I'm missing?

@flayks
Copy link
Author

flayks commented Jan 23, 2020

You're welcome, thanks for your ideas!

It's purely to get some sync of style, navigation and scroll on all my devices (mobile, tablet, desktop) when developing for responsive and stuff, it's very handy. I used to have it along the webpack-dev-server and worked like a charm.

@PepsRyuu
Copy link
Owner

Ah I see, first I'm hearing about it. 😅 Sounds interesting!

From your config, it looks like they're running on the same port?

@flayks
Copy link
Author

flayks commented Jan 23, 2020

It is very cool yea.

No actually, I run nollup on port 3100 (3000 by default), and then proxy that server on the BrowerSync one. I'd say it's more of a proxy issue maybe? But could be related to nollup, no idea.

@flayks
Copy link
Author

flayks commented Jan 23, 2020

Okay, this sounds like fixing the issue with BrowserSync (so def not nollup related):

// BrowserSync
nollup && browsersync({
    port: bsPort,
    proxy: {
        target: 'http://localhost:' + port,
        ws: true
    },
    open: false,
    notify: false
}),

@PepsRyuu
Copy link
Owner

Great! I should hopefully have a fix for the first issue by tomorrow. :)

@PepsRyuu
Copy link
Owner

Released 0.10.3. Let me know if it works for you!

@flayks
Copy link
Author

flayks commented Jan 24, 2020

Looks good to me! Thanks for the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants