遠くて遅いSMBサーバ上のファイルをEmacs上で編集しているとすごくラグった話

Windows上のEmacsで共有フォルダのファイルを直接編集したり、WSLで共有フォルダを /mnt 下にmountしている状況でその先をEmacsで編集したりすると容赦のない遅さが襲ってきて死ぬ。

TRAMPみたいに (file-remote-p (buffer-file-name))non-nil を返す状況だと、いろいろなパッケージがそれなりによきにはからってくれるが、WindowsのSMB共有についてはよきにはからってくれない。WSL上でmountしているならローカルと区別する汎用的な方法もない。

軽減策 : オートセーブやバックアップをリモート側に作るのを止める

ファイルアクセスが遅いサーバ上にオートセーブやバックアップファイルを作ると、 編集中に保存が走ってもちろんクソ遅い。特にオートセーブがよくない。 たぶん高速なストレージの上にある user-emacs-directory の下に作るとよい。

  (add-to-list 'auto-save-file-name-transforms
  	     `("^\\(//\\|/mnt/\\).*" ,(expand-file-name "auto-saves/" user-emacs-directory) t))
  (add-to-list 'backup-directory-alist
  	     `("^\\(//\\|/mnt/\\).*" . ,(expand-file-name "backups/" user-emacs-directory)))

temporary-file-directory に作るのもよいかもしれない。古いオートセーブやバックアップが残ってても邪魔なだけな事が多いし、履歴が重要ならそもそもgitの管理対象にすべきだろうし。

temporary-file-directory に作るならば、no-litteringを入れて、 (no-littering-theme-backups) とするのもよい。その他の整理整頓の機能もちょっと興味深いし。

軽減策 : flyspellを止める

うちの環境では、今はjit-spellを使っているため特に遅くはなってないのだが、昔 flyspell を使ってた頃、SMB共有しているファイルではすごく遅くなった記憶がある。ただ当時はWindows上のEmacsがメインだったのせ、そのせいかもしれない。

ちなみに、 jit-spell よりjinxの方がさらに速いはずだが、初期の頃に試した際に日本語にもスペルチェックがかかってうっとうしかったので使うのを止めたのだった。で、ふとissueを眺めると解決方法がありそう

軽減策 : doom-modelineの設定を変える

今回この記事を書く原因となった現象は、この設定で概ね解消した。 doom-modelineを有効にしているとクソ重くて、無効にすると早くなるならこの対策が有効だろう。

doom-modellineはデフォルトでバッファの指すファイルの有無をmodelineに表示するのだが、 結果として file-exist-p をかなりの頻度で呼ぶことになるので、遠くてファイルアクセスの遅いサーバであればそこでラグる。カーソル移動しているだけでラグるのでかなり腹が立つ。

対策としてはそこだけ止めるといい。 buffer-state-icon は出なくなるが、アイコン更新タイミングで遅くならなくなる。

(setq doom-modeline-buffer-state-icon nil)

逃避策 : あきらめよう

なお、ここまでやってもやっぱりたまに遅くなる。気付いたら追記するかもしれない。

回避策: smbclientを使う

冒頭に書いたとおり、TRAMPを使ってファイルアクセスをしていると (file-remote-p (buffer-file-name))non-nil を返すようになり、いろいろなパッケージがそれなりによきにはからうので遅くなりづらくなる。

で、TRAMPで smbclient を使って /smb:user%domain@host:/path/to/file みたいな事ができるので、WSLならいっそそっちを使ってみてもいいかもしれない。ただ、試してみた限りだと smbclient に加えてwinexeが必要なようだ。 winexe を使うということはアクセス先が本当のWindowsじゃないとたぶん何かまずい。ただ、winexeがないと文句を言いつつも編集自体はできるので使えないことはない。

おわり