Bash-completion slows up the start of bash

Bug #790043 reported by Atanas Atanasov on 2011-05-30
This bug affects 20 people
Affects Status Importance Assigned to Milestone
bash-completion (Ubuntu)

Bug Description

Binary package hint: bash-completion

I have been noticing that bash has unusually slow start-up times. After looking into the problem, I found out this is mostly caused by the execution of /etc/bash_completion (calls to this exist in several places). Of course, removing them speeds up the start but leaves a less functional shell. As a work-around I would like to suggest starting up /etc/bash_completion in the background. In this way, bash will start quickly, have access only to basic built-in completions for the first 2 seconds until /etc/bash_completion finishes executing.

ProblemType: Bug
DistroRelease: Ubuntu 11.04
Package: bash-completion 1:1.3-1ubuntu3
ProcVersionSignature: Ubuntu 2.6.38-8.42-generic
Uname: Linux 2.6.38-8-generic x86_64
Architecture: amd64
Date: Sun May 29 22:43:51 2011
EcryptfsInUse: Yes
PackageArchitecture: all
 PATH=(custom, no user)
SourcePackage: bash-completion
UpgradeStatus: Upgraded to natty on 2011-04-24 (35 days ago)

Atanas Atanasov (thenasko) wrote :
Bryce Harrington (bryce) wrote :

Hi Atanas, thanks this is a good suggestion. Do you have a test case handy for measuring the startup time?

Changed in bash-completion (Ubuntu):
importance: Undecided → High
status: New → Triaged
Atanas Atanasov (thenasko) wrote :

Hi Bryce,

I should start by saying the execution time of bash-completion depends a lot of the amount of software installed in any particular computer. I posted the this bug based on my experience with a laptop which I no longer have. While the machine was older its specs weren't very bad -- AMD Turion X2 1.8GHz dual core, 2 GB RAM. I just tested bash-completion on a small server with similar specifications but far less software installed. Here are the stats.

nasko@chow:~$ time bash /etc/bash_completion

real 0m0.787s
user 0m0.632s
sys 0m0.148s

nasko@chow:~$ time bash empty_script
bash: exit: No such file or directory

real 0m0.007s
user 0m0.008s
sys 0m0.000s

The difference in real execution time is almost 0.8s.

osirisgothra (osirisgothra) wrote :

It's worth noting that the bash completion scripts are being started twice when logging in either via a tty or bash's (-l) option. The fault with that is that most systems are checking the shell in /etc/profile.d/ to see if its bash and then proceeding to call the bash_completion itself, neglecting the fact that bash calls /etc/bash.bashrc anyway which will do the same thing. Lucky for me i rarely log in via tty, im usually in xterm and dont use the (-l) option, but even with one go, those scripts that are being executed are installed into /etc/bash_completion.d/ by the various packages that feature specialized completion. Though we can't blame them because this is exactly what was intended in the first place. The tag is passed back to bash to address startup script execution times in order to speed up this it is going to have to consider the existing scripts out there already. For now maybe there is some way to cache this in a way that would be efficient for both resources and users?

Peter Cordes (peter-cordes) wrote :

/etc/profile.d/ only sources /usr/share/bash-completion/bash_completion if it hasn't been already. note the check on -z "$BASH_COMPLETION_COMPAT_DIR", which the giant bash_completion script defines with

: ${BASH_COMPLETION_COMPAT_DIR:=/etc/bash_completion.d}

 So I guess BASH_COMPLETION_COMPAT_DIR is the canonical way to check if it's already loaded, since the variable gets marked readonly. (That prevents even unset from working on it.)

 This doesn't help if profile.d goes first, and then bash.bashrc or the user's ~/.bashrc sources completions without checking, though.

 The commented-out lines in the default /etc/bash.bashrc should have the same check added, if they haven't. My /etc/bash.bashrc.dpkg-old from 2013 still shows it with the crusty old:
# enable bash completion in interactive shells
#if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
# . /etc/bash_completion

/etc/profile.d is a silly place to have this, though. How and whether programmable completion is enabled by default is a topic for another bug, but I don't think there's any way to justify having it for login shells but not for non-login shells. xterm, gnome-terminal, etc. all normally start non-login shells.

Peter Cordes (peter-cordes) wrote :

@Atanas: interesting idea to have bash load completions in the background, but shell scripting as a language has NO support for doing anything like this. You can't just have it happen in another thread, because you need it to modify the context of the CURRENT shell.

  You'd need a new major feature to read a stream of commands from a file in the background and have it modify the current shell environment. It would either have to have a whole bunch of arbitrary rules, like you aren't allowed to cd / pushd / popd, or you'd introduce a lot of potential weirdness, and huge amounts of corner cases to figure out what should happen if the background command stream did something at the same time as the normal command stream.

 maybe if you restricted the commands allowed to just function definitions, and use of the complete shell builtin, that would make it viable. But the current bash_completion goes and sources everything in /etc/bash_completion.d, which means it had to have some commands run (e.g. the source builtin, and some logic to blacklist

 So it's theoretically doable, but it would be a lot of work for something that is finally not really an issue, even on hardware that's a bit old by today's standards. Basically, it's not pretty, but luckily most people have fast CPUs. And hopefully not too many separate files to generate hard drive bottlenecks with magnetic drives that seek slowly...

Peter Cordes (peter-cordes) wrote :

bug 1173728 is about programmable completion being loaded by default, or not. Further discussion about how and whether it is should go there. Sorry for the tangent about it in this bug.

Peter Cordes (peter-cordes) wrote :

The shell builtin command return can be used to exit early from a file sourced with . or source.

bash_completion could protect itself from being re-sourced by doing
type __reassemble_comp_words_by_ref 2>/dev/null && return
Or maybe
complete -p paste 2>/dev/null && return
So complete -r; source /usr/share/bash-completion/bash_completion would re-load.

 This still violates the expectation that users might have that if they changed stuff in /etc/bash_completion.d, they could just re-source the system bash_completion script.

complete -p paste 2>/dev/null &&
  echo "completions already loaded, complete -r before sourcing if you want them re-loaded" >&2 &&

Peter Cordes (peter-cordes) wrote :

So to be clear, the changes I'm suggesting are:

* /etc/skel/.bashrc (pkg=base-files) change the progcomp check to an un-commented
# enable programmable completion
[[ -e /etc/profile.d/ ]] && . /etc/profile.d/

* /etc/bash.bashrc (pkg=bash): remove the progcomp commented-out section, maybe replace with a comment like:
# enable programmable completion with this line, here or (default) in ~/.bashrc
# [[ -e /etc/profile.d/ ]] && . /etc/profile.d/

Root's /root/.bashrc doesn't come into play on an ubuntu system, normally. Even if you use sudo -s, HOME doesn't change, so you still get your own ~/.bashrc

If you're mucking around with testing corner cases, put
echo "bash_completion callstack: ${BASH_SOURCE[*]}"
 in /usr/share/bash-completion/bash_completion to get output like
bash_completion callstack: /usr/share/bash-completion/bash_completion /etc/profile.d/ /home/peter/.bashrc

 Or drop that line into /etc/bash_completion.d/trace, if you don't want to modify a non-conffile.

Peter Cordes (peter-cordes) wrote :

crap, wrong bug, meant to post that last on bug 1173728

Atanas Atanasov (thenasko) wrote :

@Peter: I am most probably misreading your comment about lack of background execution support in shell scripts. Why can't we load the completions with ". /etc/bash_completion &" instead of ". /etc/bash_completion"?

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Duplicates of this bug

Other bug subscribers