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

Performance issue with preinstall and postinstall scripts #4551

Closed
vkrol opened this issue Sep 26, 2017 · 12 comments
Closed

Performance issue with preinstall and postinstall scripts #4551

vkrol opened this issue Sep 26, 2017 · 12 comments

Comments

@vkrol
Copy link
Contributor

vkrol commented Sep 26, 2017

Do you want to request a feature or report a bug?
Bug.

What is the current behavior?

If the current behavior is a bug, please provide the steps to reproduce.
Create the following package.json:

{
  "name": "yarn-playground",
  "private": true,
  "scripts": {
    "preinstall": "echo 1",
    "postinstall": "echo 1"
  }
}

Run Measure-Command { yarn } in PowerShell:

TotalSeconds      : 5,4693932

If the package.json does not contain preinstall OR postinstall script then the duration will be:

TotalSeconds      : 0,471668

What is the expected behavior?
I do not understand why the yarn takes so much time if both scripts are present.

Please mention your node.js, yarn and operating system version.
Node.js 8.5.0
Yarn 1.1.0
OS Windows 10

@vkrol
Copy link
Contributor Author

vkrol commented Sep 26, 2017

I think that there is the problem with this timeout

this.stuckTimer = setTimeout(this.stuckTick, 5000);

@BYK
Copy link
Member

BYK commented Sep 27, 2017

@vkrol great find! Would you like to submit a fix? I'd do the following two:

  1. Add this.stucktimer.unref() right after that line so it wouldn't block exiting.
  2. Add clearTimeout(this.stuckTimer) right after
    this.runningCount--;

What do you think? Also /cc @arcanis

@vkrol
Copy link
Contributor Author

vkrol commented Sep 27, 2017

@BYK thanks! I will create the fix. Do I need to create some test for it?

@vkrol
Copy link
Contributor Author

vkrol commented Sep 27, 2017

@BYK I found some confusing behavior in Jest. The fake Timer implementation does not have unref method in Node environment so blocking-queue.js test will fail with an error:

this.stuckTimer.unref is not a function

I asked a question about this in Discord chat.

test("fake Time implementation does not have unref method", () => {
  const realTimer = setTimeout(() => {});
  expect(typeof realTimer.unref).toEqual("function");

  jest.useFakeTimers();

  const fakeTimer = setTimeout(() => {});
  expect(typeof fakeTimer.unref).toEqual("undefined");
});

@BYK
Copy link
Member

BYK commented Sep 28, 2017

@vkrol sorry, I couldn't find your message on Discord :( Ping me directly there?

I think instead of using fake timers you can make sure the timer gets released in tests then? unref is node-specific and not really documented anywhere I guess so no surprise Jest doesn't support it. We can summon @cpojer to see if he has any idea tho?

@cpojer
Copy link
Contributor

cpojer commented Sep 28, 2017

Yeah, Jest doesn't support it at this time. You'll need to guard it for Jest, like fakeTimer.unref && fakeTimer.unref() to make it work in the test for now.

@vkrol
Copy link
Contributor Author

vkrol commented Sep 28, 2017

@BYK

sorry, I couldn't find your message on Discord :(

Sorry for the confusion: I am asked in Jest Discord chat.

unref is node-specific and not really documented anywhere I guess so no surprise Jest doesn't support it.

Unref is documented in Node.js documentation https://nodejs.org/api/timers.html#timers_timeout_unref

We can summon @cpojer to see if he has any idea tho?

I created the issue in Jest repository jestjs/jest#4559

@vkrol
Copy link
Contributor Author

vkrol commented Sep 28, 2017

@BYK

I think instead of using fake timers you can make sure the timer gets released in tests then?

Fake timers already used there

jest.useFakeTimers();

@BYK
Copy link
Member

BYK commented Sep 28, 2017

Unref is documented in Node.js documentation https://nodejs.org/api/timers.html#timers_timeout_unref

TIL. Sorry :)

Fake timers already used there

Then how about we go with @cpojer's suggestion and checking for it?

@vkrol
Copy link
Contributor Author

vkrol commented Sep 28, 2017

@BYK do you think that we need to add the following line of code to the BlockingQueue implementation?

this.stuckTimer && this.stuckTimer.unref()

I think that it is somewhat hacky, but if you approve this, then ok :)

@BYK BYK self-assigned this Sep 29, 2017
@BYK
Copy link
Member

BYK commented Sep 29, 2017

It should be this.stuckTimer.unref && this.stuckTimer.unref(). With a comment that points to the Jest issue, I think it's fine.

@vkrol
Copy link
Contributor Author

vkrol commented Sep 29, 2017

It should be this.stuckTimer.unref && this.stuckTimer.unref()

Yes, sure. Sorry.

With a comment that points to the Jest issue, I think it's fine.

Thanks. I will do it.

@BYK BYK closed this as completed in #4588 Oct 2, 2017
BYK pushed a commit that referenced this issue Oct 2, 2017
…cripts (#4588)

**Summary**

Fixes #4551.

See #4551 (comment)

**Test plan**

* Existing tests pass
* Manually tested
joaolucasl pushed a commit to joaolucasl/yarn that referenced this issue Oct 27, 2017
…cripts (yarnpkg#4588)

**Summary**

Fixes yarnpkg#4551.

See yarnpkg#4551 (comment)

**Test plan**

* Existing tests pass
* Manually tested
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants