Как уменьшить влияние изменения значения массива `fpath` на время запуска zsh?

Я использую zsh версии 5.1.1 и tmux версии 2.3 , и недавно я заметил, что запуск новой оболочки (через новое окно или панель в tmux ) занимает больше времени, чем раньше.

Мне достаточно набрать около 5 символов до появления подсказки. Я бы хотел уменьшить это время, поэтому я написал оператор return на разных позициях внутри моего файла zshrc пока не нашел строку, которая отвечала за увеличение времени начала. Это кажется:

 fpath=(~/.zsh/completion $fpath) 

И я могу воспроизвести мою проблему со следующим минимальным zshrc :

 fpath=(~/.zsh/completion $fpath) autoload -Uz compinit compinit 

Первая строка добавляет путь ~/.zsh/completion к массиву fpath . Я делаю это, потому что хочу записать файлы, содержащие код моих пользовательских функций завершения внутри этого каталога.

Чтобы понять, сколько времени требуется для запуска оболочки, я нашел эту команду:

 for i in $(seq 1 10); do /usr/bin/time zsh -i -c exit; done 

Он запускается и выходит из 10 снарядов последовательно, каждый раз измеряя время, которое потребовалось. Вот что он сообщает с предыдущим минимальным zshrc :

 0.36user 0.04system 0:00.42elapsed 96%CPU (0avgtext+0avgdata 6056maxresident)k 0inputs+160outputs (0major+9087minor)pagefaults 0swaps 0.30user 0.04system 0:00.36elapsed 96%CPU (0avgtext+0avgdata 5900maxresident)k 0inputs+160outputs (0major+8949minor)pagefaults 0swaps 0.30user 0.05system 0:00.37elapsed 96%CPU (0avgtext+0avgdata 6080maxresident)k 0inputs+160outputs (0major+8992minor)pagefaults 0swaps 0.31user 0.04system 0:00.37elapsed 95%CPU (0avgtext+0avgdata 5936maxresident)k 0inputs+160outputs (0major+8956minor)pagefaults 0swaps 0.30user 0.04system 0:00.36elapsed 96%CPU (0avgtext+0avgdata 6052maxresident)k 0inputs+160outputs (0major+9089minor)pagefaults 0swaps 0.32user 0.04system 0:00.38elapsed 96%CPU (0avgtext+0avgdata 5944maxresident)k 0inputs+160outputs (0major+8948minor)pagefaults 0swaps 0.32user 0.04system 0:00.37elapsed 95%CPU (0avgtext+0avgdata 6004maxresident)k 0inputs+160outputs (0major+8991minor)pagefaults 0swaps 0.32user 0.02system 0:00.36elapsed 96%CPU (0avgtext+0avgdata 6056maxresident)k 0inputs+160outputs (0major+9109minor)pagefaults 0swaps 0.30user 0.05system 0:00.36elapsed 96%CPU (0avgtext+0avgdata 6072maxresident)k 0inputs+160outputs (0major+9003minor)pagefaults 0swaps 0.31user 0.04system 0:00.36elapsed 96%CPU (0avgtext+0avgdata 6040maxresident)k 0inputs+160outputs (0major+9055minor)pagefaults 0swaps 

Я не уверен, что прочитал это правильно, но, похоже, это означает, что в среднем для запуска требуется 0.32 секунды.

Вот что fpath=(...) та же команда с тем же минимальным zshrc после комментирования строки fpath=(...) :

 0.08user 0.02system 0:00.10elapsed 97%CPU (0avgtext+0avgdata 5608maxresident)k 0inputs+0outputs (0major+1721minor)pagefaults 0swaps 0.06user 0.00system 0:00.07elapsed 97%CPU (0avgtext+0avgdata 5660maxresident)k 0inputs+0outputs (0major+1723minor)pagefaults 0swaps 0.05user 0.00system 0:00.06elapsed 92%CPU (0avgtext+0avgdata 5680maxresident)k 0inputs+0outputs (0major+1720minor)pagefaults 0swaps 0.05user 0.00system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 5724maxresident)k 0inputs+0outputs (0major+1734minor)pagefaults 0swaps 0.04user 0.02system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 5748maxresident)k 0inputs+0outputs (0major+1730minor)pagefaults 0swaps 0.05user 0.00system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 5692maxresident)k 0inputs+0outputs (0major+1724minor)pagefaults 0swaps 0.04user 0.01system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 5636maxresident)k 0inputs+0outputs (0major+1728minor)pagefaults 0swaps 0.04user 0.01system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 5628maxresident)k 0inputs+0outputs (0major+1727minor)pagefaults 0swaps 0.04user 0.01system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 5684maxresident)k 0inputs+0outputs (0major+1722minor)pagefaults 0swaps 0.05user 0.00system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 5728maxresident)k 0inputs+0outputs (0major+1731minor)pagefaults 0swaps 

Теперь, в среднем, он занимает всего 0.05 секунды.

По умолчанию значение FPATH равно:

 /usr/local/share/zsh/site-functions:/usr/share/zsh/vendor-functions:/usr/share/zsh/vendor-completions:/usr/share/zsh/functions/Calendar:/usr/share/zsh/functions/Chpwd:/usr/share/zsh/functions/Completion:/usr/share/zsh/functions/Completion/AIX:/usr/share/zsh/functions/Completion/BSD:/usr/share/zsh/functions/Completion/Base:/usr/share/zsh/functions/Completion/Cygwin:/usr/share/zsh/functions/Completion/Darwin:/usr/share/zsh/functions/Completion/Debian:/usr/share/zsh/functions/Completion/Linux:/usr/share/zsh/functions/Completion/Mandriva:/usr/share/zsh/functions/Completion/Redhat:/usr/share/zsh/functions/Completion/Solaris:/usr/share/zsh/functions/Completion/Unix:/usr/share/zsh/functions/Completion/X:/usr/share/zsh/functions/Completion/Zsh:/usr/share/zsh/functions/Completion/openSUSE:/usr/share/zsh/functions/Exceptions:/usr/share/zsh/functions/MIME:/usr/share/zsh/functions/Misc:/usr/share/zsh/functions/Newuser:/usr/share/zsh/functions/Prompts:/usr/share/zsh/functions/TCP:/usr/share/zsh/functions/VCS_Info:/usr/share/zsh/functions/VCS_Info/Backends:/usr/share/zsh/functions/Zftp:/usr/share/zsh/functions/Zle 

В начале переменной я заметил путь /usr/local/share/zsh/site-functions .
Это был пустой каталог, поэтому я удалил его и заменил его символической ссылкой, целью которой является мой каталог завершения:

 cd /usr/local/share/zsh; sudo rm site-functions; sudo ln -s ~/.zsh/completion site-functions 

С этой символической ссылкой мне не нужно менять значение fpath . Функции завершения все еще работают, и время начала снарядов было разделено на 4 , от примерно 0.32 секунды до примерно 0.08 секунды. Эта разница заметна для меня. Тем не менее, он не имеет права использовать общесистемный каталог.

Есть ли другой, лучший способ достичь такого же результата?


Редактировать:

Благодаря @thrig я понял, что мой ~/.zsh/ на самом деле является символической ссылкой на каталог Dropbox:

 ls -l .zsh lrwxrwxrwx 1 user user 16 jan. 18 18:54 .zsh -> Dropbox/conf/zsh 

Я сделал это, чтобы иметь резервную копию моей конфигурации, и потому, что я не знаю, как использовать git.

Если переместить функции завершения в каталог вне Dropbox, время начала zsh станет намного ниже.


Изменить 2:

Я не понимаю, теперь кажется, что zsh снова начинает медленно, даже если я поместил свои функции завершения вне каталога Dropbox.

В случае, если это помогает, я загрузил на сайт, похожий на pastebin, вывод следующей команды:

 strace -e trace=desc -o log -r zsh 

Согласно man strace , параметр -e trace=desc должен отслеживать все системные вызовы, связанные с файловым дескриптором. -r должен печатать относительную метку времени при входе в каждый системный вызов.

Вот ссылка для журнала, когда fpath не изменился .
И вот 2-я ссылка для журнала при изменении fpath .

Я не могу интерпретировать файлы журнала, но есть большая разница в размере. Первый, по-видимому, включает около 4000 системных вызовов, а второй – около 67000 .


Редактировать 3:

Я также записал вывод следующей команды:

 PS4='+[%D{%H:%M:%S.%.}]%N:%i> ' zsh -x 

… с помощью утилиты script .

Вот ссылка на файл журнала, когда fpath не изменился .
И вот ссылка на файл журнала при изменении fpath .

На этот раз первый файл журнала содержит всего около 600 строк, а второй – около 100000 строк.

В файле журнала, где fpath , функции, которые чаще всего называются compdef (около 69000 раз), compinit (около 16000 раз) и compdump (около 14000 раз).

Благодарим вас за помощь, оказанную в комментариях.

  • Стандартный / канонический способ проверить, выводит ли предыдущий трубопровод выпуск?
  • Более быстрый запуск zsh
  • Как я могу применить `cut` к нескольким файлам, а затем« вставить »результаты?
  • Получение команды tree для отображения каталогов
  • Расширение тильды в zsh
  • alias vs export для простых команд
  • Почему высокие коды выхода на Linux-оболочках (> = 256) работают не так, как ожидалось?
  • В чем разница между тем, где и где
  • One Solution collect form web for “Как уменьшить влияние изменения значения массива `fpath` на время запуска zsh?”

    Я думал, что, возможно, проблема возникла из моей версии zsh, поэтому я очистил пакет zsh и скомпилировал его из источника:

     % sudo aptitude install git-core gcc make autoconf yodl libncursesw5-dev texinfo % git clone git://zsh.git.sf.net/gitroot/zsh/zsh % cd zsh % git checkout zsh-5.3.1 % ./Util/preconfig % ./configure --build=x86_64-linux-gnu \ --prefix=/usr \ --includedir=/usr/include \ --mandir=/usr/share/man \ --infodir=/usr/share/info \ --sysconfdir=/etc \ --localstatedir=/var \ --libdir=/usr/lib/x86_64-linux-gnu \ --libexecdir=/usr/lib/x86_64-linux-gnu \ --bindir=/bin \ LDFLAGS="-Wl,--as-needed -g" \ --enable-maildir-support \ --enable-etcdir=/etc/zsh \ --enable-function-subdirs \ --enable-site-fndir=/usr/local/share/zsh/site-functions \ --enable-fndir=/usr/share/zsh/functions \ --with-tcsetpgrp \ --with-term-lib="ncursesw tinfo" \ --enable-cap \ --enable-pcre \ --enable-readnullcmd=pager \ --enable-custom-patchlevel=Debian \ --enable-additional-fpath=/usr/share/zsh/vendor-functions,/usr/share/zsh/vendor-completions \ --disable-ansi2knr 

    Я нашел зависимости и параметры конфигурации, прочитав файл INSTALL а также этот метод, найденный в Google:

     https://gist.github.com/nicoulaj/715855 

    … и посмотрев, как разработчики Ubuntu скомпилировали последние пакеты zsh :

     https://launchpadlibrarian.net/280509421/buildlog_ubuntu-yakkety-amd64.zsh_5.2-5ubuntu1_BUILDING.txt.gz 

    Были некоторые варианты, которые были написаны дважды или не были распознаны zsh, поэтому я удалил их. Значение, которое разработчики Ubuntu предоставили LDFLAGS , похоже, не работает на моей машине, поэтому я скопировал тот, что был из gist на Github. Параметры, которые я сохранил, описаны ./configure --help :

     --build=BUILD configure for building on BUILD [guessed] --prefix=PREFIX install architecture-independent files in PREFIX [/usr/local] --includedir=DIR C header files [PREFIX/include] --mandir=DIR man documentation [DATAROOTDIR/man] --infodir=DIR info documentation [DATAROOTDIR/info] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --libexecdir=DIR program executables [EPREFIX/libexec] --bindir=DIR user executables [EPREFIX/bin] LDFLAGS linker flags, eg -L<lib dir> if you have libraries in a nonstandard directory <lib dir> --enable-maildir-support enable maildir support in MAIL and MAILPATH --enable-etcdir=DIR the default directory for global zsh scripts --enable-function-subdirs install functions in subdirectories --enable-site-fndir=DIR same for site functions (not version specific) --enable-fndir=DIR the directory in which to install functions --with-tcsetpgrp assumes that tcsetpgrp() exists and works correctly --with-term-lib=LIBS search space-separated LIBS for terminal handling --enable-cap enable the search for POSIX capabilities (may require additional headers to be added by hand) --enable-pcre enable the search for the pcre library (may create run-time library dependencies) --enable-readnullcmd=PAGER pager used when READNULLCMD is not set --enable-custom-patchlevel set a custom ZSH_PATCHLEVEL value --enable-additional-fpath=DIR add directories to default function path --enable-ansi2knr translate source to K&R C before compiling номера --build=BUILD configure for building on BUILD [guessed] --prefix=PREFIX install architecture-independent files in PREFIX [/usr/local] --includedir=DIR C header files [PREFIX/include] --mandir=DIR man documentation [DATAROOTDIR/man] --infodir=DIR info documentation [DATAROOTDIR/info] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --libexecdir=DIR program executables [EPREFIX/libexec] --bindir=DIR user executables [EPREFIX/bin] LDFLAGS linker flags, eg -L<lib dir> if you have libraries in a nonstandard directory <lib dir> --enable-maildir-support enable maildir support in MAIL and MAILPATH --enable-etcdir=DIR the default directory for global zsh scripts --enable-function-subdirs install functions in subdirectories --enable-site-fndir=DIR same for site functions (not version specific) --enable-fndir=DIR the directory in which to install functions --with-tcsetpgrp assumes that tcsetpgrp() exists and works correctly --with-term-lib=LIBS search space-separated LIBS for terminal handling --enable-cap enable the search for POSIX capabilities (may require additional headers to be added by hand) --enable-pcre enable the search for the pcre library (may create run-time library dependencies) --enable-readnullcmd=PAGER pager used when READNULLCMD is not set --enable-custom-patchlevel set a custom ZSH_PATCHLEVEL value --enable-additional-fpath=DIR add directories to default function path --enable-ansi2knr translate source to K&R C before compiling 

    Компиляция работала, но из 48 тестов, выполненных командой make check было 2 отказа:

     % make % make check … ************************************** 46 successful test scripts, 2 failures, 0 skipped ************************************** Makefile:187: recipe for target 'check' failed make[1]: *** [check] Error 1 make[1]: Leaving directory '/home/user/GitRepos/zsh/Test' Makefile:263: recipe for target 'check' failed make: *** [check] Error 2 

    Я не мог избавиться от них.

    Наконец, вместо того, чтобы использовать make install для установки двоичного checkinstall , я использовал checkinstall чтобы иметь .deb который я могу удалить, если мне нужно изменить оболочку в будущем (с dpkg -r zsh ):

     % sudo checkinstall 

    Во время установки мне пришлось дать краткое описание (я использовал shell with lots of features ), и, что более важно, мне пришлось дать версию. Без версии, совместимой с политикой Debian, checkinstall не будет генерировать .deb . Я просмотрел вывод политики apt-cache policy zsh чтобы проверить, что такое схема именования, используемая Debian, и выбрал 5.3.1-1ubuntu2 .

     % echo /bin/zsh >> /etc/shells % chsh → /bin/zsh 

    Эти 2 строки были необходимы, чтобы Ubuntu распознал /bin/zsh в качестве допустимой оболочки входа и сделал ее моей оболочкой по умолчанию.

    Теперь версия оболочки 5.3.1 (вместо 5.1.1 ):

     % zsh --version zsh 5.3.1 (x86_64-pc-linux-gnu) 

    И оболочка начинает быстро (около 0.04s ):

     % repeat 10 =time zsh -i -c exit 0.06user 0.03system 0:00.12elapsed 80%CPU (0avgtext+0avgdata 5592maxresident)k 0inputs+0outputs (0major+5668minor)pagefaults 0swaps 0.06user 0.01system 0:00.09elapsed 77%CPU (0avgtext+0avgdata 5480maxresident)k 0inputs+0outputs (0major+5634minor)pagefaults 0swaps 0.04user 0.01system 0:00.07elapsed 82%CPU (0avgtext+0avgdata 5736maxresident)k 0inputs+0outputs (0major+5641minor)pagefaults 0swaps 0.04user 0.01system 0:00.07elapsed 77%CPU (0avgtext+0avgdata 5652maxresident)k 0inputs+0outputs (0major+5645minor)pagefaults 0swaps 0.03user 0.03system 0:00.07elapsed 82%CPU (0avgtext+0avgdata 5736maxresident)k 0inputs+0outputs (0major+5634minor)pagefaults 0swaps 0.04user 0.01system 0:00.07elapsed 78%CPU (0avgtext+0avgdata 5548maxresident)k 0inputs+0outputs (0major+5624minor)pagefaults 0swaps 0.04user 0.02system 0:00.07elapsed 78%CPU (0avgtext+0avgdata 5612maxresident)k 0inputs+0outputs (0major+5655minor)pagefaults 0swaps 0.04user 0.01system 0:00.07elapsed 77%CPU (0avgtext+0avgdata 5780maxresident)k 0inputs+0outputs (0major+5624minor)pagefaults 0swaps 0.03user 0.02system 0:00.07elapsed 78%CPU (0avgtext+0avgdata 5584maxresident)k 0inputs+0outputs (0major+5641minor)pagefaults 0swaps 0.03user 0.02system 0:00.07elapsed 78%CPU (0avgtext+0avgdata 5668maxresident)k 

    В первый раз, когда я скомпилировал, я забыл переключиться на последнюю ветку релиза, поэтому я был на master .
    Эта версия разработки zsh имела еще худшее время запуска, чем версия из репозиториев Ubuntu. Около 0.42s чтобы запустить оболочку. Но опять же, только если я добавил каталог в fpath в zshrc и создал файл внутри последнего (достаточно простого touch file ).

    Поэтому я задаюсь вопросом, возникла ли эта проблема из вариантов компиляции или версии выпуска. Я надеюсь, что релизная версия, которую я собрал, будет оставаться быстрой …

    Спасибо @thrigh и @ Stéphane Chazelas за то, что помогли мне в комментариях.

    Interesting Posts

    nullmailer: Ошибка отправки: не удалось выполнить программу exec

    Что я должен знать, когда я определяю функцию bash для использования имени программы?

    Bash не правильно вычисляет длину подсказки

    Как установить MS Core Fonts без моего рабочего переключения на них?

    Создание пользователя с помощью / sbin / nologin, любое преимущество для запуска passwd и установки на случайные

    Как я могу перейти к предыдущему / следующему каталогу?

    Печатать коннективные символы Юникода, используя одно нажатие клавиши

    Слова Devanagari (комбинированные) отображаются неправильно

    Улучшения полосы пропускания ожидаются от перехода на Wayland или Mir?

    sed + удалить строки, содержащие строку, кроме строк с

    Лучшее ускорение строки для hg

    Определение источника установленной файловой системы в Unix

    Как монтировать контейнер cryptsetup только с `mount`?

    liferea: изменить цвет ссылки по умолчанию

    Как настроить среду для es?

    Linux и Unix - лучшая ОС в мире.