用多线程提高emacs启动效率的可能性

emacs 26现在支持一些基本的多线程,多线程是不是能提高一些emacs启动的效率?

比如饱受诟病的spaceline,虽然2.0版有不小提升,但是还是不快,而且不太适合autoload, 毕竟一般这个是希望随emacs启动的。

在emacs 25我的做法是设一个定时器,让spaline在加载结束后0.3秒加载,这样主要的emacs组件加载完直接就可以开始工作,spaceline迟一点加载没有影响。当然这只是理想情况,实际上spaceline加载之前操作也不会响应……只是感觉上快了一点

emacs 26有了多线程,我就把定时器换成了线程。这样spaceline在单独的线程里加载。但是这还是理论。实际感觉没啥区别 :sweat_smile:


我现在有两个想法,

一是把一些加载较慢,不是立即需要但是希望随emacs启动的包放到单独的进程里加载。比如spaceline,lsp-mode。

二是把整个启动过程分割成互相不依赖的任务然后交给不同进程来完成。

这样会不会加快启动速度?可行性如何?我配置里弄的多线程好像没啥用……


P.S. 如果用我这种方法加载spaceline,spaceline加载之前的buffer的modeline是不会自动更新的。所以homepage的modeline是原本的样子,但是打开新的buffer就都是spaceline的样式了。或者你也可以写一个函数关了homepage再加载回去

加载有依赖关系要处理。

我没理解,什么加载有依赖关系要处理?

这么说吧,多线程只能返回一个结果,不能返回状态。你在子线程加载一个包,返回以后主线程是不会加载的。最多只是共享一些变量。

1 个赞

这么说子线程不能更改emacs的状态,只能用来做计算?

不能,除了和外部程序的交互以外,线程是“无副作用”的。

喔喔,这么说我就懂了

我还是给你点信心吧……

Emacs 一直以来没有并行和 Emacs Lisp 的动态作用域有关。然后新加的多线程用的是黑科技,和我上面说的“常见的线程”行为不一样,内存是默认共享的。也就是说在线程加载的函数和变量会改变 emacs。

具体的规范还没定下来,可能下一个版本这个特性就被改掉了。

而且就算能这样,也不会是直接开个线程执行个 require spaceline就能完事的,涉及到 local variable 的部分还是要在主线程完成。也就是说,你需要改写 spaceline 的结构以适应异步加载。

这样的话我还是改回我的定时器吧……有什么需要大量计算的函数在考虑多线程。

悄悄问一句,我发这么多帖子没问题吧😬

又不是水贴。

嗯……我提问的时候一般都是纠结了一个多小时而且Google上花式搜索无果以后。emacs用的人还是少,一般情况下文档就能解决问题,但是文档解决不了的时候很难找到“别人问过而且被解决”的问题

为什么不试试用异步,比如https://github.com/kiwanami/emacs-deferred这种
之前加载elfeed的feeds文件,就用的这个

1 个赞

异步和我说的常見线程一樣,不能做到共用內存空間。feed 这種数据可以通過 closure 传递,因為 XML 转 Lisp Object 的時間可以用 async 节省,主进程只要花 eval 一个 Lisp Object 的時間。但用 emacs async 做函數定义传递相當于复制一份代碼,主进程再 eval 一次,等于沒省時間。

用什么方式,自己多实验下最好,理论的东西,别人和自己理解的,不一定就是正确的