聊一聊 Emacs 的字节编译

发布于 2024-11-15 05:23:00 字数 2323 浏览 2 评论 0

某些 Lisp 有一项独门绝迹,那就是可以在任意时刻将函数编译成字节码/本地代码(具体编译成什么有赖于方言和具体实现)。

对于那些能够编译的 Lisp 函数(例如 CLISP ),一般都支持两种形式的代码:一种是缓慢的,未优化未编译过的代码,一种是快速,高效编译过的代码。

但是你不要以为未编译的代码就一无是处了,除了无需花费时间在编译上之外,它也有其他的有点。

对于 Emacs Lisp 来说,未编译过的函数就是一个 lambda 表达式。只不过它存在于一个 symbol 中,就相当与给它取了个名字。

而编译后的 form 则是一个(特殊的) 数组,编译后的字节码以字符串的形式存在这个数组的第二个元素中。其他的元素还包括常量,docstring 等。

Elisp 提供了 byte-compile 函数来编译其他函数。该函数能接受一个 lambda 函数或者一个 symbol,不过如果参数是 symbol 的话,编译后的函数回覆盖该 symbol 的原 S 表达式。

(byte-compile (lambda (x) (* 2 x)))
=> #[(x) "^H\301_\207" [x 2] 2]

编译器不仅仅是将函数是转换成字节码并展开宏,还会进行一些优化,比如删除无用代码,预先执行 safe constant forms, 以及内联函数,从而极大地提高执行效率。
(通过我的 measure-time macro 来测算的)。

(defun fib (n)
  "Fibonacci sequence."
  (if (<= n 2) 1
    (+ (fib (- n 1)) (fib (- n 2)))))

(measure-time
  (fib 30))
=> 1.0508708953857422

(byte-compile 'fib)

(measure-time
  (fib 30))
=> 0.4302399158477783

大多数 Emacs 自带的函数都预先编译过了。不过也有部分自带的函数没有被编译,所以我想,不如我来花点时间把它们编译一下算了。

Common Lisp 是有提供一个判断函数(compiled-function-p) 来测试另一个函数是否有编译过的。
但不知为何,Elisp 中没有预定义这样一个函数,我只能自己写一个了:

(defun byte-compiled-p (func)
  "Return t if function is byte compiled."
  (cond
    ((symbolp   func) (byte-compiled-p (symbol-function func)))
    ((functionp func) (not (sequencep func)))
    (t nil)))

我一开始的想法是便利所有 interned symbol,若通过上面的测试函数发现该 symbol 的 function slot 中是未编译的函数,那么就调用 byte-compile 来编译它。
不过后来我发现, byte-compile 足够聪明,它会自动忽略那些没有函数以及那些函数以及编译过的 symbol。

那么,下一个问题就是,我们如何遍历每个 interned symbol? 函数 mapatoms 可以做到这一点. 给它一个函数作为参数,它就会将该函数应用到每个 interned symbol 上。
这样一来,问题就简单了. (译者注:我运行了这个语句之后,Evil 彻底用不了了,不得不重启 Emacs...)

(mapatoms 'byte-compile)

这就搞定了!整个过程不过几秒钟,不过会产生大量的警告. 目前我还未找到屏蔽这些警告方法,所以你最好不要自动运行这个语句,否则你会发现时不时地会弹出一个 window。

而且,我也不确定这么做会不会损坏你的 Emacs session,毕竟不是所有的函数写的时候都有好好的考虑编译后还能不能用,尤其是那些用到宏的函数。

另外,我很怀疑这样能否带来性能上的明显提升,就像我前面所得,大多数的函数预先编译过了,而这部分函数才是使用最频繁的函数。

把所有函数都编译一次,可能只是给你你心理上安慰一点而已。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

甜心小果奶

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

linfzu01

文章 0 评论 0

可遇━不可求

文章 0 评论 0

枕梦

文章 0 评论 0

qq_3LFa8Q

文章 0 评论 0

JP

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文