- Pythonパッケージマネージャー uv は、pipより 10倍以上速いインストール速度 を示しており、これは単にRustで書かれているからではなく、設計上の選択 によるもの
- 速度を実現した中核は 静的メタデータ標準(PEP 518, 517, 621, 658) で、コードを実行せずに依存関係を把握できるようにしたこと
- uvはpipが維持している レガシー機能(.egg、pip.conf、システムPythonへのインストールなど) を大胆に削り、不要なコードパスを排除 した
- Rustが寄与した部分は ゼロコピー逆シリアライズ、ロックフリー並行性、単一バイナリ構成 などで、全体の高速化のうち一部にすぎない
- 全体としてuvの事例は、標準化されたメタデータと不要な互換性の除去こそが性能革新の核心 であることを示している
uvの速度を可能にした標準
- pipが遅いのは実装の問題ではなく、過去の setup.pyベースの構造 により、依存関係を知るためにコードを実行しなければならなかったため
- setup.pyの実行にはビルド依存関係のインストールが必要で、これは 「鶏と卵の問題」 を引き起こした
- インストール過程で 任意コードの実行と繰り返される失敗 が発生し、インストール速度を低下させた
- PEP 518(2016) は
pyproject.toml を導入し、コード実行なしでビルド依存関係を宣言できるようにした
- PEP 517(2017) はビルドフロントエンドとバックエンドを分離し、pipがsetuptoolsの内部を理解する必要をなくした
- PEP 621(2020) は
[project] テーブルを標準化し、TOMLを解析するだけで依存関係を確認できるようにした
- PEP 658(2022) はパッケージメタデータを Simple Repository API に直接含め、wheelをダウンロードせずに依存関係情報を取得できるようにした
- PyPIは2023年5月にPEP 658を適用し、uvは2024年2月に公開され、新しい標準インフラを完全活用した最初のツール として登場した
- RustのCargoやnpmのように、Pythonエコシステムも今や 静的メタデータベースのパッケージング へ移行している
uvが削除した機能
- uvの速さは 不要な機能の削減 から生まれている
- .eggのサポートなし: pipは今も処理するが、uvは完全に除外
- pip.confを無視: 設定ファイル、環境変数、継承ロジックをすべて省略
- バイトコードコンパイルを無効化:
.py を .pyc に変換せず、インストール時間を短縮
- 仮想環境を必須化: システムPythonへ直接インストールしないため、権限チェックや安全性コードを削除
- 厳格な仕様準拠: 不正なパッケージを拒否し、例外処理ロジックを縮小
- requires-pythonの上限制約を無視:
python<4.0 のような防御的制約を無視し、依存関係解決(バックトラッキング) を削減
- 最初のインデックスを優先: 複数のインデックスのうち最初でパッケージを見つけたら即座に停止し、依存関係混同攻撃の防止とネットワークリクエスト削減 を実現
- これらはすべて、pipが通る必要のあるコードパスをuvが削除した例である
Rustなしでも可能な最適化
- uvの高速化のかなりの部分は 言語に依存しない設計最適化 に由来する
- HTTP Rangeリクエスト でwheelファイルのセントラルディレクトリだけを部分ダウンロードし、全体のダウンロードを回避
- 並列ダウンロード により複数パッケージを同時に取得
- グローバルキャッシュとハードリンク を使い、同一パッケージを複数の仮想環境にインストールしても 追加のディスク容量を消費しない
- Python非依存の解析: TOMLとwheelメタデータを直接解析し、setup.pyしかない場合にのみPythonを実行
- PubGrub依存関係解決アルゴリズム を採用し、pipのバックトラッキング方式より高速で、エラー説明も明確
Rustが実際に寄与した部分
- Rustは特定の 低レベル最適化 において重要な役割を果たしている
- rkyvベースのゼロコピー逆シリアライズ により、キャッシュデータをコピーせず直接利用
- ロックフリーの並行データ構造 により、安全な並列アクセスを実装
- インタプリタ初期化が不要: uvは単一の静的バイナリであり、pipのPythonプロセス起動コストを排除
- バージョン情報をu64整数に圧縮表現 し、比較やハッシュ計算を高速化
- これらの要素は性能を高めるが、全体の高速化の主因ではない
重要な教訓
- uvの速さは Rustだからではなく、やらないことが多いから 生まれている
- PEP 518・517・621・658の標準化が 高速なパッケージ管理の基盤 を整え、uvは レガシー排除と現代的な前提 によってそれを実現した
- pipも並列ダウンロード、グローバルキャッシュ、メタデータベースの解析を実装できるが、15年にわたる下位互換性の維持 が障害になっている
- 結果としてpipは常に遅くならざるを得ず、新しい前提から出発したツールだけが根本的な高速化を実現できる
- 他のパッケージマネージャーへの教訓は、静的メタデータ・コード実行なしの依存関係探索・事前解決可能な構造 が不可欠だという点
- Cargoとnpmはすでにこの方式を採用しており、依存関係確認のためにコードを実行しなければならないエコシステムは本質的に遅い
1件のコメント
Hacker Newsの反応
この記事は uvの性能 を多角的にうまく説明していると思う
Rustで書かれている点も助けにはなっているが、この10年間でPythonエコシステムが
setup.py依存から脱却するよう進めてきた 標準化の取り組み のほうが、はるかに大きな役割を果たしたRustも同じように、コミュニティの力量を引き上げる理由で選ぶ価値がある
既存の試行錯誤をたどり直しながらよりよい設計ができ、そこにRust自体の利点も加わって、いわば「ワンツーパンチ」になっている
「uvはRustだから速いのではなく、やっていないこと が多いから速い」という主張には共感する
ただし、ベンチマークなしで速度要因を断定するのは早いとも思う
PEP 518, 517, 621, 658 の影響は大きいが、互換性の削除 がどれだけ貢献したのかは疑問だ
また、言語選択が最適化にどんな影響を与えたのかも扱われていない
CargoのTOMLパーサーがPythonよりはるかに速い点も興味深い
実際にはTOMLはビルド時にしか読まれないので比重は大きくないが、wheelの普及 が速度向上に貢献した
関連参考記事: setup.py deprecated, wheels are faster
rkyvを使った zero-copy deserialization はRust固有の技術ではないC/C++ のような低水準言語でも可能だ
「インタプリタの起動がない」というのも同じ文脈だ
記事の内容は良いが、LLMが整えた文体 があまりに人工的に感じられる
いつかはLLMによって壊れた文章を、再び人間らしく復元する時代が来るのかもしれない
サプライチェーンセキュリティの専門家に見えるが、その記事もLLM特有の 曖昧な文体 に変質していた印象だった
固定化したプロンプトがどの文章も似たものにしてしまい、インターネット全体が同じ声で話しているように聞こえるのが残念だ
uvの速さに熱狂する空気が理解できない
たいていのPythonユーザーは、パッケージのインストール速度を 悩みの上位10項目 にすら入れていない気がする
自分も毎日Pythonを使っているが、体感はそこまで大きくない
poetryで依存関係の更新に5〜30分かかっていた失敗したらまた30分待たなければならず、uvは本当に 快適な体験 だった
pip installがデプロイ時間の大きな割合を占めていたキャッシュで速度を上げようと苦労した時間が多かった
poetry installは2分、uv syncは数秒で終わるCIごとに2分節約できるので、積み重ね効果が大きい
uvx sometoolを実行するときも、仮想環境の作成と依存関係のインストール が数秒で終わるので、作業フローが完全に変わるもうuvのないプロジェクトには戻りにくい
uvの一部の 速度最適化手法 はpipにも移植できそうに見える
例: 並列ダウンロード、
.pycの遅延生成、eggの無視、バージョンチェックなどただ、uvはvenvの扱いがあまりにうまいので、わざわざpipをいじる必要はなさそうだ
結局のところ「Rustのおかげだけではない」という点では、pipにもまだ速くなる余地はある
速い言語を選ぶプログラマは、すでに 性能最適化のマインドセット を持っていることが多い
言語そのものより、そうした姿勢のほうが性能を左右する
uvが
python<4.0の上限制約を無視する理由が興味深い大半のパッケージはPython 4で壊れることを恐れて 防御的に 設定しているだけで、実際には問題ない
上限制約は現実的な問題よりも、仮想的な問題を解決しようとする試みだった
python<3.0のような制約は依然として重要なので、そのようなケースは防ぐべきだPEP 658が2023年に適用され、uvが2024年に登場したのは偶然ではない
エコシステムの準備が整ったからこそ、uvのようなツールが可能になった
ただ、パッケージメンテナーたちがなぜこうした変化を受け入れたのかは気になる
setup.pyでうまく回っていた人たちもいたはずだが、pyproject.toml へ移行した動機は何だったのだろうかsetup.pyは多くの人にとって不便だったたとえばRequestsですら、まだ完全なPEP 517/518/621互換ではない
1年半たってもマイナーリリースが遅れており、その間に ビルド問題 も発生していた
ただし、pipがなぜこれを十分に活用していないのかは疑問だ
「実行しないコードパスは待つ必要がない」という表現は不正確だ
時間を節約するのは、実際に実行しないコードだけだ
たとえば
.eggサポートがなくても、それがすでに 廃止された形式 なら速度には影響しない実際にどの項目がどれだけ時間を節約したのかという 定量データ があれば、さらに良かったと思う
それでも全体としてはよく整理された記事だ