インタプリタ
ソースコードを機械語に変換せず、その場で解釈して実行する。
方式#
| 方式 | 内容 | 速度 |
|---|---|---|
| AST ウォーカー | AST を再帰的に辿る | 最も遅い |
| バイトコード VM | バイトコードに落として仮想機械で回す | 中間 |
| JIT | 実行時に機械語へ | 速い |
実用的なインタプリタ(CPython、Ruby)は バイトコード VM 方式をとる。 AST を毎回辿るのは、ノードごとの分岐と ポインタ追跡が多すぎて遅い。
遅い理由#
a + bコンパイル後の機械語なら 1 命令。 インタプリタでは
- バイトコードを読む
- 命令の種類で分岐する(ディスパッチ)
- オペランドの型を実行時に調べる
- 型に応じた加算を選ぶ
- 結果をオブジェクトとして確保する
10〜100 倍の差がつく。 分岐予測が当たらないディスパッチループが特に重い。
利点#
| 利点 | 内容 |
|---|---|
| 起動が速い | ビルド不要 |
| 対話的に使える | REPL |
| 移植性 | 処理系があれば動く |
| 動的な機能 | eval、実行時のクラス変更 |
| デバッグ | ソースの位置がそのまま分かる |
Python の GIL#
CPython はグローバルインタプリタロックにより、 同時に 1 スレッドしかバイトコードを実行できない。
参照カウントの更新を安全にするための設計だが、 CPU バウンドな処理がスレッドで並列化できない。 数値計算で NumPy(C 実装で GIL を解放する)や マルチプロセスが使われるのはこのため。
Python 3.13 以降、GIL を無効化できるビルドが 実験的に導入されている。
参考文献#
- Robert Nystrom. Crafting Interpreters. Genever Benning, 2021.(全文公開) https://craftinginterpreters.com/
- Alfred V. Aho, Monica S. Lam, Ravi Sethi, Jeffrey D. Ullman. Compilers: Principles, Techniques, and Tools, 2nd ed. Pearson, 2006.
- PEP 703 – Making the Global Interpreter Lock Optional in CPython. https://peps.python.org/pep-0703/