去掉exec-path-from-shell加快两秒启动时间

如果异步不影响,那根本没必要启动时就加载这个

在 Emacs 29 刚出来时用了一会从源码编译出来的,用了如下代码来解決 macOS 上的 PATH 问题

(let ((paths
       (eval-when-compile
         (with-temp-buffer
           (call-process-shell-command "cat /etc/paths /etc/paths.d/*" nil t)
           (split-string (buffer-string))))))
  (setenv "PATH" (mapconcat #'identity paths ":"))
  (setq exec-path (append paths (list exec-directory))))

起作用的前提是用 macOS 特有的 /etc/paths.d 来管理 path 而不是用 shell profile,作用上等同于用 /usr/libexec/path_helper

这是把 paths 写在 /etc/paths.d 里面吗👀

private/etc/paths.d $ ls
10-pkgsrc  40-XQuartz TeX
private/etc/paths.d $ cat *
/opt/pkg/sbin
/opt/pkg/bin
/opt/X11/bin
/Library/TeX/texbin
private/etc/paths.d $ cat ../paths
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

写死PATH肯定能加快启动。mac上还有一种办法,emacs-plus 编译的时候现在会自动嵌入当前环境变量,理论上都不需要 exec-path-from-shell。不过对于经常变化的场景下就比较麻烦了,所以我选择用 zinit,速度和功能都令人满意。

请教一下,这么配置:


;; Environment: the same path as in your shell, bash or zsh
(when (or sys/macp sys/linuxp (daemonp))
  (use-package exec-path-from-shell
    ;; :demand t
    :config (setq exec-path-from-shell-check-startup-files nil)
    :hook (after-init . exec-path-from-shell-initialize)))

有效吧?

不行,必须立即初始化,否则有些包可能不正常。而且只需在GUI和daemon下启用。

;; Environment: the same path as in your shell, bash or zsh
(when (or sys/mac-x-p sys/linux-x-p (daemonp))
  (use-package exec-path-from-shell
    :init (exec-path-from-shell-initialize)))
2 个赞

谢谢,大佬

先更新了下配置,有空再仔细看下怎么优化 ~

优化很简单,一个是 (setq exec-path-from-shell-arguments '("-l")),或者用 zinit之类的管理zsh/bash

环境变量相关的配置放到 .zshenv (for zsh) or .profile(for bash) 中, 就可以了是吧?

加入这行配置:

(setq exec-path-from-shell-arguments '("-l"))

启动减少到 1 秒左右:

不加:

exec-path-from-shell 在几年前(具体记不得了)用时,就发现很慢,现在没在看过它的实现了。 为了快,2个方面可以改进会有较大的提升:

  1. 将需要copy的环境变量在Emacs退出时保存在文件中,下次加载该文件,读出环境变量;这个过程会很稳定,而且快。
  2. setenv 仅是维护Emacs内置变量process-environment, 也就是说Emacs对环境的更改都是通过维护process-environment的;这是一个interactive函数,考虑了很多场景,也就是说会慢, 可以写1个最简单的可以快很多;
  3. getenv 同样也是慢的,情况简单的考虑用getenv-internal会快;

具体可以看 https://github.com/junjiemars/.emacs.d/blob/cc/config/shells.el

是的,这样会快很多。坏处就是动态的环境变量都无法读取,只能读取固定文件的配置。

动态的环境变量是指什么呢?

  1. 启动Emacs前,更改环境变量,Emacs启动后加载上次的环境变量,这时出现不一致,在Emacs重启后再次与环境一致。
  2. 启动Emacs后变动,更改环境变量,任何程序也无法获知变动的环境变量,这是系统决定的,也是Emacs 使用process-environment的理由;但是在Emacs重启后再次与环境一致。

我说的动态是指shell启动时动态确定的变量,比如要通过语句判断的(跨平台中用得很多)。这样更灵活,如果配置比较稳定就不需要。

其实现在应该根本不用这个插件,在 mac 上 emacs plus 会自动 inject path,在 linux 上好像 path 就是正常的

1 个赞

不用 emacs-plus 还是需要用它的

Linux下不行,除非PATH环境变量是固定的。

要我说直接写死 path 在配置里得了搞这么多麻烦的,反正 mac 都是个人用,也不是在服务器上要天天换来换去需要全自动化部署的。我的 emacs 启动速度 0.5s,linux 上 0.2s,从来都是把它当 vim 一样随开随关的。

我用的就是 emacs-plus.

奇怪的是用这个插件,启动 1秒左右;不用这个插件,反而超过两秒。

其实我更建议手动设置 path,一般情况下是不会变的