Warum wird die Bash-Vervollständigung unter OS X so langsam geladen?

16

Ich verstehe nicht, warum die Bash-Vervollständigung auf meinem MacBook Pro so langsam geladen wird.

Ich habe folgendes in meinem gemacht ~/.bash_profile:

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

Die Ausführungszeit für bash_completion beträgt in der Regel> 2 Sekunden.

Ich finde das sehr ärgerlich, wenn ich am Terminal arbeite und ständig neue Tabs öffnen muss.

Gibt es eine Möglichkeit, dies oder etwas zwischenzuspeichern?

(Beachten Sie, dass ich iTerm2 verwende und dies auf dem Original-Terminal in Mac ebenso langsam ist).

verschwunden
quelle
Das sollte nicht passieren. Stimmt es, dass Sie MacPorts Bash-Vervollständigung verwenden?
Slhck
Wie sieht die geladene Datei aus?
Daniel Beck
@slhck: Ja, ich verwende tatsächlich Macports Bash-Vervollständigung
verschwunden
@ Daniel: Alles ist in Ordnung, außer dies. Ich habe fast jede Zeile profiliert.
Verschwunden
5
Ich erlebe die gleiche Langsamkeit und verwende Homebrew.
Brice

Antworten:

9

Kurzversion: Durch das Entfernen einer einzelnen Zeile aus wurde /usr/local/etc/bash_completiondie Zeit zum Öffnen eines neuen Tabs von zehn Sekunden auf eine Viertelsekunde verkürzt. Lesen Sie weiter für Details.

Ich verwende Bash-Vervollständigung von Homebrew und habe das gleiche Problem festgestellt. Bei jedem Öffnen eines Terminals dauerte das Laden der Bash-Abschlussskripte mehr als zehn Sekunden.

Die meiste Zeit scheint es in einer einzigen Zeile in der have()Funktion zu sein: ein Aufruf, typeum festzustellen, ob ein Befehlszeilenprogramm installiert ist.

have()Wenn die Standardfunktion und alle bereitgestellten Bash-Vervollständigungsskripte vorhanden sind, würde das Laden der Skripte 10,561 Sekunden dauern (gemeldet durch das Präfix timein der . /opt/local/etc/bash_completionZeile in meiner .bash_profileDatei).

Nachdem ich die PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&Zeile meines /usr/local/etc/bash_completionSkripts have=yesauskommentiert habe (beim Verlassen der Zeile dauert das Öffnen eines neuen Terminals nur 0,258 Sekunden. Diese Zeit könnte weiter verkürzt werden, indem unnötige Abschlussskripts (Symlinks) aus dem /usr/local/etc/bash_completion.dVerzeichnis entfernt werden.

Ich weiß nicht, warum der Anruf typeso lange dauert. Ich untersuche das als nächstes.

Ein möglicher Nachteil dieses Ansatzes besteht darin, dass Bash-Completion-Funktionen in den Speicher geladen werden, obwohl Sie sie nicht verwenden können. Die have()Funktion prüft, ob ein Befehl oder eine Anwendung installiert ist. Wenn dies nicht der Fall ist, beschließt das Abschlussskript im Allgemeinen, sich nicht um das Laden zu kümmern, da es keinen Nutzen bringt.

Im Moment bin ich mit dem Kompromiss zufrieden, aber ich werde das typeProblem weiter untersuchen, sobald ich Zeit habe. Ich werde meine Antwort aktualisieren, wenn ich eine bessere Lösung finde.

godbyk
quelle
Für mich reduziert das Kommentieren dieser Zeile die Zeit um 50 ms von 230 ms auf 180 ms. Natürlich hatte ich es noch nie so schlimm. 👍
Edward Anderson
Dies hat sich nur um die 60 ms abgeschwächt, sodass ich die Problemumgehung nicht eingehalten habe. Ich habe keine Wartezeiten von zehn Sekunden, aber ungefähr zwei Sekunden, was ein wenig lästig ist.
Danemacmillan
7

Für alle, die zu dem Schluss kommen, dass die Startzeiten für neue Shells unter MacOS zu lang sind, ist dies die Lösung .

Ich habe gerade festgestellt, dass es tatsächlich zwei Pakete gibt, über die installiert werden können brew. Ich habe das bash-completionPaket seit Jahren installiert und mich nie darum gekümmert, es in Frage zu stellen, obwohl ich in dieser Zeit von Bash 3 zu 4 zu jetzt 5 übergegangen bin. Von Zeit zu Zeit würde ich das Problem jedoch noch einmal untersuchen stolpert oft über diese StackOverflow-Diskussion.

Es gibt noch ein Paket bash-completion@2!

Was ist der Unterschied? bash-completionist für Bash Version 3.2. bash-completion@2ist für Bash Version 4.1+ und 5.

Durch das Entfernen des alten bash-completionPakets und die Installation bash-completion@2sind meine Shell-Startzeiten von 605 ms auf 244 ms gesunken. Das ist eine enorme Geschwindigkeitsverbesserung.

Ich vermute, dass viele von uns den gleichen Fehler machen, da die brew infoStatistiken zeigen, dass Ersteres Tonnen von Installationen hat, während Letzteres so wenige hat:

Bildbeschreibung hier eingeben

Es sollte beachtet werden, dass die aktuell gewählte Antwort das Auskommentieren einiger Zeilen erwähnt, was die Startzeiten nur geringfügig verbessert (wenn das alte bash-completionPaket verwendet wird, was wahrscheinlich viele sind), aber keinerlei Auswirkungen auf das neue bash-completion@2Paket hat: dieses neue Paket ist schnell egal was. Das bedeutet, dass keine Hacks erforderlich sind.

TL; DR:

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

Denken Sie daran, den Quellpfad zur Abschlussdatei in Ihrer Datei .bashrcoder zu aktualisieren .bash_profile.

Quellen:


Als etwas verwandtes Thema benutze ich das rcloneDienstprogramm häufig, daher ist es installiert. Es ist auch die größte Abschlussdatei, die ich je gesehen habe . Durch das Entfernen wird die Startzeit meiner Shell auf ~ 120 ms reduziert, was sehr schnell ist.


Bearbeiten:

Für alle, die die technischen Details wissen möchten, die dieses Problem erklären, habe ich ausführlich in den Homebrew-Foren darüber geschrieben . Um es zusammenzufassen, dass der Grund , bash-completion@2so viel schneller ist , weil es geschrieben wurde , so dass es nicht mehr mit Spannung lädt alle Abschluss - Dateien; Stattdessen wird eine Abschlussdatei nach Bedarf geladen oder, wie der Autor es beschreibt, auf nicht eifrige Weise geladen .

danemacmillan
quelle
Ich denke, die Standard-Bash-Version unter macOS ist immer noch v3.2 - ich glaube nicht, dass sie mit Bash v4.2 geliefert wird. Haben Sie eine Referenz, in der steht, dass macOS mit Bash v4.2 + ausgeliefert wird?
Nwinkler
1
@nwinkler Du hättest recht. Ich bin verwirrt, warum ich das erwähnt habe, weil MacOS immer noch mit ausgeliefert wird version 3.2.57(1)-release (x86_64-apple-darwin18). Vielen Dank, dass Sie darauf hingewiesen haben. Ich habe die Linie von meinem Beitrag entfernt.
Danemacmillan
1
Verblüffend, ich weiß ... Danke, dass Sie Ihre Antwort aktualisiert haben!
Nwinkler
3

Mit der Idee, die Godbyk mir gab, stellte ich fest, dass meine PATH-Variable einige Verzeichnisse enthielt, die keine Binärdateien hatten oder nicht existierten, und entfernte sie erheblich. Mit anderen Worten, dies ist der Pfad, den ich in meinem Baschromat hatte:

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

Und dann habe ich es geändert:

PATH="$GOPATH/bin:$PATH"

Dies lag daran, dass die haveFunktion in dieser Bash-Vervollständigung nach jedem Befehl suchte und ich zu viele nutzlose Verzeichnisse hatte, die für jede dieser Binärdateien besucht werden sollten, wodurch sie schneller wurden.

Farid Nouri Neshat
quelle
Ich habe es auch geschafft, die Ladezeit von ungefähr 5 Sekunden auf weniger als 1 Sekunde zu ändern, indem ich Pfade entfernt habe, die in meiner PATH-Umgebungsvariablen nicht vorhanden sind.
juriejan
0

Ich hatte das gleiche Problem. Ein paar einfache Debugging-Tricks brachten mich zur eigentlichen Ursache.

Aktivieren DEBUG modeSie zuerst, damit Sie sehen können, was passiert:

export BASH_COMPLETION_DEBUG=true

Auf diese Weise können Sie ausführlich über die Konsole drucken und den letzten Befehl anzeigen. Sie können das Skript jetzt im Hintergrund ausführen und sehen, was passiert

. /opt/local/etc/bash_completion &

Nimm nicht das PID, womit du dann verfolgen kannst psoder pstree:

pstree -p <the PID>:

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

Wie Sie sehen, wurden einige rostbezogene Befehle gestartet, die Ewigkeiten in Anspruch nahmen.

Das vorübergehende Entfernen /opt/boxen/homebrew/etc/bash_completion.d/cargolöste meine Symptome.

Matthew Fellows
quelle
-1

Wenn Sie mit MacPorts> = 2.1.2 und Mountain Lion arbeiten, scheint dies bash_profilefalsch zu sein. Befolgen Sie die Anweisungen unter So funktioniert git-completion.bash unter Mac OS X? . Ich gehe davon aus, dass dies die automatische Vervollständigung beschleunigen könnte.

Eine andere Lösung wäre, zu versuchen, die automatische Vervollständigung über Fink oder Homebrew zu installieren . Wenn das nicht funktioniert, können Sie auch eine andere Shell ausprobieren. Ich habe festgestellt, dass Fish Shell hervorragend ist, wenn es um die automatische Vervollständigung geht (out of the box). Obwohl Version 2 noch in der Beta ist, kann ich es nur empfehlen.

Ehrfurcht
quelle
-1

Ich vermute, dass Ihre Bash zu alt ist. Ich führe Stock Bash aus, das mit Mountain Lion geliefert wurde, und hier ist, was ich sehe:

$ 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.
numerische Darstellung
quelle
Ich sehe diesen Port-Befehl nicht. :( Wie finde ich heraus, welche Git-Tab-Vervollständigungssoftware auf meinem Mac ausgeführt wird?
Dean Hiller
@DeanHiller Diese Antwort bezieht sich auf den Macports-Paketmanager, der den Befehl port bereitstellt. Macports 'Bash Completion-App ist neuer als die mit OS X gelieferte.
Matt S