ottijp blog

sourcekit-lspの補完が遅いのを速くする

2021-01-10swiftLSPsourcekit-lspsourcekitvimvim-lsp

vimでLSP(Language Server Protocol)を試してます.

swiftを書くことがあるので,sourcekit-lspを使ってswiftのLSPを試したのですが,補完がめちゃくちゃ遅い・・・. そこで,パフォーマンスが改善されているsourcekit-lspの最新版を含むToolchainをインストールして使うことで速くなったので,そのメモです.

環境

  • macOS: 10.15 (Catalina)
  • vim: MacVim 169 (Vim 8.2)
  • Xcode: 12.2
  • Toolchain: swift-5.3.2-Release

vim-lspの導入

mattnさんの記事を参考に,vim-lsp-settingsを使ってvim-lspを導入しました.

cf: Big Sky :: Vim をモダンな IDE に変える LSP の設定

sourcekit-lspは自動でインストールされないので,使っているXcodeに含まれるものを指定するようにしました..vimrc の該当箇所はこんな感じです.

.vimrc(プラグイン追加)
call dein#add('prabirshrestha/asyncomplete.vim')
call dein#add('prabirshrestha/asyncomplete-lsp.vim')
call dein#add('prabirshrestha/vim-lsp')
call dein#add('mattn/vim-lsp-settings')
call dein#add('hrsh7th/vim-vsnip')
call dein#add('hrsh7th/vim-vsnip-integ')
.vimrc(設定)
inoremap <expr> <Tab>   pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <cr>    pumvisible() ? asyncomplete#close_popup() : "\<cr>"
let g:lsp_signature_help_enabled = 1
let g:lsp_diagnostics_enabled = 1
let g:lsp_diagnostics_echo_cursor = 1
let g:lsp_settings = {
\  'sourcekit-lsp': {'cmd': ['xcrun', 'sourcekit-lsp']}
\}

問題

これだけでswiftのlspがvimで使えるようにはなったんですが(vim-lsp-settingsに感謝!),補完が走ると数秒固まってしまい,キー入力も受け付けない感じでした・・・. .vimrc に次のような設定を入れてLSPのログを出しながら動かしてみると,このような感じでした.

.vimrc
let g:asyncomplete_auto_completeopt = 0
set completeopt=menuone,noinsert,noselect,preview

グローバルなシンボルを全部取ってきて遅くなっているような感じでした.( import Foundation がなければ固まることはなかったです.) おそらく以下で議論されている問題だと思います.

cf: Code-completion performance improvement via server-side filtering - Development / SourceKit-LSP - Swift Forums

Xcode12.2に同梱されているsourcekit-lspには,上記イシューで追加されたオプション(-completion-server-side-filtering, -completion-max-results)はありませんでした.

$ xcrun sourcekit-lsp --help
OVERVIEW: Language Server Protocol implementation for Swift and C-based languages

USAGE: sourcekit-lsp [options]

OPTIONS:
  --build-path          Specify build/cache directory
  --configuration, -c   Build with configuration (debug|release) [default: debug]
  --log-level           Set the logging level (debug|info|warning|error) [default: info]
  -Xcc                  Pass flag through to all C compiler invocations
  -Xclangd              Pass options to clangd command-line
  -Xcxx                 Pass flag through to all C++ compiler invocations
  -Xlinker              Pass flag through to all linker invocations
  -Xswiftc              Pass flag through to all Swift compiler invocations
  -index-db-path        Override index-database-path from the build system
  -index-store-path     Override index-store-path from the build system
  --help                Display available options

解決策

Xcode12.2に同梱のsourcekit-lspは少し古そうなことがわかったので, パフォーマンスが改善された最新のsourcekit-lspを含むToolchainをインストールして利用しました.

Toolchainとは,swiftのバージョンに合わせた開発ツールセット (依存バージョンを合わせたコンパイラ等のセット)みたいなものです.

Toolchainのインストール

以下のページからswift 5.3.2のXcode用Toolchainをダウンロードしてインストールしました.

Swift.org - Download Swift

$ ls -l /Library/Developer/Toolchains
total 0
drwxr-xr-x  7 root  wheel  224 May 29  2019 swift-3.1.1-RELEASE.xctoolchain/
drwxr-xr-x  7 root  wheel  224 May 30  2019 swift-4.0-RELEASE.xctoolchain/
drwxr-xr-x  7 root  wheel  224 Mar 23  2020 swift-5.0-RELEASE.xctoolchain/
drwxr-xr-x  7 root  wheel  224 Jan 10 09:54 swift-5.3.2-RELEASE.xctoolchain/
lrwxr-xr-x  1 root  wheel   61 Jan 10 09:54 swift-latest.xctoolchain@ -> /Library/Developer/Toolchains/swift-5.3.2-RELEASE.xctoolchain

Toolchain名の特定

インストールしたToolchainのバンドル名を特定しておきます.

$ grep -A 1 CFBundleIdentifier /Library/Developer/Toolchains/swift-5.3.2-RELEASE.xctoolchain/Info.plist
        <key>CFBundleIdentifier</key>
        <string>org.swift.532202012141a</string>

パフォーマンス改善対応が入っていることの確認

Toolchainの中のsourcekit-lspを実行し,先のパフォーマンス改善対応オプションが含まれることを確認します.

$ xcrun --toolchain "org.swift.532202012141a" sourcekit-lsp --help
OVERVIEW: Language Server Protocol implementation for Swift and C-based languages

USAGE: sourcekit-lsp [options]

OPTIONS:
  --build-path            Specify build/cache directory
  --completion-max-results
                          When server-side filtering is enabled, the maximum number of results to return
  --completion-server-side-filtering
                          Whether to enable server-side filtering in code-completion
  --configuration, -c     Build with configuration (debug|release) [default: debug]
  --log-level             Set the logging level (debug|info|warning|error) [default: info]
  -Xcc                    Pass flag through to all C compiler invocations
  -Xclangd                Pass options to clangd command-line
  -Xcxx                   Pass flag through to all C++ compiler invocations
  -Xlinker                Pass flag through to all linker invocations
  -Xswiftc                Pass flag through to all Swift compiler invocations
  -index-db-path          Override index-database-path from the build system
  -index-store-path       Override index-store-path from the build system
  --help                  Display available options

入ってました.

vim-lsp-settingsの設定変更

ビルドしたsourcekit-lspを使うように,.vimrcを変更します.

.vimrc
let g:lsp_settings = {
\  'sourcekit-lsp': {'cmd': ['xcrun', '--toolchain', 'org.swift.532202012141a', 'sourcekit-lsp']}
\}

補完件数がフィルタリングのデフォルトの動作なので,オプションを付けて実行する必要はありません.

対応後の動作

こんな感じに速くなりました.

ちなみに,sourcekit-lspのビルドではうまくいかなかった

はじめ,手元でsourcekit-lspをビルドしてみたのですが,補完は速くはなったものの,構文エラーなどがsourekit-lspから報告されなくなってしまいました.(LSP通信でdiagnosticsが空になる.) 試しにVSCodeで使ってみるとちゃんとエラーが報告されるので,vim-lspとの相性?かもしれません.

そのあとで,ビルドせずともToolchainの中にあるものをそのまま使えばいいことがわかり,ビルドする方法は止めました. (sourcekit-lspのREADMEにある ii の記述です.)

1. Get SourceKit-LSP with a Swift toolchain
    i. If you have installed Xcode 11.4+ or the corresponding Command Line Tools package, the SourceKit-LSP server is included and can be run with xcrun sourcekit-lsp.
    ii. If you are using a toolchain from Swift.org, the SourceKit-LSP server is included and can be run with xcrun --toolchain swift sourcekit-lsp on macOS, or using the full path to the sourcekit-lsp executable on Linux.
    iii. If your toolchain did not come with SourceKit-LSP, see Development for how to build it from source.

ビルドしたい人は以下を参照してください.

cf: sourcekit-lsp/Development.md at main · apple/sourcekit-lsp

refs


ottijp
Satoshi SAKAO (@ottijp)

都内でアプリケーションエンジニアをしています

...