🔄

山本悠滋改めすがすがC言語の「1人以上で勉強会」 第3回 UnisonでWSL2を快適にするチャレンジ

2023/11/18に公開

山本悠滋の「1人以上で勉強会」

この記事について

山本悠滋の「1人以上で勉強会」という私が運営しているオンライン勉強会みたいなもので、当日喋りながら書いたメモです。勉強会の宣伝のためにZennで公開することにしました。

配信で使われたメモ

山本悠滋改めすがすがC言語の「1人以上で勉強会」

  • 第3回:

    • UnisonでWSL2を快適にするデモ
  • この勉強会について

    • (毎回同じようなことを言っているので省略)

業務連絡

  • 今回以降「すがすがC言語の『1人以上で勉強会』」に改めます
    • チャンネル名: 「すがすがC言語」
    • Twitter: 「YAMAMOTO Yuji (HN: すがすがC言語)」
    • => 「『山本悠滋』は誰?」と思われかねないので...

Unisonとは

  • リモートやローカルにおけるファイルや
    ディレクトリーの同期を行うツール
  • OCaml製
  • Windows・Mac・Linuxで動作
    • OCamlさえ動けば他のUnixでも?
  • rsyncと同様のアルゴリズムを用いていて、無駄なく同期
  • リモートと同期する際はsshを介して行う
    • これもrsyncと同様
  • 双方向に同期して、衝突の検出もできる
  • ディレクトリーへの変更を再帰的に監視して自動で同期
    • 自家版Dropboxみたいなことも簡単に
  • CLIでもGUIでも使える
    • 今回はCLIだけ紹介します(普段GUI版を使っていないので)

WSL2の悩み

例: 手元のプロジェクトでtsc

$ cd /mnt/c/t/
$ git clone https://github.com/igrep/custard
$ cd custard/
$ npm i
$ time npx tsc

real    0m4.497s
user    0m3.282s
sys     0m1.001

# v.s.

$ cd
$ git clone https://github.com/igrep/custard
$ cd custard/
$ npm i
$ time npx tsc

real    0m1.682s
user    0m3.220s
sys     0m0.231s

資料作りの際実験したときよりは差が小さいが、やはり遅い

ℹ️ 手元の環境

  • CPU: AMD Ryzen 5 5500
  • RAM: 32GB
  • ⚠️ベンチマークを取るときはなるべく他の処理を切るようにしましょう!
    • 配信中はOBSを思いっきり動かしながらやりますが...
  • ホスト: Windows 11 Home 22H2 22621.2428
    • TODO: OSのバージョンを現在のものに改める
    • WSL: 2.0.9.0
  • ゲスト: Ubuntu 22.04.3 5.15.133.1-microsoft-standard-WSL2

Unisonによる対策

  • 基本的にLinux側のFS /home 以下で作業
  • Unisonで変更を非同期に伝播させる
Linux -- Unisonで同期 --> Windows
  ^
  |
  |
作業✍

メリット

  • 非同期に変更を反映させるので、
    体感上FSの遅さの影響を受けにくい
  • 同期するファイルの除外設定ができるので、
    その分高速に同期できる

デメリット

  • 同期するファイルはコピーする分容量を2倍食う
  • Unisonの同期機能の設定がちょっと難しい
    • デモしながら解説します

デモ: WSL2で構築したLinuxと同期する

DebianやUbuntu公式のパッケージは執筆時点で罠

$ sudo apt install unison
...
$ unison -version
unison version 2.51.5 (ocaml 4.13.1)

リアルタイム同期に必要な、unison-fsmonitorがない!

$ which unison-fsmonitor
unison-fsmonitor: command not found

試しに使ってみてもうまく行かない

$ sudo apt install openssh-server
$ mkdir ~/test/
$ unison C:\test ssh://igrep@localhost/test -repeat watch
igrep@localhost's password:
... 略 ...
Fatal error: Server: No file monitoring helper program found

file monitoring helper programとはunison-fsmonitorのこと

パッケージマネージャーからインストールしたものは削除

sudo apt remove unison

代わりにGitHub Releaseからインストール

# 作業用のディレクトリーの作成推奨
$ mkdir install-unison && cd install-unison

# 配信時点の最新版は v2.53.3
# Linux向けがいくつかあるけど多分どれでも良い
$ wget https://github.com/bcpierce00/unison/releases/download/v2.53.3/unison-2.53.3-ubuntu-x86_64.tar.gz
$ tar xf unison-2.53.3-ubuntu-x86_64.tar.gz
$ sudo cp bin/unison* /usr/local/bin/

軽い動作確認

# ハイフン 1つなのに注意!
$ unison -version
unison version 2.53.3 (ocaml 4.14.1)

VM起動時に自動で起動

  • 👇こんなbatファイルを作ってこちらから起動するようにしておくと、
    VM起動と共に同期を始められるので便利
  • 最近のUnisonは自動でリトライしてくれるので、
    VM起動前に unison -repeat watch すれば、
    VMが起動する前にunisonがVMにアクセスしても問題なし
rem Unisonを別ウィンドウで起動
rem   `-repeat watch` で自動で同期
start unison -repeat watch C:\unison-test ssh://igrep@localhost/unison-test
wsl

.prf ファイルを書いてみよう

root = C:\unison-test
root = ssh://igrep@localhost/unison-test

# コメント行は「#」で始める

path = prj/wasm-reference-types-examples
path = prj/multipost
path = prj/custard

ignore = Name {dist}
ignore = Name {tmp}
ignore = Name {node_modules}
ignore = Name {*.so}

# 他の .prf ファイルで共通化することも
include common
  • 同期の設定をまとめたファイル
    • 多くの設定項目はコマンドラインオプションでも指定できる
    • コマンドラインによる指定が優先される
  • ~/.unison ディレクトリーに .prf という拡張子で置く
    • 残念ながら ~/.unison 以外に置くことができない模様

その他の機能

WSL2ならopenssh-serverなしで同期できる?

できた:

バックアップの設定

  • 上書き・削除するファイルをバックアップする機能

.prf ファイルの例:

backuplocation = local
backupprefix = .unison/$VERSION.
backupsuffix =

注意

最新のドキュメントが、一旦保存しないと読めない

  • https://github.com/bcpierce00/unison/wiki
    • こちらにあるHTMLファイルを保存しないとHTMLのドキュメントが見えない
    • 追記: 正確には、PDFでは保存しなくても読めます

初回だと次のような警告が出ることが

$ unison C:\test ssh://igrep@localhost/test -repeat watch
Unison 2.52.0 (ocaml 4.11.2): Contacting server...
igrep@localhost's password:
Connected [//D-2023-03//home/igrep/test -> //D-2023-03/C:/test]

Looking for changes
Warning: No archive files were found for these roots, whose canonical names are:
        C:/test
        //D-2023-03//home/igrep/test
This can happen either
because this is the first time you have synchronized these roots,
or because you have upgraded Unison to a new version with a different
archive format.

Update detection may take a while on this run if the replicas are
large.

Unison will assume that the 'last synchronized state' of both replicas
was completely empty.  This means that any files that are different
will be reported as conflicts, and any files that exist only on one
replica will be judged as new and propagated to the other replica.
If the two replicas are identical, then no changes will be reported.

If you see this message repeatedly, it may be because one of your machines
is getting its address from DHCP, which is causing its host name to change
between synchronizations.  See the documentation for the UNISONLOCALHOSTNAME
environment variable for advice on how to correct this.

Donations to the Unison project are gratefully accepted:
http://www.cis.upenn.edu/~bcpierce/unison

Press return to continue.[<spc>]

  Waiting for changes from server
Reconciling changes
Nothing to do: replicas have been changed only in identical ways since last sync.
  • Unisonは、単に同期するだけではなくて、
    同期したディレクトリーにおける、同期した時点の状態を
    ~/.unison に記録している。
    もう一度同期するときはその記録した状態と、
    実際のディレクトリーの状態を比較することで、
    正確な変更の反映ができる。

  • この警告は、~/.unisonに情報が記録されてないので、
    正確な同期ができるか分からない、というもの

  • 実際にこの警告が出た後、メッセージの通りスペースを押して
    同期すると、大量のコンフリクトを報告されることが。

  • 古いバージョンのUnisonに注意

    • 同期するマシン間で
      Unison自身のバージョンだけでなく、
      コンパイルしたOCamlのバージョンまで揃えないといけない!
    • 最新版であればまず問題にならない

あるかも知れない質問

\\wsl.localhost\ と同期してみたら?

試してみましょう:

# Windows 側で実行
$ unison -repeat watch  C:\unison-test \\wsl.localhost\Ubuntu\home\igrep\unison-test
  • Windows側での変更しか検出されない!
  • -repeatに数字を指定すればpollingするようになるのでいけるかも
    • 今回は割愛

そもそもなんでWindowsのFSにコードを置く?

  • 🤔 Linux上で編集するようなコードであれば同期しなくていい?
  • 人それぞれ事情はあると思いますが...
    • Windows上で使い慣れた編集ツールがある、とか?
    • バックアップのとりやすさ
      • Linux版Dropboxを入れる必要がない
      • Linux版Dropboxはinotifyの制約を受ける
        • 設定を変えないと同期する件数を増やせない
          • Unisonも同じ制約を受けるが、設定の
            ignoreなどを使えば影響を受けにくい
      • GUIを使えるようにしないと設定しにくい
      • 他のストレージサービスだと
        そもそもLinux版の公式クライアントがない場合が
      • いつもgit pushしてるから気にしない!
        という人は気にしなくてよし!

番外編

  • macと手元のLinux仮想マシンを同期する場合
    • https://github.com/autozimu/unison-fsmonitor
    • mac版unisonにはunison-fsmonitorがないので
      こちら⬆️を使おう。
    • 追記: 両方homebrewにあるのでインストールも簡単
      • brew install unison
      • brew install autozimu/homebrew-formulas/unison-fsmonitor
  • WSL1で今回紹介した方法が使えるかは不明

まとめ

  • WSL2を使っていて、
  • OSをまたいだファイルの編集が遅いと感じているときは、
  • 代わりにUnisonを使って都度同期するのがお勧め

次回予定

  • ソフトウェアの速度は「遅いか・速いか」ではなく
    「間に合うか・間に合わないか」
GitHubで編集を提案

Discussion