全部细节见,
原来困扰我的问题是每次打开一个新的js文件时lsp-mode会让我等很长时间,现在这个问题已解决了。打开第一个文件还是要等待,但之后打开新文件速度就很快了。
我读了lsp-mode的代码,性能上还有很大改进空间。比如lsp-register-custom-settings
本质就是一行代码操作一个list,但是特别慢。有兴趣的同学可以进一步优化。
另外lsp-clients实际上加了一打的clients,完全可以手动加入某个client,lsp-register-custom-settings
也许可以不用。这样第一次加载lsp-mode也可以快很多了。
3 个赞
Youmu
2
;; no real time syntax check
(setq lsp-prefer-flymake :none)
这个变量已经是标记为 obsoete 了,现在推荐用 lsp-diagnostic-package
4 个赞
懒猫 说要重建一个lsp-mode
seagle0128 是lsp-mode的参与者
其他人想要参与恐怕也是力不足
总是听说vim的lsp很快 neovim自带lua和tree-sitter
博客代码还需要改进。思路是对的,但是代码有问题。 lsp-auto-config
不能为nil,牵涉到逻辑太多. (setq lsp-client-packages '(lsp-clients))
对我就可以了,因为我只用javascript.手动(require 'lsp-clients)
也没必要的
这其实是一个 trade-off 的问题。我参与了lsp-clients
的讨论。最早其实是没有这个东东的,用户想用什么就装一个 lsp-xxx
,然后自己配置。这时候很多人就出来说使用太复杂了,不如eglot
,blablabla。。。
@yyoncho 就提出了这样一个改进,目标是 out-of-box,对标就是eglot
。目前可以看到lsp-mode
已经内置了大多数的 langserver,比 eglot 要多不少。不需要太多额外的配置就能跑起来,甚至很多 langserver 可以自动下载安装。从用户体验上说确实是降低了门槛,提高了易用性,对新手更友好。当然,对很多高手而言其实差别不大,比如 @redguardtoo 大佬可能并不需要。lsp-clients 中主要是对 langserver 的注册,真正启用是在打开相应的项目文件时。启动时加载肯定有一定影响,但根据我的使用体验看应该不大。当然,我并没有详细测试数据,如果影响真的很大可能需要提供一些信息、报个 issue 我们一起来看。
总体上讲,个人认为这还是利大于弊的。目前我的配置中完全采用了 lsp 方案,体验也很接近 VSCode。这也是 LSP 存在的价值和意义。后续 lsp-mode 还会在性能和功能上进行加强和优化。比如 @yyoncho 提到会有自己的 posframe 实现来替代目前的展示方案,还有 JSON 解析优化等等。另外,还有懒猫等提出的想用 rust 写一个 lsp client 然后集成到 emacs,这也是很好的想法。
zsxh
6
lsp-clients 我觉得是没有做到按需加载吧,像org babel那样,第一次加载这么多无关的lang包,启动就很慢了。
(defcustom lsp-client-packages
'(ccls cquery lsp-clients lsp-clojure lsp-csharp lsp-css lsp-dart lsp-dls lsp-elm
lsp-erlang lsp-eslint lsp-fsharp lsp-gdscript lsp-go lsp-haskell lsp-haxe
lsp-intelephense lsp-java lsp-json lsp-metals lsp-pwsh lsp-pyls
lsp-python-ms lsp-rust lsp-solargraph lsp-terraform lsp-verilog lsp-vetur
lsp-vhdl lsp-xml lsp-yaml)
"List of the clients to be automatically required."
:group 'lsp-mode
:type '(repeat symbol))
lsp-client-packages
可以用默认的设置,定制这个变量只是略加速项目中第一个文件的载入速度。后面打开项目其他文件速度都很快了,如使用最新版lsp-mode的话。
这并不是加载所有功能,只是注册 clients,真正打开文件才会启动相应的server。而且,提供 lsp-client-packages
就给用户定制想要的 clients。
我明白只是注册clients,本质就是一行代码对一个list进行合并和uniq操作。但就是这一行简单的代码特别慢。原先是每次打开一个新文件Emacs都要卡几秒。在最新版接受了我的patch后好很多了,只是打开第一个文件时要卡几秒。
能做个profiling吗?看看究竟是哪个调用耗时。打开一个文件卡几秒太夸张了,这个应该解决。我的环境上没有这个问题
ChenLi
12
1 个赞
没有意识到你说的是这个 PR。已经 merge 了,thanks!
posframe展示是因为在一个issue里我录了个gif coc使用floatwindow的效果,问了下能不能在emacs用posframe,结果等了很久还没…
目前 lsp-ui 中已经支持 child frame,但还不是很统一。这方面还在讨论中,不过优先级确实没那么高。
另外一个可改善lsp性能的技巧。和emacs无关,见 Rename runs over node_modules folder? · Issue #394 · sourcegraph/javascript-typescript-langserver · GitHub 这个langserver假设用户用的是vscode,所以会去搜索jsconfig.json,读入其设置。可以用来设置可以跳过扫描的文件和目录
lsp-mode的lsp-file-watch-ignored
不会影响langserver扫描,只是影响lsp-mode自己的变量。
我还没验证过,各位验证过的可以交流一下体验
1 个赞
又发现了一个优化lsp-mode的技巧,如果用js2-mode
打开js文件的话,可以用其自带的imenu,因为js2-mode
自带一个js parser,响应很快,不用等lsp的比较慢的parser返回imenu结果了。
(if (derived-mode-p 'js2-mode) (setq-local lsp-enable-imenu nil))
(lsp-deferred)
2 个赞
js2-mode 自带的parser不是增量分析的
tree-sitter可以增量分析
如果只是imenu的话 ctags不行吗?
ctags只能用正则表达式,解析不出上下文(如函数所在的class,promise). 另外imenu只解析当前buffer,要分析的数据很少,所以对parser的效率要求不高。我不用lsp的imenu功能是因为第一次扫描代码的时间太长,但我习惯一开始就用imenu看刚打开的代码,这样会卡很久。