Pourquoi l'achèvement de bash est-il si lent sur OS X?

16

Je ne comprends pas pourquoi l'achèvement de bash est chargé si lentement sur mon MacBook Pro.

J'ai fait ce qui suit dans mon ~/.bash_profile:

echo "Loading BashCompletion..."
if [ -f /opt/local/etc/bash_completion ]; then
    . /opt/local/etc/bash_completion
fi
echo "BashCompletion loaded."

le temps d'exécution pour bash_completion est généralement> 2 secondes.

Je trouve cela vraiment ennuyeux lorsque je travaille sur le terminal, ce qui m'oblige à ouvrir constamment de nouveaux onglets.

Existe-t-il un moyen de mettre en cache ceci ou quelque chose?

(Notez que j'utilise iTerm2 et que c'est également lent sur le terminal d'origine sur Mac).

disparu
la source
Cela ne devrait pas se produire. Ai-je raison d'utiliser la complétion bash de MacPort?
slhck
À quoi ressemble le fichier que vous chargez?
Daniel Beck
@slhck: Oui, j'utilise effectivement la complétion bash de macport
disparu le
@Daniel: Tout va bien sauf cela. J'ai profilé presque chaque ligne.
disparu le
5
Je ressens la même lenteur et j'utilise Homebrew.
Brice

Réponses:

10

Version courte: la suppression d'une seule ligne du temps /usr/local/etc/bash_completionréduit pour ouvrir un nouvel onglet de dix secondes à un quart de seconde. Lisez la suite pour plus de détails.

J'utilise bash-complètement de homebrew et j'ai rencontré le même problème. Il fallait plus de dix secondes pour charger les scripts d'achèvement de bash chaque fois que j'ouvrais un terminal.

La plupart du temps, il semble être occupé par une seule ligne dans la have()fonction: un appel à typepour déterminer si un programme en ligne de commande est installé.

Avec la have()fonction par défaut et tous les scripts d'achèvement de bash fournis en place, il faudrait 10,561 secondes pour charger les scripts (signalés en préfixant timela . /opt/local/etc/bash_completionligne de mon .bash_profilefichier.

Après avoir commenté la PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&ligne de mon /usr/local/etc/bash_completionscript (quitter la have=yesligne, ouvrir un nouveau terminal ne prend que 0,258 s. Ce temps pourrait être encore réduit en supprimant les scripts de fin inutiles (liens symboliques) du /usr/local/etc/bash_completion.drépertoire.

Je ne sais pas pourquoi l'appel typeprend si longtemps. J'enquête ensuite.

Un inconvénient potentiel de cette approche est qu'elle entraînera le chargement en mémoire des fonctions d'achèvement de bash même si vous ne les utilisez pas. La have()fonction vérifie si une commande ou une application est installée. Si ce n'est pas le cas, le script d'achèvement décide généralement de ne pas s'embêter à se charger car il ne sera d'aucune utilité.

Pour le moment, je suis satisfait du compromis, mais je continuerai d'explorer le typeproblème au fur et à mesure que j'aurai le temps. Je mettrai à jour ma réponse si je trouve une meilleure solution.

godbyk
la source
Pour moi, commenter cette ligne réduit le temps de 50 ms, de 230 ms à 180 ms. Bien sûr, je ne l'ai jamais eu si mal en premier lieu. 👍
Edward Anderson
Cela n'a réduit que d'environ 60 ms, donc je n'ai pas conservé la solution de contournement. Je n'ai pas dix secondes d'attente, mais environ 2 secondes, ce qui est légèrement gênant.
danemacmillan
7

Pour ceux qui arrivent à la conclusion que les temps de démarrage pour les nouveaux shells sur MacOS sont trop lents pour eux, c'est la solution .

Je viens de découvrir qu'il existe en fait deux packages qui peuvent être installés via brew. J'installe le bash-completionpackage depuis des années, et je n'ai jamais pris la peine de le remettre en question, même si, à cette époque, je suis passé de Bash 3, à 4, jusqu'à maintenant 5. De temps en temps, cependant, je revisiterais le problème , tombant souvent sur cette discussion très StackOverflow.

Il y a un autre package bash-completion@2,!

Quelle est la différence? bash-completionest pour Bash version 3.2. bash-completion@2est pour Bash version 4.1+ et 5.

En supprimant l'ancien bash-completionpackage et en installant bash-completion@2, mes temps de démarrage du shell sont passés de 605 ms à 244 ms. C'est une énorme amélioration de la vitesse.

Je soupçonne que beaucoup d'entre nous font la même erreur, car les brew infostatistiques montrent que le premier a des tonnes d'installations, tandis que le second en a si peu:

entrez la description de l'image ici

Il convient de noter que la réponse actuellement choisie mentionne commenter certaines lignes, ce qui n'améliore que légèrement les temps de démarrage (si vous utilisez l'ancien bash-completionpackage, ce que beaucoup sont probablement), mais n'a aucun impact sur le nouveau bash-completion@2package: ce nouveau package est rapide quoi qu'il arrive. Cela signifie qu'aucun piratage n'est requis.

TL; DR:

brew uninstall bash-completion && brew install bash-completion@2

N'oubliez pas de mettre à jour le chemin source vers le fichier d'achèvement dans votre fichier .bashrcou .bash_profile.

Sources:


En tant que sujet quelque peu lié, j'utilise rclonebeaucoup l' utilitaire, il est donc installé. Il se trouve également que le fichier d'achèvement le plus volumineux que j'ai jamais vu . Le supprimer réduit le temps de démarrage de mon shell à ~ 120 ms, ce qui est très rapide.


Éditer:

Pour tous ceux qui veulent les détails techniques qui expliquent ce problème, j'ai longuement écrit à ce sujet sur les forums Homebrew . Pour résumer, la raison pour laquelle cela bash-completion@2est beaucoup plus rapide est qu'il a été écrit de manière à ne plus charger tous les fichiers d'achèvement avec impatience ; au lieu de cela, il charge un fichier d'achèvement à la demande, ou comme l'auteur le décrit, il les charge de manière non désireuse .

danemacmillan
la source
Je pense que la version Bash par défaut sur macOS est toujours la v3.2 - Je ne pense pas qu'elle soit livrée avec Bash v4.2. Avez-vous une référence où il est dit que macOS est livré avec Bash v4.2 +?
nwinkler
1
@nwinkler Vous auriez raison. Je suis perplexe de savoir pourquoi je l'ai mentionné, car MacOS est toujours livré avec version 3.2.57(1)-release (x86_64-apple-darwin18). Merci d'avoir fait remarquer cela; J'ai supprimé la ligne de mon message.
danemacmillan
1
Déconcertant, je sais ... Merci d'avoir mis à jour votre réponse!
nwinkler
3

Avec l'idée que godbyk m'a donnée, j'ai trouvé que ma variable PATH avait quelques répertoires qui n'avaient pas de binaires ou qui n'existaient pas, les supprimer les a accélérés de manière significative. En d'autres termes, voici le CHEMIN que j'avais dans mon bashrc:

PATH="$GOPATH/bin:/some/directory/not/existing:/some/empty/directory:/some/directory/without/binaries:$PATH"

Et puis je l'ai changé en:

PATH="$GOPATH/bin:$PATH"

C'était parce que la havefonction dans cet achèvement bash, cherchait chaque commande, et j'avais trop de répertoires inutiles qui allaient être visités pour chacun de ces binaires, les supprimant les accéléra.

Farid Nouri Neshat
la source
J'ai également réussi à changer le temps de chargement d'environ 5 secondes à moins de 1 seconde en supprimant les chemins qui n'existent pas dans ma variable d'environnement PATH.
juriejan
0

J'ai eu le même problème. Quelques astuces de débogage simples m'ont amené à la cause première.

Tout d'abord, activez DEBUG modepour voir ce qui se passe:

export BASH_COMPLETION_DEBUG=true

Cela permet une impression détaillée sur la console, vous pouvez donc voir la dernière commande. Vous pouvez maintenant exécuter le script en arrière-plan et vous verrez ce qui se passe

. /opt/local/etc/bash_completion &

Ne prenez pas le PID, que vous pouvez ensuite tracer avec psou pstree:

pstree -p <the PID>:

| |     \-+= 82095 mfellows -bash
| |       \-+- 82103 mfellows -bash
| |         |-+- 82104 mfellows cargo --list
| |         | \--- 82106 mfellows rustc -vV --cap-lints allow

Comme vous pouvez le voir, il a démarré certaines commandes liées à la rouille, qui prenaient des âges.

La suppression temporaire a /opt/boxen/homebrew/etc/bash_completion.d/cargorésolu mes symptômes.

Matthew Fellows
la source
-1

Si vous utilisez MacPorts> = 2.1.2 et Mountain Lion, il semble que vous ayez bash_profiletort. Suivez les instructions sur Comment faire fonctionner git-complétement.bash sur Mac OS X? . Je suppose que cela pourrait accélérer l'auto-complétion.

Une autre solution serait d'essayer d'installer l'auto-complétion via Fink ou Homebrew. Si cela ne fonctionne pas, vous pouvez essayer un autre shell. J'ai trouvé que la coque Fish est exceptionnelle en ce qui concerne l'auto-complétion (prête à l'emploi). Bien que la version 2 soit encore en version bêta, je la recommande vivement.

génial
la source
-1

Je vais deviner que votre bash est trop vieux. J'utilise stock bash fourni avec Mountain Lion et voici ce que je vois:

$ port info bash-completion
bash-completion @2.0, Revision 1 (sysutils)

Description:          Programmable completion library for bash. This port
                      **requires bash >=4.1** and is meant to be used together with
                      the bash port.
Homepage:             http://bash-completion.alioth.debian.org/

Runtime Dependencies: bash
Conflicts with:       bash-completion-devel
Platforms:            darwin
License:              GPL-2+
Maintainers:          raimue@macports.org

$ bash --version
GNU bash, version **3.2.48(1)-release (x86_64-apple-darwin12)**
Copyright (C) 2007 Free Software Foundation, Inc.
illustration numérique
la source
Je ne vois pas d'avoir cette commande de port. :( Comment puis-je savoir quel logiciel de complétion d'onglet git est en cours d'exécution sur mon mac.
Dean Hiller
@DeanHiller Cette réponse fait référence au gestionnaire de packages Macports, qui fournit la commande port. L'application de complétion bash de Macports sera plus récente que celle fournie avec OS X.
Matt S