[PATCH v2] Speed up bash completion loading

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Jonathan Nieder
Date: Sunday, November 15, 2009 - 3:29 am

On my slow laptop (P3 600MHz), system-wide bash completions take
too much time to load (> 2s), and a significant fraction of this
time is spent loading git-completion.bash:

$ time bash -c ". ./git-completion.bash"  # hot cache, before this patch

real    0m0.509s
user    0m0.310s
sys     0m0.180s

Kirill noticed that most of the time is spent warming up the
merge_strategy, all_command and porcelain_command caches.

Since git is not used in each and every interactive xterm, it
seems best to load completion support with cold caches and then
load each needed thing lazily.  This has most of the speed
advantage of pre-generating everything at build time, without the
complication of figuring out at build time what commands will be
available at run time.

The result is that loading completion is significantly faster
now:

$ time bash -c ". ./git-completion.bash"  # cold cache, after this patch

real    0m0.171s
user    0m0.060s
sys     0m0.040s

Suggested-by: Kirill Smelkov <kirr@mns.spb.ru>
Cc: Shawn O. Pearce <spearce@spearce.org>
Cc: Stephen Boyd <bebarino@gmail.com>
Cc: SZEDER Gábor <szeder@ira.uka.de>
Cc: Sverre Rabbelier <srabbelier@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
This version incorporates the small improvements previously sent, plus the
following nice one (which makes caching merge strategies safe again).
Thanks for the advice, everyone.

Junio C Hamano wrote:

Yes. :)

 contrib/completion/git-completion.bash |   76 +++++++++++++++++---------------
 1 files changed, 41 insertions(+), 35 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index e3ddecc..43d76b7 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -21,13 +21,7 @@
 #    2) Added the following line to your .bashrc:
 #        source ~/.git-completion.sh
 #
-#    3) You may want to make sure the git executable is available
-#       in your PATH before this script is sourced, as some caching
-#       is performed while the script loads.  If git isn't found
-#       at source time then all lookups will be done on demand,
-#       which may be slightly slower.
-#
-#    4) Consider changing your PS1 to also show the current branch:
+#    3) Consider changing your PS1 to also show the current branch:
 #        PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
 #
 #       The argument to __git_ps1 will be displayed only if you
@@ -324,12 +318,8 @@ __git_remotes ()
 	done
 }
 
-__git_merge_strategies ()
+__git_list_merge_strategies ()
 {
-	if [ -n "${__git_merge_strategylist-}" ]; then
-		echo "$__git_merge_strategylist"
-		return
-	fi
 	git merge -s help 2>&1 |
 	sed -n -e '/[Aa]vailable strategies are: /,/^$/{
 		s/\.$//
@@ -339,8 +329,17 @@ __git_merge_strategies ()
 		p
 	}'
 }
-__git_merge_strategylist=
-__git_merge_strategylist=$(__git_merge_strategies 2>/dev/null)
+
+unset __git_merge_strategies
+# 'git merge -s help' (and thus detection of the merge strategy
+# list) fails, unfortunately, if run outside of any git working
+# tree.  __git_merge_strategies is set to the empty string in
+# that case, and the detection will be repeated the next time it
+# is needed.
+__git_compute_merge_strategies ()
+{
+	: ${__git_merge_strategies:=$(__git_list_merge_strategies)}
+}
 
 __git_complete_file ()
 {
@@ -474,27 +473,24 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	__git_compute_merge_strategies
 	case "${COMP_WORDS[COMP_CWORD-1]}" in
 	-s|--strategy)
-		__gitcomp "$(__git_merge_strategies)"
+		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
 	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--strategy=*)
-		__gitcomp "$(__git_merge_strategies)" "" "${cur##--strategy=}"
+		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
 		return 0
 		;;
 	esac
 	return 1
 }
 
-__git_all_commands ()
+__git_list_all_commands ()
 {
-	if [ -n "${__git_all_commandlist-}" ]; then
-		echo "$__git_all_commandlist"
-		return
-	fi
 	local i IFS=" "$'\n'
 	for i in $(git help -a|egrep '^  [a-zA-Z0-9]')
 	do
@@ -504,17 +500,18 @@ __git_all_commands ()
 		esac
 	done
 }
-__git_all_commandlist=
-__git_all_commandlist="$(__git_all_commands 2>/dev/null)"
 
-__git_porcelain_commands ()
+unset __git_all_commands
+__git_compute_all_commands ()
+{
+	: ${__git_all_commands=$(__git_list_all_commands)}
+}
+
+__git_list_porcelain_commands ()
 {
-	if [ -n "${__git_porcelain_commandlist-}" ]; then
-		echo "$__git_porcelain_commandlist"
-		return
-	fi
 	local i IFS=" "$'\n'
-	for i in "help" $(__git_all_commands)
+	__git_compute_all_commands
+	for i in "help" $__git_all_commands
 	do
 		case $i in
 		*--*)             : helper pattern;;
@@ -595,8 +592,13 @@ __git_porcelain_commands ()
 		esac
 	done
 }
-__git_porcelain_commandlist=
-__git_porcelain_commandlist="$(__git_porcelain_commands 2>/dev/null)"
+
+unset __git_porcelain_commands
+__git_compute_porcelain_commands ()
+{
+	__git_compute_all_commands
+	: ${__git_porcelain_commands=$(__git_list_porcelain_commands)}
+}
 
 __git_aliases ()
 {
@@ -1088,7 +1090,8 @@ _git_help ()
 		return
 		;;
 	esac
-	__gitcomp "$(__git_all_commands)
+	__git_compute_all_commands
+	__gitcomp "$__git_all_commands
 		attributes cli core-tutorial cvs-migration
 		diffcore gitk glossary hooks ignore modules
 		repository-layout tutorial tutorial-2
@@ -1444,7 +1447,8 @@ _git_config ()
 		return
 		;;
 	pull.twohead|pull.octopus)
-		__gitcomp "$(__git_merge_strategies)"
+		__git_compute_merge_strategies
+		__gitcomp "$__git_merge_strategies"
 		return
 		;;
 	color.branch|color.diff|color.interactive|\
@@ -1545,7 +1549,8 @@ _git_config ()
 	pager.*)
 		local pfx="${cur%.*}."
 		cur="${cur#*.}"
-		__gitcomp "$(__git_all_commands)" "$pfx" "$cur"
+		__git_compute_all_commands
+		__gitcomp "$__git_all_commands" "$pfx" "$cur"
 		return
 		;;
 	remote.*.*)
@@ -2142,7 +2147,8 @@ _git ()
 			--help
 			"
 			;;
-		*)     __gitcomp "$(__git_porcelain_commands) $(__git_aliases)" ;;
+		*)     __git_compute_porcelain_commands
+		       __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;;
 		esac
 		return
 	fi
-- 
1.6.5.2

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
excerpts from tomorrow's &quot;What's cooking&quot; draft, Junio C Hamano, (Wed Nov 11, 2:34 am)
Re: excerpts from tomorrow's &quot;What's cooking&quot; draft, Sverre Rabbelier, (Wed Nov 11, 10:57 am)
Re: excerpts from tomorrow's &quot;What's cooking&quot; draft, Nicolas Sebrecht, (Wed Nov 11, 11:42 am)
Re: excerpts from tomorrow's &quot;What's cooking&quot; draft, Daniel Barkalow, (Wed Nov 11, 11:45 am)
Re: excerpts from tomorrow's &quot;What's cooking&quot; draft, Nicolas Sebrecht, (Wed Nov 11, 2:26 pm)
ks/precompute-completion, Jonathan Nieder, (Wed Nov 11, 3:08 pm)
[PATCH] give priority to progress messages, Nicolas Pitre, (Wed Nov 11, 3:24 pm)
Re: ks/precompute-completion, Stephen Boyd, (Thu Nov 12, 11:40 pm)
Re: ks/precompute-completion, Jonathan Nieder, (Fri Nov 13, 12:06 am)
Re: ks/precompute-completion, Stephen Boyd, (Fri Nov 13, 12:12 am)
[PATCH] Speed up bash completion loading, Jonathan Nieder, (Fri Nov 13, 1:50 am)
Re: [PATCH] Speed up bash completion loading, Jonathan Nieder, (Fri Nov 13, 2:03 am)
Re: [PATCH] Speed up bash completion loading, Jonathan Nieder, (Fri Nov 13, 3:29 am)
Re: [PATCH] Speed up bash completion loading, Stephen Boyd, (Fri Nov 13, 1:43 pm)
Re: [PATCH] Speed up bash completion loading, Jonathan Nieder, (Sat Nov 14, 3:35 am)
Re: [PATCH] Speed up bash completion loading, Jonathan Nieder, (Sat Nov 14, 4:01 am)
Re: [PATCH] Speed up bash completion loading, SZEDER =?iso-8859-1? ..., (Sat Nov 14, 7:43 am)
Re: [PATCH] Speed up bash completion loading, Jonathan Nieder, (Sat Nov 14, 12:33 pm)
Re: [PATCH] Speed up bash completion loading, Stephen Boyd, (Sat Nov 14, 4:46 pm)
Re: excerpts from tomorrow's &quot;What's cooking&quot; draft, Sverre Rabbelier, (Sat Nov 14, 7:07 pm)
Re: [PATCH] Speed up bash completion loading, Jonathan Nieder, (Sat Nov 14, 11:50 pm)
Re: [PATCH] Speed up bash completion loading, Junio C Hamano, (Sun Nov 15, 2:05 am)
[PATCH v2] Speed up bash completion loading, Jonathan Nieder, (Sun Nov 15, 3:29 am)
Re: [PATCH v2] Speed up bash completion loading, Shawn O. Pearce, (Sun Nov 15, 6:55 pm)
Re: [PATCH v2] Speed up bash completion loading, Stephen Boyd, (Mon Nov 16, 1:28 am)
[PATCH v3] Speed up bash completion loading, Jonathan Nieder, (Tue Nov 17, 5:49 pm)
Re: [PATCH v3] Speed up bash completion loading, Shawn O. Pearce, (Tue Nov 17, 5:59 pm)