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

Only install hooks that are hooked #648

Closed
arcanis opened this issue Jan 15, 2020 · 12 comments
Closed

Only install hooks that are hooked #648

arcanis opened this issue Jan 15, 2020 · 12 comments

Comments

@arcanis
Copy link
Contributor

arcanis commented Jan 15, 2020

We've noticed Husky can add a significant overhead to git commands when used together with Yarn 2 due to the fact that it needs to spawn at least one Node process for each hook called - and multiple hooks are called when doing a commit, and Node processes aren't exactly cheap 😢

What would you think of adding a "pay only for what you use" mode where Husky would only add hooks that are actually used by the project? In most cases, that would limit them to precommit, and if you want to add/remove a hook you'd just have to run yarn husky to regenerate them.

I could open a PR if you think that would be useful.

@typicode
Copy link
Owner

Currently, you can add hooks to .huskyrc and it just works.

The downside of the other approach is that, for example in a team, people would need to manually think about running yarn husky when a new hook is added. That would be a breaking change also.

But I agree, it's not ideal the way it is now and it's an area of improvement. I'm exploring some ideas.

@typicode
Copy link
Owner

Just published husky 4.1.0, it should be significantly faster.

@Yegorich555
Copy link

Could you help me to understand? Right now I have just only pre-commit hook pointed in my package.json. When I'm starting git push the other hooks are fired also and it takes time for firing empty hooks and ending but it shouldn't. Is it related to this opened issue (mentioned upper)? How it can be fixed via .huskyrc right now?

@typicode
Copy link
Owner

@Yegorich555 empty hooks should be skipped very fast. Below you'll find a quick benchmark on a budget laptop.

Having pre-commit hook run and prepare-commit-msg, commit-msg, post-commit skipped takes
HUSKY_DEBUG=1 git ci -m foo 0.29s user 0.07s system 107% cpu 0.335 total

Having pre-commit hook only installed takes
HUSKY_DEBUG=1 git ci -m foo 0.23s user 0.07s system 108% cpu 0.280 total

Skipping 3 hooks takes ~0.05s.

Does it take a lot longer than that?

$ cat .huskyrc
{ "hooks": { "pre-commit": "echo hello" } }

$ date > foo && git add foo && time HUSKY_DEBUG=1 git commit -m foo
husky:debug husky v4.2.1 - pre-commit
husky:debug Current working directory is /tmp/foo
husky > pre-commit (node v13.6.0)
hello
husky:debug npx --no-install husky-run exited with 0 exit code
husky:debug husky v4.2.1 - prepare-commit-msg
husky:debug Current working directory is /tmp/foo
husky:debug prepare-commit-msg config not found, skipping hook
husky:debug husky v4.2.1 - commit-msg
husky:debug Current working directory is /tmp/foo
husky:debug commit-msg config not found, skipping hook
husky:debug husky v4.2.1 - post-commit
husky:debug Current working directory is /tmp/foo
husky:debug post-commit config not found, skipping hook
[master 0ba85e5] foo
 1 file changed, 1 insertion(+), 1 deletion(-)
HUSKY_DEBUG=1 git ci -m foo  0.29s user 0.07s system 107% cpu 0.335 total

$ rm .git/hooks/{prepare-commit-msg,commit-msg,post-commit}
$ date > foo && git add foo && time HUSKY_DEBUG=1 git ci -m foo
husky:debug husky v4.2.1 - pre-commit
husky:debug Current working directory is /tmp/foo
husky > pre-commit (node v13.6.0)
hello
husky:debug npx --no-install husky-run exited with 0 exit code
[master 0c93634] foo
 1 file changed, 1 insertion(+), 1 deletion(-)
HUSKY_DEBUG=1 git ci -m foo  0.23s user 0.07s system 108% cpu 0.280 total

@typicode
Copy link
Owner

That said in future versions of Husky, a different approach than skipping hooks may be used.

@arcanis
Copy link
Contributor Author

arcanis commented Jan 24, 2020

I have a crazy but funny idea: what if Husky was greping for the hook name in the manifest?

I know, it sounds stupid - maybe the hook name is found in the manifest without being a Husky key -, but after all we don't need perfect detection. In the vast majority of cases (for example post-commit, commit-msg, ...) a very basic grep-based heuristic will be able to skip missing hooks, and in the few cases where the heuristic will be wrong (update?) it will just cause Husky to be slightly slower, much like right now.

Basically, instead of proving that a hook exist, we maybe can prove that it doesn't exist and use that to skip it?

@typicode
Copy link
Owner

Crazy ideas are always interesting :)

Maybe I'm missing something, but isn't it similar to this:
https://github.com/typicode/husky/blob/master/sh/husky.sh#L60

Or you mean something else?

@arcanis
Copy link
Contributor Author

arcanis commented Jan 24, 2020

Oh amazing, I didn't see the change! Yep, that's exactly what I had in mind 😃

@Yegorich555
Copy link

Yegorich555 commented Jan 26, 2020

@Yegorich555 empty hooks should be skipped very fast. Below you'll find a quick benchmark on a budget laptop.

Having pre-commit hook run and prepare-commit-msg, commit-msg, post-commit skipped takes
HUSKY_DEBUG=1 git ci -m foo 0.29s user 0.07s system 107% cpu 0.335 total

Having pre-commit hook only installed takes
HUSKY_DEBUG=1 git ci -m foo 0.23s user 0.07s system 108% cpu 0.280 total

Skipping 3 hooks takes ~0.05s.

Does it take a lot longer than that?

It's very interesting. I noticed, that previous git-pushes took < 1sec, but after installing husky it takes about 5-10sec. I would like to notice I have only pre-commit hook. Maybe hooks-firing works fast but the whole push-process is incredible long now...

@typicode
Copy link
Owner

@Yegorich555 What's your OS/GUI tool? If you rm hooks that are run during push, is it faster?

@Yegorich555
Copy link

Yegorich555 commented Jan 29, 2020

I use GitKraken... Note: the issue exists when push happens via VPN to customerGitlab (not to github.com) which actually means the push process takes about 5 seconds itself and in this case, the firing of every empty hook is distinguishable and takes at least 5 seconds in addition... Of course, it's not clear enough for me and you... I'll retest this case with other repositories and maybe will provide detailed info...

I've got push-info from GitKraken:
image
And you can notice that right now we have 675ms for an empty pre-push hook. This is not as much as I mentioned earlier but it takes time...

@typicode
Copy link
Owner

typicode commented Jan 7, 2021

Closing as there's no more overhead or unused hooks with v5

@typicode typicode closed this as completed Jan 7, 2021
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