【问题标题】:Can I profile my .zshrc/.zshenv?我可以配置我的 .zshrc/.zshenv 吗?
【发布时间】:2011-05-20 01:42:32
【问题描述】:

似乎我的 shell 启动时间太长了。有什么方法可以分析它,以便我弄清楚是什么让它这么慢?

【问题讨论】:

    标签: profiling zsh


    【解决方案1】:

    Zsh 有一个分析模块。在~/.zshrc~/.zshenv开头添加如下:

    # Uncomment to use the profiling module
    # zmodload zsh/zprof
    

    取消注释,启动一个新的交互式shell,然后运行命令zprof。您将获得一份详细的项目列表,您可以查看这些项目以更好地了解您的性能瓶颈在哪里:

    num  calls                time                       self            name
    -----------------------------------------------------------------------------------
     1)    1           7.29     7.29   19.60%      7.29     7.29   19.60%  _p9k_init_ssh
     2)    2           6.72     3.36   18.06%      6.63     3.31   17.81%  gitstatus_start_impl
     3)    1           4.00     4.00   10.75%      4.00     4.00   10.75%  _p9k_must_init
     4)    3          19.28     6.43   51.80%      3.82     1.27   10.28%  (anon)
     5)    1           1.63     1.63    4.37%      1.63     1.63    4.37%  _p9k_restore_state_impl
     6)    1          16.92    16.92   45.46%      1.61     1.61    4.32%  _p9k_precmd_impl
     7)    1           7.13     7.13   19.16%      0.87     0.87    2.33%  _p9k_set_prompt
     8)   22           6.26     0.28   16.83%      0.84     0.04    2.27%  _p9k_build_segment
     9)   17           0.82     0.05    2.19%      0.82     0.05    2.19%  _p9k_param
    10)    6           2.24     0.37    6.02%      0.74     0.12    1.98%  _p9k_left_prompt_segment
    11)    5           0.59     0.12    1.60%      0.59     0.12    1.60%  add-zsh-hook
    12)    1           3.05     3.05    8.20%      0.58     0.58    1.56%  prompt_dir
    

    这里有一个来自speeding up zsh 的单行字,如果开始时间不规律,您会很感激:

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

    运行该作业,您应该会看到如下输出:

            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
            0.05 real         0.02 user         0.02 sys
    

    利润。

    【讨论】:

      【解决方案2】:

      您可以在~/.zshrc 中的第一个可疑点(或开头)开始计时:

      integer t0=$(date '+%s')  # move this around
      ... maybe something suspect ...
      
      # End of zshrc
      function {
          local -i t1 startup
          t1=$(date '+%s')
          startup=$(( t1 - t0 ))
          [[ $startup -gt 1 ]] && print "Hmm, poor shell startup time: $startup"
      }
      unset t0
      

      如果我看到启动速度太慢,这会提醒我,并将其作为永久包装器保留。

      对于更复杂的测量,有一个名为 zprof 的 zsh 模块。就像将~/.zshrc 的内容临时包装在zmodload zsh/zprofzprof 中一样简单。这将转储一些很容易解释的详细分析表。

      zshmodules(1) 手册页中的更多信息。

      当我发现特别慢的东西(rbenv init、vcs_info check-for-changes、antigen、nvm、zsh-mime-setup、解释器版本检查等)时,我添加SLOW cmets 作为提醒,并尝试找到解决方法。缓慢的启动会导致很多痛苦,所以我倾向于避免使用我不了解其内部工作原理的 zsh 包/框架字。 compinit 是我愿意忍受的最慢的东西,大约是总启动时间的一半。

      【讨论】:

        【解决方案3】:

        尝试在文件开头添加:

        # set the trace prompt to include seconds, nanoseconds, script name and line number
        # This is GNU date syntax; by default Macs ship with the BSD date program, which isn't compatible
        PS4='+$(date "+%s:%N") %N:%i> '
        # save file stderr to file descriptor 3 and redirect stderr (including trace 
        # output) to a file with the script's PID as an extension
        exec 3>&2 2>/tmp/startlog.$$
        # set options to turn on tracing and expansion of commands contained in the prompt
        setopt xtrace prompt_subst
        

        最后是这个:

        # turn off tracing
        unsetopt xtrace
        # restore stderr to the value saved in FD 3
        exec 2>&3 3>&-
        

        你应该得到一个详细的日志,显示每行执行的 epoch_second.nanosecond 时间。请注意,GNU date(和操作系统支持)需要具有纳秒级输出。

        编辑:

        添加了 cmets

        编辑 2:

        如果你有 zsh 4.3.12 或更高版本,你应该可以像这样设置PS4 而不是使用date 命令:

        zmodload zsh/datetime
        setopt promptsubst
        PS4='+$EPOCHREALTIME %N:%i> '
        

        它应该可以在 Linux 和 OS X 上运行,从而为您提供纳秒级精度。

        【讨论】:

        • 我在我最初发布的内容中添加了一个非常重要的空间。
        • 确保也使用setopt prompt_subst - 否则$(date ..) 部分不会被替换。
        • 您能否就上面每一行的具体作用添加更多注释?
        • 我写了a blog post about zsh profiling。它包括一个 zsh 脚本,该脚本将日志转换为一个排序列表,其中列出了哪些命令花费的时间最多。 (我按照你的建议使用了 EPOCHREALTIME 和 XTRACE——感谢你写下这个答案!)
        • 您不再需要加载该模块。我不确定哪个版本允许它,但你可以用%D{%s%.} 代替$EPOCHREALTIME
        猜你喜欢
        • 1970-01-01
        • 2019-01-21
        • 2013-08-17
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-11
        相关资源
        最近更新 更多