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

Defer windowWidth() to improve perf for non-help usage #610

Merged
merged 3 commits into from Aug 29, 2016

Conversation

nolanlawson
Copy link
Contributor

Hi 👋, I'm a big fan of yargs, so after talking with @lrlna about #521, I wanted to try my hand at improving the overall runtime of require('yargs').

I started by profiling with the Chrome dev tools using node-nightly and the --inspect option, where I noticed that windowWidth() is a very expensive function:

screenshot 2016-08-29 09 12 12

Since windowWidth() only has to be calculated when we need the column width, e.g. when the user has typed --help or -h, I figured we could lazily evaluate it. That's what this PR does.

Here is a very small benchmark to demonstrate the perf improvement:

time for i in {1..500}; do node -e 'require("./index")'; done

Running in node 5.12.0 on a 2013 Macbook Air, I got the following results (real time, averaged):

  • Before: 122.14ms
  • After: 108.746ms

Since that includes the cost of the Node process itself, we can also use performance-now to measure just the runtime of require('yargs'):

for ((i=0;i<500;i++)); do node -e 'var now = require("performance-now"); var s = now(); require("./index"); var e = now() - s; console.log(e)'; done | awk '{ sum+=$1 } END { print sum/NR }'

This gives:

  • Before: 41.3002ms
  • After: 28.5307ms

So in rough terms require('yargs') should be about ~30% faster with this PR, with an average of ~12ms shaved off each invocation of require('yargs'). (Obviously it doesn't make any difference when doing -h or --help, but my hunch is that that's not the average use case.)

Please let me know if I missed something in the style/coverage/etc. or if this PR is unfeasible for some other reason I didn't notice. Hope this helps!

@maxrimue
Copy link
Member

This. is. awesome.
Thank you so much @nolanlawson 🎉

@@ -96,11 +96,23 @@ module.exports = function (yargs, y18n) {
epilog = msg
}

var wrap = windowWidth()
var wrapSet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would initialize this to false, for clarity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, good catch!

@nexdrew
Copy link
Member

nexdrew commented Aug 29, 2016

Besides my nit-picky inline comments, this LGTM! Thanks @nolanlawson!

@nexdrew
Copy link
Member

nexdrew commented Aug 29, 2016

Me likey. 😺 Thanks again, @nolanlawson, this is great!

@bcoe bcoe merged commit cbc3636 into yargs:master Aug 29, 2016
@bcoe
Copy link
Member

bcoe commented Aug 29, 2016

@nolanlawson thank you very much for digging into this.

@lrlna
Copy link
Member

lrlna commented Aug 30, 2016

woot!! Thanks so much @nolanlawson ✨ ✨

@bcoe
Copy link
Member

bcoe commented Sep 30, 2016

@nolanlawson @lrlna want to give this a spin?

npm cache clear; yargs@6.0.0-alpha.1?

These performance changes go out with the next release (would love the extra set of eyes).

@lrlna
Copy link
Member

lrlna commented Oct 2, 2016

@bcoe i am using that on a refactor of one of my projects right now; it's all good so far and I'll keep an eye :D

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

Successfully merging this pull request may close these issues.

None yet

5 participants