使用 Gcc Jit 为 emacs 加速
1 背景
1.1 native-comp
前段时间 emacs 正式发布了 28.1, 其中一项重要特性就是合并了之前的 native-comp 分支( 俗称gccemacs). GCC Emacs 是一种利用 libgccjit 来编译 Elisp 的技术, 目标是提升 Emacs 以及 package 的启动速度和运行速度, 相比没有优化过的版本, 性能平均提高 3.7 倍.
我一直在使用 emacs 的测试版( 现在是emacs29 ), 因此对于 native-comp 也用了好几个月. 个人体验来讲, 除了编译时间比较长之外, 其他地方都很稳定, 而且使用起来也十分方便, 推荐大家在觉得性能有问题的时候进行尝试.
1.2 Just-In-Time Compilation
关于什么是 GCC JIT, 引用官网的一小段话:
GCC can be built as a shared library “libgccjit.so”, for generating machine code from API calls, using GCC as the backend. This shared library can then be dynamically-linked into bytecode interpreters and other such programs that want to generate machine code “on the fly” at run-time.
我尽量用简短的言语解释:
- 一个程序在它运行的时候创建并且运行了全新的代码, 并非那些最初作为这个程序的一部分保存在硬盘上的固有代码, 这就是所谓的 Just In Time.
- JIT 会把一些运行频繁的代码编译成本地机器相关的机器码, 这种直接执行机器指令能提高性能.
- JIT 还会进行一些编译优化, 比如逃逸分析, 锁消除, 类型检测消除, 方法内联等等, 从而提高速度.
上述是对 JIT 非常粗浅的介绍, GCC JIT 做的远不止这些, 感兴趣的小伙伴可以自行查阅.
2 安装
2.1 gcc jit环境
尝鲜的用户建议直接根据发行版安装 libgccjit 包以节省编译时间, 比如如果你是arch 用户, 可以直接 yay -S libgccjit-git
一键安装.
下面给出更为通用的本地编译方案: 首先 git clone 一个完整的 gcc 仓库, 推荐使用 github 上的 mirror 以获得更快的速度
git clone --depth=1 https://github.com/gcc-mirror/gcc.git
接着进行编译
mkdir build
cd build
../src/configure --enable-host-shared --enable-languages=jit,c,c++,objc,obj-c++ --enable-checking=release --disable-bootstrap
make -j12
make install
2.2 emacs
2.2.1 常规
接下来是 emacs 的安装, 同样推荐使用 github 上的 mirror:
git clone --depth=1 https://github.com/emacs-mirror/emacs.git
接下来进行编译:
./autogen.sh
./configure --with-nativecomp
make -j12 NATIVE_FULL_AOT=1
make install
注:
- 其中
NATIVE_FULL_AOT
是可选指令, 会强制把所有的 el 文件提前编译成 eln, 编译时间会大幅度增加, 如果你并不着急使用, 建议加上以节约后续使用的时间. - 默认情况下, 在用户更新 package 或者修改代码后, emacs 会对这些有变动的文件进行重新编译.
2.2.2 mac 用户
如果你使用 mac 的话, 因为默认会使用 gcc 引起错误, 需要修改 configure
为:
./configure --with-nativecomp CC='clang'
其他步骤和之前一致.
3 简单配置
在你的配置文件 init.el
中加入一些简单的优化:
;; Silence compiler warnings as they can be pretty disruptive
(setq native-comp-async-report-warnings-errors nil)
;; Set the right directory to store the native comp cache
(add-to-list 'native-comp-eln-load-path (expand-file-name "eln-cache/" user-emacs-directory))
4 后言
至此, 已经完成了 emacs native comp 的安装. 当然, 在日常使用中用户不必关注和处理细节, 因为 emacs 会在后台自动地完成所有的编译和应用, 该过程会静默完成, 除了运行速度快了一些, 其他该怎么用还是怎么用.
个人而言, 对于编程体验特别是 lsp
的代码补全速度提升较大
Code on the fly