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

Do not rely on /usr/bin/env in critical paths #1483

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mame
Copy link

@mame mame commented Feb 20, 2023

rbenv uses a lot of sub shell script calls, and #!/usr/bin/env bash is executed each time. This is not very efficient depending on the PATH settings.

This changeset is to use $BASH rbenv-* when calling rbenv-* in critical paths to invoke ruby. This eliminates the overhead of calling /usr/bin/env.

Before:

$ time ruby -v
ruby 3.3.0dev (2023-02-20T01:33:06Z master 7d5794bad5) [x86_64-linux]

real    0m0.532s
user    0m0.022s
sys     0m0.087s

After:

$ time ruby -v
ruby 3.3.0dev (2023-02-20T01:33:06Z master 7d5794bad5) [x86_64-linux]

real    0m0.204s
user    0m0.018s
sys     0m0.028s

rbenv uses a lot of sub shell script calls, and `#!/usr/bin/env bash` is
executed each time. This is not very efficient depending on the PATH
settings.

This changeset is to use `$BASH rbenv-*` when calling `rbenv-*` in
critical paths to invoke ruby. This eliminates the overhead of calling
`/usr/bin/env`.

Before:
```
$ time ruby -v
ruby 3.3.0dev (2023-02-20T01:33:06Z master 7d5794bad5) [x86_64-linux]

real    0m0.532s
user    0m0.022s
sys     0m0.087s
```

After:
```
$ time ruby -v
ruby 3.3.0dev (2023-02-20T01:33:06Z master 7d5794bad5) [x86_64-linux]

real    0m0.204s
user    0m0.018s
sys     0m0.028s
```
@mame
Copy link
Author

mame commented Feb 20, 2023

Note: My environment is WSL2 on Windows and my PATH setting contains some NTFS directories; NTFS access is very slow, so this problem is very noticeable.

The idea of reducing the overhead of /usr/bin/env by using $BASH comes from @naruse.

@mislav
Copy link
Member

mislav commented Feb 20, 2023

Hi, thanks for the suggestion and for sharing the speed comparison.

In case of a slow PATH, I think you will have many more problems with your dev environment than just with rbenv. The shebang /usr/bin/env is practically standard.

However, rbenv is known to add some overhead to every Ruby invocation. The biggest contributor to that is that bash is slow. In your case, another contributor to that is that searching the PATH is slow. To avoid any overhead to executing ruby, I would suggest moving to something like chruby instead.

I do want to take a deeper look into your PR, so please give me some time to do that. I want to make the speed comparison on systems where there are no NTFS directories in path, as well as try to think about the possible downsides of the change you've proposed.

@mame
Copy link
Author

mame commented Feb 20, 2023

Thank you for your quick reply!

Here is the minimum and average seconds for 1000 invocations of ruby -v when there is no NTFS directory in path.

minimum average
Before my patch 0.0888 0.175
After my patch 0.0831 0.158

It is not so fast as the case of NTFS directory, but it seems to be faster.

However, I understand that you don't want to insert a lot of $BASH from a maintenance point of view. If you don't like it, feel free to close it. Thanks for your time!

@jasonkarns
Copy link
Member

Do we have documentation as to which versions of bash reliably set $BASH? (especially when it was introduced) Any known versions of bash that have bugs regarding that variable?

Would also want to double confirm this is fine on FreeBSD (it being the primary example for why /usr/bin/env is preferred over /bin/bash). I don't have any suspicion that it wouldn't, but would be prime suspect to confirm.

@mame
Copy link
Author

mame commented Feb 22, 2023

Do we have documentation as to which versions of bash reliably set $BASH? (especially when it was introduced)

Good question. I don't know when it was introduced, but it is already mentioned in the manpage of bash-1.14.7 (in 1996).

https://git.savannah.gnu.org/cgit/bash.git/commit/?id=726f63884db0132f01745f1fb4465e6621088ccf

Even in the case that $BASH is not defined, rbenv will work as before as long as $BASH is interpreted as empty.

Any known versions of bash that have bugs regarding that variable?

I don't know, but I hope it is stable enough.

Would also want to double confirm this is fine on FreeBSD (it being the primary example for why /usr/bin/env is preferred over /bin/bash).

I confirm that $BASH is defined in bash on my FreeBSD machine.

[mame@freebsd /usr/home/mame]$ echo $BASH
/usr/local/bin/bash

I made a quick check that my rbenv branch works great on the machine. A slight improvement was also observed on the machine.

min. ave.
Before my patch 0.0218 0.0294
After my patch 0.0195 0.0251

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

3 participants