DEV Community 日本語
フォロー
Python ORM を Rust エンジンで構築しました — GIL、PyO3、asyncio が実際に連携する方法
Yara-orm は、Python 向けに設計された新しい非同期 ORM で、Django スタイルのモデルインターフェースを提供しますが、読み取りパフォーマンスの向上には Rust ベースのエンジンを使用しています。コアのイノベーションは、Python のシングルスレッド asyncio イベントループと Rust の Tokio のマルチスレッドランタイムを組み合わせたデュアルランタイムアーキテクチャにあります。このセットアップは、Python の I/O 操作とデータベース操作間のブロッキングを防ぐことを目的としています。Global Interpreter Lock (GIL) は課題を提示し、Python オブジェクトとのやり取り時に Rust コードでの明示的な処理が必要です。Yara-orm は、GIL をパラメータバインディング (Python から Rust へ) および行デコーディング (Rust から Python へ) の間のみで取得することにより、これを管理します。Rust データベースエンジンは、コネクションプーリングとクエリ実行を含め、GIL を解放した状態で動作し、他の Python タスクが並行して実行できるようになります。これらのランタイム間で渡されるデータは所有権を持ち、スレッド間での安全性を確保するために Send である必要があります。Rust の future は pyo3-async-runtimes を使用して Python の awaitable に変換され、Python の asyncio ループとシームレスに統合されます。Rust の future が Tokio のワーカー スレッドで完了すると、その結果は処理のために asyncio ループにスケジュールバックされます。このアーキテクチャにより、asyncio イベントループはデータベース I/O によってブロックされず、データベース I/O は GIL を保持しません。パフォーマンスの最適化は、行ごとに発生し、ORM の速度に大きく影響する行デコーディングプロセスに集中しています。これらの最適化には、効率的な型処理と、より高速なデータ変換のためのディスパッチメカニズムが含まれます。同期ドライバーを使用する SQLite の場合、デカップリングの原則を維持するために専用のブロッキングスレッドプールが使用されます。GIL を保持する直接変換と、シリアライゼーションアプローチ (MessagePack など) との間の選択は、トレードオフとして提示されます。Yara-orm は直接変換を選択し、典型的なシングルイベントループの非同期 Python サービスでより良いパフォーマンスを提供すると考えています。このプロジェクトは pip を介してインストール可能で、GitHub リポジトリとドキュメントへのリンクが提供されています。著者は、同様の PyO3 ブリッジを構築した他の開発者からの洞察も求めています。