WSL2のpipが遅い!解決策と原因

WSL2のpipが遅い!解決策と原因

Windows Subsystem for Linux(WSL2)のUbuntu 20.04でpipコマンドの動作が非常に遅かったので、原因を調べて解決しました。

普通のpipの速度に直せたので、修正方法と原因を記録しておきます。

githubのこのissueを参考にしています。やはり何かあったときはgithubのissueかstack overflowですよね。

結論

環境:Windows10, WSL2, Ubuntu20.04

原因:環境変数DISPLAYとkeyring

修正方法
1. DISPLAY変数の削除
2. Xserverの常時立ち上げ
3. keyringをdisable

pipが遅い!

WSL2のpipの動作が遅すぎました。どのくらい遅いかというと下記です。

pip listに1分36秒もかかってる!

$ time pip list
...
pip list 0.26s user 0.01s system 0% cpu 1:36.38 total

ここではpip listコマンドの時間を計測しましたが、pipに関わる全てのコマンドとてつもなく遅いです。

色々と調べていると冒頭に載せたissueが見つかりました。ほかにも多くの方がこの問題にぶつかっているみたいでした。

解決方法を紹介していきます。

3つの解決方法

pipが遅いのを修正する方法は下記3つです。

どれかひとつ行えば大丈夫です!

  • DISPLAY変数の削除
  • Xserverの常時立ち上げ
  • keyringをdisable

それぞれ、Githubのissue#8385を参考にしています

環境変数DISPLAYを削除

issueでは、pipが遅いのはWSLからWindows側のファイルシステムにアクセスしているからでは?という議論が行われています。

自分はWSL側でGUIを利用するプログラムを作成していたので、環境変数DISPLAYで出力先のXserverをWindows側に設定していました。具体的には、下記を~/.zshenvに追記していました。

export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0

この設定によってなにかがWindows側にアクセスしているのかもしれません。早速、試しに環境変数DISPLAYを消してVcXsrvも終了してpipコマンドを実行してみました。

結果は早くなりました。つまり、環境変数DISPLAYが原因でpipが遅くなっていたということです。

DISPLAY変数を消せばよいことはわかりましたが、GUIアプリの利用時に毎回DISPLAY変数を定義するのはめんどくさいですよね。DISPLAY変数を宣言したままでもpipを正常に動かす方法を探ります。

Xserverの立ち上げ

issueに下記のコメントがあります。

If you want a temporary fix I recommend running an X11 server such as MobaXterm(or some other equivalent). I don’t understand why, but it did fix my slowdown issue for all commands.

https://github.com/pypa/pip/issues/8485#issuecomment-668212786

え、xserver動かせば治るの?早速やってみましょう。

自分はVcXsrvを利用しているので、Windows側でVcXsrvを起動してWSL2上でpip listを実行してみます。(こちらでWSL2でVcXsrvと連携する方法についてめとめています)

# VcXsrvを起動した後のpip list
$ time pip list
...
pip list 0.21s user 0.06s system 91% cpu 0.294 total

90秒以上かかっていたものが、1秒未満まではやくなりました。

つまり、VcXsrvを常に起動していればpipは遅くなるないということです。

VcXsrvは、簡単にWindowsの起動時に起動するように設定できます。ですが、個人的にスタートアップのアプリを増やしたくないので、VcXsrvは必要な時だけ実行したいです。

Xserverを起動せずにpipを早くする方法を試していきます。

keyringをDISABLE化

issueで提案されている方法を行ってみました。

keyringパッケージをインストールして、keyringの設定ファイルを設置します。

設定ファイルではkeyringという認証系の機能をオフにしています。

# keyringのインストール
$ pip3 install -U keyring
# 設定ファイルの設置
$ cat .config/python_keyring/keyringrc.cfg
[backend]
default-keyring=keyring.backends.null.Keyring

これでpip listを実行すると、DISPLAY変数が定義済みでもpipが早くなりました!

keyringを設定ファイルではなくて環境変数で制御する

上記で、keyringの設定ファイルを作成することで解決する方法を紹介しました。

ただ、設定ファイルって増えてくると管理できなくなりますし、現在どんな設定になっているのかがわからなくなりますよね。

自分は環境変数の方が管理しやすいと思っているので、環境変数でkeyringの機能をオフにしてみます。

設定するべき環境変数は、PyPIのkeyringドキュメントに記載されていました(Disabling Keyringの項です)。

どうやら、環境変数PYTHON_KEYRING_BACKENDの指定でできるそうです。

$ echo 'export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring' >> ~/.zshenv
$ source ~/.zshenv

上記を実行して、keyringrc.cfgファイルを削除してpip listを実行したところ、正常に動作することが確認できました。

設定ファイルで管理しても環境変数で管理してもどちらでもよいと思いますが、個人的には環境変数で管理したいですね。

DISPLAY変数も環境変数で管理しているので、keyringの設定も環境変数で行ったほうが管理がしやすいからです。

まとめ

WSL2のpipが遅い原因とその対処方法についてまとめました。WSL2でGUIアプリを開発している人は注意が必要です。

記事内のVcXsrvについては下記の記事で設定方法を紹介しているので、ぜひご覧ください。