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

Spawning a child process on Windows is really slow, takes minutes to complete #142

Closed
AndyOGo opened this issue Jul 3, 2018 · 13 comments
Closed

Comments

@AndyOGo
Copy link

AndyOGo commented Jul 3, 2018

I experience a really weird massive delay on windows by running npm or git as a child process.
Compared to my running it on MacOS, windows takes ages to complete 🤔

These are my test scripts:

const execa = require('execa');

execa('npm', ['whoami']).then(({stdout}) => {
  console.log(stdout);
}).catch(reason => {
  console.error(reason);
})
const execa = require('execa');

execa('git', ['status']).then(({stdout}) => {
  console.log(stdout);
}).catch(reason => {
  console.error(reason);
})

Timing those calls:

The first call is significantly slower than the second call (that's maybe due to JIT).
But the difference between MacOS and Windows is tremendous:

Run MacOS Windows
1 npm whoami 1289.505351 ms = 1.2895 sec 189807.887698 ms = 189.8079 sec = 3.1635 min
2 git status 15.803947 ms (x81.59387974409178 times faster) 201.531065 ms (x941.82942812315312 times faster)

test script:

const execa = require('execa');

const precise = require('precise');
const timer = precise();

timer.start();
execa('npm', ['whoami']).then(({stdout}) => {
  timer.stop();
  console.log('Message received in', timer.diff() / 1000000, 'ms');
  console.log(stdout);
}).catch(reason => {
  timer.stop();
  console.log('Message received in', timer.diff() / 1000000, 'ms');
  console.error(reason);
}).then(() => {
  const timer2 = precise();
  timer2.start();
  execa('git', ['status']).then(({stdout}) => {
    timer2.stop();
    console.log('Message received in', timer2.diff() / 1000000, 'ms');
    console.log(stdout);
  }).catch(reason => {
    timer2.stop();
    console.log('Message received in', timer2.diff() / 1000000, 'ms');
    console.error(reason);
  })
})

Windows 10:

C:\eplatform\git-repos\patterns-library>npm run test-child-spawn

> @axa-ch/[email protected] test-child-spawn C:\eplatform\git-repos\patterns-library
> node ./stack/tasks/test-child-spawn.js

Message received in 189807.887698 ms
user-name
Message received in 201.531065 ms
On branch bugfix/windows-spawn-hangs
Your branch is up-to-date with 'origin/bugfix/windows-spawn-hangs'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   package.json

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .idea/
        patterns-library.iml

no changes added to commit (use "git add" and/or "git commit -a")

Mac OSX El Capitan Version 10.11.6:

npm run test-child-spawn

> @axa-ch/[email protected] test-child-spawn /Users/axawinterthur/dev/axa-ch_style-html-guide
> node ./stack/tasks/test-child-spawn.js

Message received in 1289.505351 ms
andyogo
Message received in 15.803947 ms
On branch bugfix/windows-spawn-hangs
Your branch is up-to-date with 'github/bugfix/windows-spawn-hangs'.
nothing to commit, working tree clean
@SamVerschueren
Copy link
Contributor

Can your try running it with Node.js child_process instead of execa? It might have nothing to do with execa itself.

@AndyOGo
Copy link
Author

AndyOGo commented Jul 3, 2018

@SamVerschueren
Thanks for your quick answer.
Sure, IMHO I think it will be a bug in node, though we just started to setup basic tests and run them on windows and Mac, to see the measured difference. Will post the results asap.

@AndyOGo
Copy link
Author

AndyOGo commented Jul 3, 2018

@SamVerschueren
I shared our test results with using execa.
Next we will write a plain child_process test, will keep you updated.

@AndyOGo
Copy link
Author

AndyOGo commented Jul 3, 2018

Test run with native child_process.execFile

Run MacOS Windows
1 npm whoami 1256.060359 ms = 1.256 sec 189733.792206 ms = 189.7338 sec = 3.162 min
2 git status 16.693848 ms (x75.24091264039304 times faster) 161.197277 ms (x1177.02851894948573 times faster)

test script:

const { execFile } = require('child_process');
const precise = require('precise');
const timer = precise();

// Node does not support PATHEXT on Windows
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';

timer.start();

execFile(npmCmd, ['whoami'], (error, stdout, stderr) => {
  timer.stop();
  console.log('Message received in', timer.diff() / 1000000, 'ms');
  if (error) {
    console.error(error);
  } else {
    console.log(stdout);
  }

  const timer2 = precise();
  timer2.start();

  execFile('git', ['status'], (error, stdout, stderr) => {
    timer2.stop();
    console.log('Message received in', timer2.diff() / 1000000, 'ms');
    if (error) {
      console.error(error);
    } else {
      console.log(stdout);
    }
  });
});

Windows 10:

C:\eplatform\git-repos\patterns-library>npm run test-child-spawn-nodejs

> @axa-ch/[email protected] test-child-spawn-nodejs C:\eplatform\git-repos\patterns-library
> node ./stack/tasks/test-child-spawn-nodejs.js

Message received in 189733.792206 ms
user-name

Message received in 161.197277 ms
On branch bugfix/windows-spawn-hangs
Your branch is up-to-date with 'origin/bugfix/windows-spawn-hangs'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .idea/
        patterns-library.iml

nothing added to commit but untracked files present (use "git add" to track)

Mac OSX El Capitan Version 10.11.6:

npm run test-child-spawn-nodejs

> @axa-ch/[email protected] test-child-spawn-nodejs /Users/axawinterthur/dev/axa-ch_style-html-guide
> node ./stack/tasks/test-child-spawn-nodejs.js

Message received in 1256.060359 ms
andyogo

Message received in 16.693848 ms
On branch bugfix/windows-spawn-hangs
Your branch is up-to-date with 'github/bugfix/windows-spawn-hangs'.
nothing to commit, working tree clean

@AndyOGo
Copy link
Author

AndyOGo commented Jul 3, 2018

@SamVerschueren
Okay, this is a critical bug in node on Windows

@AndyOGo
Copy link
Author

AndyOGo commented Jul 3, 2018

I just created an issue at node's repo:
nodejs/node#21632

@AndyOGo
Copy link
Author

AndyOGo commented Jul 4, 2018

Issue at npm:
npm/npm#21148

@AndyOGo
Copy link
Author

AndyOGo commented Aug 27, 2018

@SamVerschueren
Alright, luckily we finally found the culprit.
It's update-notifier being part of [email protected] which can't handle enterprise proxies and timeouts after 3 minutes 😱

Using NO_UPDATE_NOTIFIER: true did work for me 😄

Original workaround found in:
npm/npm#20979

New issue at NPM's new issue tracker:
https://npm.community/t/npm-version-takes-3-minutes-to-complete-when-run-in-child-process-and-behind-corporate-proxy/1658

@AndyOGo
Copy link
Author

AndyOGo commented Aug 27, 2018

@sindresorhus This issues of not handling proxy environments dates back to got if I understand it correctly 🤔

@sindresorhus
Copy link
Owner

Got docs on proxy here: https://github.com/sindresorhus/got#proxies

npm should probably use https://github.com/np-maintain/global-tunnel so all the tools they depend on also use the set proxy info.

@AndyOGo
Copy link
Author

AndyOGo commented Aug 27, 2018

@sindresorhus
Thanks for your quick response.

Unfortunately those links do not provide reasonable solutions if a user just wants to use npm commands from his CLI or have a script which runs several in order...

Maybe node should have proxy support by environment variables backed in, though current status is definitly not ideal...

Actually I'm also convinced that's a bug in npm to use a package like update-notifier, which is out of it's control...

@sindresorhus
Copy link
Owner

sindresorhus commented Aug 27, 2018

Unfortunately those links do not provide reasonable solutions if a user just wants to use npm commands from his CLI or have a script which runs several in order...

Yes, it does, global-tunnel fixes proxy for all request libs used in the dependency tree. Please take a closer look at it. If npm used that, it would be fixed.

Maybe node should have proxy support by environment variables backed in, though current status is definitly not ideal...

It should, but the core team doesn't seem interested in solving the problem: nodejs/node#8381

@AndyOGo
Copy link
Author

AndyOGo commented Aug 27, 2018

Thanks a lot, seems you faced this issue several times already...
I will look into it.

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

3 participants