Emacs 现在的线程没有 IPC,只有 GIL。
我把 GC 关掉,再把 thread.c 的 acquire_global_lock 去掉,就可以在并行的线程中运行简单的代码了。让 emacs 有同时运行多线程的功能并不复杂,而只是需要花费很多时间来判断哪些线程能安全的运行什么代码罢了。
比如说,不可能让多个线程同时运行 redisplay,所以在非主要线程运行 redisplay_internal 时可以 pthread_kill 主要线程。而主要线程收到这个 signal 时 redisplay 就行了。
MSW 和 haiku port 的 message loop 和绘画都是在非主要线程中运行,需要 redisplay 时就通过 signal 来提示。
从操作系统底层实现看,线程本质就是进程模型,只是多个线程之间共享一定的内存访问空间,方便线程读取大数据,避免数据在进程之间进行传递浪费时间。
我认为的多线程模型是,不管线程自己要计算10秒、10分还是10年,线程之间都要具备 独立 运行的能力,这样才能彻底解决图形卡顿的根源,而不是Emacs启动10个线程,Emacs自己来回在线程之间切换,如果一个线程没有计算完,Emacs怎么切换? 某个线程太耗时不把事件循环让出来,Emacs能怎么办?还不是卡住,这也是很多 libevent 和图形库结合会产生的问题,协程自己的事件循环要和图形库的事件循环进行协调,那为啥不让操作系统来通过线程模型来自动切换计算切片呢,即使线程没有计算完,操作系统会保证线程暂停和继续的状态一致性,不管线程内部计算量多大,都可以快速共享CPU时间。
有线程就是线程,而独立运行线程只是其中的一种。但是我在上面已经回答了您对这里的疑问。
我这个周末如果有空会折腾一下,不过工作上的事情比较多,所以不能保证会按时做到。
对,对于绘制可以在非主线程运行, redisplay 只用更新计算后的 surface 就可以了。
但是对于Linux X11 Window这种是不可能的,图形代码必须在主线程运行。
不管怎么样,关键是要分离图形和非图形的代码边界,现在Emacs还缺乏‘多线程’最佳实践模型,还只是在前进的过程中。
对,友好的图形多线程模型需要满足:
- 独立线程运行,线程之间互不影响,想算多久算多久
- 线程之间用队列通讯、全局锁会让实际的图形编程太麻烦了,到处来回锁,只要能够隔离非图形代码就行了
- 清晰的图形API边界,告诉用户在X11这种平台不要在子线程调用图形API
谢谢,不过这些我都清楚啊,不需要提醒(
哈哈,还是需要说说滴,因为我们许多人不知道啊,如果你们大牛讨论惜字如金,我们其他人怎么学习进步呢。
两个大佬巅峰对决
我是题主。两位老哥讨论如此深入,其他人也多发言啊! 特别是多分享一下使用体验。
我很好奇,emacs-ng 把这些先进且流行的技术组合到一起,到底是否真的能达到他们提出的目标。
PS: emacs-ng 项目在 FAQ 里面说,并不是想用 JS 取代 elisp,他们热爱 elisp,他们的 slogan 是 A new approach to emacs 。
它官方也没有基于这套新技术方案开发几个包出来展示下怎么用以及能干点啥,重写几个包来秀下也能更有点吸引力不是
多谢这位同志
确实。真没有找到例子。
emacs目前实现的"多线程"应该叫"协程", 没法真正并发计算, 另外, 每个线程都可以操作gui, 导致混乱, 难以实用, 感觉设计得很失败.
这方面真应该参考浏览器, 毕竟浏览器的工作模型和emacs非常类似, 都是涉及高密度用户操作和界面更新. web worker的设计就相当不错.
最近好像看到一种思路, 就是fork一个emacs子进程, 实现类似web worker的模型, 把worker放在子进程运行, 运行结果返回回来, 关闭子进程. 这样好像也可以, 就是太耗费进程. async包好像也是这么工作的.
我是比较希望emacs能支持类似沙盒的东西, 在emacs进程里能创建多个沙盒, 每个沙盒相当于一个线程, 沙盒里面可以运行elisp, 但是不能访问emacs的全局变量(包括界面等等). 然后把worker放在沙盒里运行. 主线程的elisp可以管理和控制沙盒, 并跟沙盒里的worker交换数据.
我是比较希望emacs能支持类似沙盒的东西, 在emacs进程里能创建多个沙盒, 每个沙盒相当于一个线程, 沙盒里面可以运行elisp, 但是不能访问emacs的全局变量(包括界面等等). 然后把worker放在沙盒里运行. 主线程的elisp可以管理和控制沙盒, 并跟沙盒里的worker交换数据.
这个方法对现有的emacs生态应该是没有破坏, 就是不知道emacs内部好不好实现.
如果有沙盒,那运行js应该更好吧。那样的话,还得有一个对其他语言的接口,简单的rpc应该就行了。neovim就是这么做的。