Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Multi-Minute Startup?

Many, many thanks for sharing this -- you've saved me countless hours of (probably failing at) figuring this out. I especially appreciated the "fishing lesson" that came with the fish, i.e. the TRACE_ZSH_* tips.

I do wish zsh would make it a little less cumbersome for all of us though -- you and I can't be the only people with these environmental issues.


On Aug 10, 2008, at 6:03 AM, Phil Pennock wrote:

On 2008-08-08 at 11:16 -0700, Eric D. Friedman wrote:
I was the original poster with that long completion pause and none of
the suggested solutions actually worked out.  Following the advice in
this thread, I ran a shell with -l -x on and captured the relavant

Working in an NFS/LDAP/Kerberos environment with a largish number of
users (>10k), I periodically have to debug "what's gone wrong now?".

In ~/.zshenv I set:
----------------------------8< cut here >8------------------------------
[[ -n $TRACE_ZSH_TIME ]] && PS4='+[%D{%M:%S}]%N:%i> '
if [[ -n $TRACE_ZSH ]]; then
       [[ -n "$TRACE_ZSH_FILE" ]] && exec 2> "${TRACE_ZSH_FILE}"
       setopt xtrace
----------------------------8< cut here >8------------------------------


This is often informative.

      The big pause occurs at the last line in the following.  Any
ideas as to what else I could try? My goal is to not have the
completion system show me every user in my company's home dir when I
do the first cd<TAB>; I'd never use that completion and it takes far
too long to get it anyway.
+_all_labels:39> compadd -F _comp_ignore -J -default- -qS/ -k userdirs

Various things I tried were never sufficient, as userdirs would always
get populated somehow.  Until I cheated.

The short version: ensure that 'userdirs' is a local variable inside the
completion system, populated with the values you want.  I do this by
adding to $_comp_setup -- making sure that none of the rest of the
things that hit LDAP cause slow-downs have led to what I have below.

I keep the users I want to tab-complete in a file, ~/.userdirs and then hack things so that only that is used. My code uses zfilter_comments() which is a function I frequently use to pull in files for data and skip
comments, etc.  Comments in files are handy, reading those files
efficiently in zsh also handy.

The main things are to avoid the automatic population of userdirs when
it's empty and to ensure that things like ssh, scp, etc don't hit LDAP
either. I have ~/.sshusers contain things like my own usercode, "root"
and various production accounts.  ~/.sshhosts contains hostnames.

Note that I have "users whose home-directories I care about" and "users
I ssh to the accounts of" and these are very different; the former
includes colleagues and the latter includes role accounts.  Because of
this split, we have the loop setting completion of users to $sshusers
for only some commands.  Hrm, wonder why 'users' is used, not

Note that using "zstyle -e" and "reply=($array)" lets me modify the
array at run-time and have it immediately affect completion.

"is-at-least" is one of the Misc/ functions provided, I autoload it
before this point.

I make sure that I split up the completion dumps by host since different
hosts have different versions of zsh, etc etc, so I don't want that
continually getting trashed within NFS.

Here's hoping that I'm not missing anything relevant when looking over
my config now.  Believe it or not, this is simplified.

----------------------------8< cut here >8------------------------------
function zfilter_comments {
       local f infile="$1"
       while read f; do
[[ -n ${f%%[$' \t']*\#*} && ${f#[#;]} == $f ]] || continue
               print -r -- ${f%%[$' \t']*\#*}
       done < "$infile"

typeset -a sshhosts sshusers
[[ -f ~/.sshhosts ]] && sshhosts=( $(zfilter_comments ~/.sshhosts) )
[[ -f ~/.sshusers ]] && sshusers=( $(zfilter_comments ~/.sshusers) )

local c
for c in ssh rsync sftp scp slogin
       [[ ${#sshhosts} -gt 0 ]] && \
         zstyle -e ':completion:*:'"$c"':*' hosts 'reply=($sshhosts)'
       [[ ${#sshusers} -gt 0 ]] && \
         zstyle -e ':completion:*:'"$c"':*' users 'reply=($sshusers)'
unset c

zstyle -e ':completion:*' my-accounts 'reply=($sshusers)'
zstyle ':completion:*' other-accounts ''
zstyle -e ':completion:*' accounts 'reply=($sshusers)'

function reset_userdirs {
# There is a zsh internal map, userdirs, exposed by zsh/parameter;
# it's read-only though.
	[[ -f ~/.userdirs ]] || return
	local _u
	local -a _ud
	_ud=( $(zfilter_comments ~/.userdirs) )
	for _u in $_ud; do hash -d $_u="/home/$_u"; done

if is-at-least 4.2.0; then autoload -Uz compinit ; else autoload -U compinit ; fi [[ -d "${ZDOTDIR:-$HOME}/.zcompdumps" ]] || mkdir -m 0700 -p "$ {ZDOTDIR:-$HOME}/.zcompdumps"
compinit -u -d "${ZDOTDIR:-$HOME}/.zcompdumps/${HOST%%.*}"

# Hack to turn off userdirs completion by overriding userdirs.
# This overrides userdirs as a local variable inside the completion
# system, not touching the global variable.  We don't need to load
# zsh/parameter to achieve this.
_comp_setup+=$'\ntypeset -a userdirs\nreset_userdirs'
----------------------------8< cut here >8------------------------------


Messages sorted by: Reverse Date, Date, Thread, Author