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

Re: Multi-Minute Startup?

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  
> bits.

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------------------------------


Attachment: pgpdRbPUndn66.pgp
Description: PGP signature

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