世界を動かす技術を、日本語で。

Pythonのパフォーマンスに関する神話とおとぎ話

概要

  • EuroPython 2025で Antonio Cuni が「Pythonパフォーマンスの神話とおとぎ話」について講演
  • Pythonのパフォーマンスに関する 誤解や神話 を実例で解説
  • メモリ管理 がPython高速化の最終的な壁であると指摘
  • 静的型付けやJIT導入でも 本質的な問題 は解決しない現状
  • 新プロジェクト SPy による超高速Python実現への期待

EuroPython 2025講演:「Pythonパフォーマンスの神話とおとぎ話」

  • 講演者は PyPy開発者 であり、長年Pythonのパフォーマンスに取り組む Antonio Cuni

  • 会場で「Pythonは遅いと思うか」と質問、多くの手が挙がる

  • 「Pythonは遅くない」「Pythonはグルー言語だから速度は問題ない」といった 神話の否定

  • Pythonで十分速いプログラムもあるが、 全ての用途に適しているわけではない

  • パフォーマンスが求められる場面では CythonやNumba などの利用が進む現状

    • Pythonが速いとされる用途と、全てのPythonプログラムの関係を ベン図 で説明
  • 「グルー言語だからホットスポットだけC/C++やRustで書けば良い」という 考えの限界

    • パレートの法則 (80/20則)や アムダールの法則 により、最適化には限界がある

Pythonが遅い本当の理由

  • 「インタプリタだから遅い」は 部分的な真実 に過ぎない
  • 例:p.x * 2 という表現でも、Pythonでは 多段階の処理とメモリアロケーション が発生
  • これらは 言語の動的性質 に起因し、インタプリタか否かは本質的な問題ではない

静的型付けと最適化の誤解

  • Pythonの型アノテーションは 実行時に強制されない
  • 型ヒントがあっても、 実際には様々な型の値が渡される可能性 がある
  • クラス定義や特殊メソッドの削除、インポートの動的変更など、 静的解析・コンパイルの困難性 を例示

JIT導入の限界と「最適化チェイシング」

  • JIT導入で 高速化は可能だが、実装は複雑化
  • JITの挙動を意識した コード設計が必要 となり、パフォーマンス予測が難しい
  • 一部の最適化が崩れると 全体が急激に遅くなる現象 (最適化チェイシング)の発生

Pythonの極端な動的性質

  • import文の挙動やグローバル変数の値、型アノテーション、デコレータなど、 何が起きるかコンパイラは予測困難
  • 99%のケースでは素直な使い方だが、 1%のダイナミズムがPythonの魅力 でもある
  • ライブラリ開発者が ダイナミックな機能 を活用して使いやすいAPIを実現

コンパイラゲーム:何も信じられないPythonコード

  • 動的属性追加、ランダムなメソッド定義、__new__のトリック、グローバルの差し替えなど 極端な例 を紹介
    • これらが 最適化や静的解析の壁 となる

抽象化とパフォーマンスのトレードオフ

  • コードの見通しや保守性を求めて 関数化やデータクラス化 すると、 オーバーヘッドが発生
  • JITでも 関数呼び出しや抽象化のコスト を完全には消せない
  • Pythonでは「 抽象化は無料ではない」という現実

Python高速化の限界と今後

  • パフォーマンスを突き詰めると 最終的にメモリ管理の壁 に直面
  • 現状のCPythonやPyPyの枠組みでは 根本的な高速化は困難
  • SPyプロジェクト :より速いPython実現を目指す初期段階の取り組み
  • 理想は「 全ての用途にPythonが使える世界」だが、現状はまだ道半ば

この講演は、 Pythonパフォーマンスに関する誤解や現実、そして 今後の可能性 を多面的に解説する内容。 最適化手法の限界や、 言語仕様がもたらす根本的な難しさ について深く掘り下げている。

Hackerたちの意見

いい記事だね。あの問題の多くはPython特有じゃないから、30年も前の言語から他の人が学べることの良い概要だと思う!多分、JS/TSの道を進むことになるだろうね。別のコンパイラ(PyPyとかmypyとか他の何か)がCPythonと一緒に動く感じ。でも、Python4は来ないと思うな。

GILがなくなるなんて思ってもみなかったけど、今ここにいるよね。何事も可能性はゼロじゃない。もしかしたらPython4は別のコンパイラを使ったPythonかもね。

JS/TSの話がよくわからないんだけど、TSは単なる型チェッカーで、ランタイムパフォーマンスには全く影響しないよね。

99%のパフォーマンスを1%のケースのために払ってるってことだよね。なんでみんなこれが良いトレードオフだと思うんだろう?

コードを書くのが楽しいからだよ。全てがスケールする必要も速くある必要もないし。個人的には、99%の時間を最適化して1%のために使うのがもっとクレイジーだと思う。

確実に言えるのは、一銭も払ったことがないってこと。君は?

コンピュータは、プログラミングを始めた頃の100倍以上速くなってるし、その頃ですでに十分速かったんだよね。(その間に自分のコーディング能力はあまり良くなってないし、むしろ悪くなってるかも)

1%なんて全然足りないよ。pytestやPydanticみたいなよく使われるライブラリが成り立つのはそのおかげなんだから。

多くの人がSmalltalkやCommon Lisp、Self、Dylanを使ったことがないから、CPythonが唯一の選択肢だと思ってるんだよね。それに、Electronアプリでリソースを無駄にしてるから、CPythonのパフォーマンスについて疑問を持つこともほとんどない。

そうじゃないよ。Pythonには向いてないことがたくさんある。ただ、ずっと前から存在してるし、サイバーセキュリティみたいな影響力のあるニッチな分野では、Pythonはネイティブツールよりも役立つこともあるし、複数のプラットフォームで動くからね。

大抵の場合、待ってるのは人間か、少なくともCPU以外の何かだよね。プログラマーがコードを書くのにかかる時間の方が、全ユーザーがプログラムが動くのを待つ時間よりも長いことが多い。だから、これら二つの間では、パフォーマンスは大抵トレードオフしても問題ないよ。

コードが正しくないなら、パフォーマンスは無意味だよ。簡単なケースでは、Pythonで正しいコードを書くのが比較的早いし(整数はCのようにオーバーフローしないし、C#のようにラップアラウンドもしないし、他のスクリプト言語のような馬鹿げた暗黙の変換もない)。また、ほとんどの場合、コードが速くある必要はない。たまに人間が実行する数値計算が必要なだけなら、1秒かかっても大丈夫だよ。シェルスクリプトの代わりにもかなり良い。

これを知ってる人は、これが良いトレードオフだとは思ってないと思う。もっと興味深いのは、そもそもなぜそのトレードオフが行われたのかってことだよね。答えは、私たちがこれらの設計決定の影響を理解するのが比較的簡単だから。過去20年以上のPythonの結果を見てきたからね。後知恵は20/20だよ。Pythonは1991年にリリースされたんだから、Javaよりも前だし。当時のプログラミングに関する知識と、今の知識は全然違うよね。あ、あと、こういうトレードオフは一般的に作るのがすごく難しいんだ。あなたがその時は関係ないと思っていた設計決定が、後でパフォーマンスにとって重要になることもあるけど、その時点では互換性のために設計が固定されちゃってるんだよね。

PyPyがもっと人気になることを本当に願ってる。そうすれば、Pythonがかなり速いってことを何度も主張しなくて済むから。CPythonにこだわる必要があっても、NumbaやPythranなどを使えば、最小限のコード変更で素晴らしいパフォーマンスが得られるよ。

ここで重要な背景は、コンピュータが推測的なハッピーパス実行が得意だってことだね。記事の例は暗い感じだけど、JITが引数が変じゃないかチェックするのをどうやって意味のある形でインタプリタを動かすよりも良くできるのか?でも実際には、JITはこれらのチェックを行うコードを生成できるし、現代のプロセッサはハッピーパスを予測して、チェックと並行して実行するんだ。JavaScriptも複雑なプロトタイプチェーンやボックス化されたオブジェクトの一般的な使用があるけど、v8は一般的なユースケースをすごく速くしてる。Pythonの未来が楽しみだな。

主な問題は、最適化が無邪気な変更によって静かに失敗して、突然パフォーマンスが10倍落ちることだよ。これはどの言語でも問題だけど(CPUキャッシュミスはあるし、非動的言語でもボックス化されたオブジェクトがあるからね)、PythonやJS、Rubyのような動的言語ではもっとひどい。大抵の場合は問題にならないけど、高スループットのPythonコードはC/C++を呼び出すことが多いから、そういう懸念はあまり大きくない。ほとんどのJSコードもC/C++のブラウザDOMオブジェクトを呼び出すだけだし。ホットパスがこれらの言語にない限り、「無邪気な変更でパフォーマンスが落ちる」リスクはそんなに高くない。サーバーサイドでも、ほとんどのJS/Python/RubyコードはシンプルなHTTPスタックハンドラーやデータベースを呼び出してデータをやり取りしてるだけだからね。リクエスト処理の大部分(JSON/XMLなどのエンコード、HTTPメッセージのパースなど)は、低レベルの言語で書けることが多い。

ちょっと軽い感じで言うと、LispマシンのCISCサポート言語のフルスタック設計哲学は、MシリーズのリオーダーバッファやILPがJavaScriptCoreをサポートしているところに生き続けていると言えるね。

そういうわけで、絶対的に見れば、Pythonは思ったほど遅くないんだよね。でも、プログラミング言語のパフォーマンスは絶対的に測るものじゃない。一般的にはCに対して相対的に測るんだ。で、君のPythonコードがこのPythonオブジェクトがどうアンボックスされるか、メソッドがどこにあるか、パラメータをどうアンボックスするか、どのメソッドが呼ばれるかを推測している間に、コンパイルされたコードはプログラマーが書いた実際のコードを推測して並行して実行してる。だから、Pythonインタープリターが実際のオブジェクトでメソッド呼び出しがどう解決されるかを推測し終わる頃には、コンパイルされたコードは同じ文法の複雑さのコードを約50行終わらせてる。これはちょっと雑な表現だけど、PythonとCの「p.x = y」レベルのステートメントを比較してるってことね。これを避ける方法はないよ。君はその素晴らしく能力のある推測並列CPUをPythonの解釈に使うか、実際の作業に使うかのどちらかしかできない。両方は無理だよ。結局、インタープリターもCコードだからね。特別な推測オペコードにアクセスできるわけじゃない。

JSはプロトタイプの変更をサポートしているけど、最適化を難しくするwith演算子や他の構文は、典型的なJSコードでは使われていない。だからJITは、問題のある構文の存在をチェックして遅いパスに誘導しつつ、特に大きくない一般的なパターンを最適化するためのチェックを追加できる。そして、JSのJITは、ブラウザの内部がJITのニーズに合わせて調整/リファクタリングできるので、任意のネイティブコードを呼び出すことについてあまり気にする必要がない。Pythonではそれがうまくいかない。最適化に優しくない構文が単純に多くて、人気のあるライブラリがそれを使っているから。さらに、Pythonは固定ABIの任意のCライブラリを呼び出すから、Pythonの最適化は本質的に難しいんだ。

でも、v8は一般的なユースケースをすごく速くしてくれたよね。Pythonの未来が楽しみだな。v8はまだ完全にシングルスレッドで、メッセージパッシングも限られてるんじゃない?Pythonはマルチスレッドのコードを速くするためにたくさんの作業をしたばかりなのに、もしスレッドを完全に捨てて、v8に合わせるために共有メモリでマルチプロセッシングに戻ることになったら、がっかりだよね。

ブランチ予測が、ハッピーパスのチェックが大きく/複雑になるときにパフォーマンスの損失を隠せるのか気になるな。ブランチ予測は非常に低レベルの最適化だし、予測が正しければすべてが無料になるわけじゃない。CPUは条件を評価しなきゃいけないから、リソースを使うんだよね。とはいえ、それがクリティカルパスから外れてるのは確かだけど。条件の実行よりも先に進みすぎると、CPUがスタックすると思うんだ。結局、プログラムが完了するまでにはすべてのコードが実行されなきゃいけないから。Pythonの特性を考えると、チェックがすごく複雑になって、タイトなループではリソースにかなりの圧力をかけるかもしれないね。

100%集中して読んだわけじゃないけど、このトークの内容は神話を打ち消すんじゃなくて、むしろ確認してるように見えたな。

そうそう、これでPythonが遅い理由が全部確認できた気がする。スクリプトを超える用途には向いてないと思う。毎日使ってるけど、mypyみたいなツールも信頼できないことが分かった。隅々まで考慮されてないケースが多すぎるからね。言語に明確な型設計がないと、外部ツールで根本的に解決できるわけじゃない。テストだけが、この言語で書かれたコードを信頼できる唯一の手段だよ。

記事をもっと注意深く読む必要があるよ。最初の神話は「Pythonは遅くない」ってやつで、これは打ち消されてる。遅いからね。次の神話は「ただのグルー言語で、ホットパーツをC/C++で書き直せばいい」ってやつで、これも打ち消されてる。C/Rustで書き直すだけじゃ解決しないんだ。三つ目の神話は「Pythonはインタプリタだから遅い」ってやつで、これも打ち消されてる。インタプリタだから遅いわけじゃないんだよ。

「ホットパスをC/C++で書き直す」ってのも地雷だよ。境界を越えるのがすごく非効率的だからね。だから、ネイティブコードを継続的に呼び出すんじゃなくて、「できるだけ一度にディスパッチする」必要があるんだ。

これは、ループ内で同じ操作を繰り返すことを取り出す一般的なルールの具体例じゃない? CPythonでCへの呼び出しが特に遅いかどうかは疑問だな(多くの操作は実際にはCを呼び出してるだけだし)。

境界を越えるのがどれだけ非効率的か 99.99%のプログラムに関して言えば、現代のM.2 NVMEハードドライブは十分速いし、C拡張やプロセスにデータを読み込むための一番楽な方法なんだ。それに、Unixパイプも十分速いよね。共有メモリもあって、基本的に読み込みがないからね。Pythonの場合、すべてはセットアップ次第だよ。

最近は「Rustで書き直し」って感じだよね。通常、Pythonは入り口と出口のポイント(ちょっと手を加える程度)でしょ?それからビジネスロジックの大部分はRust/C++/Fortranで処理されるんじゃない?

Pythonを「グルー言語」として使う一例で、実際にバインディングのパフォーマンス問題を避けられるのはGNU Radioだね。これは、基本的にPythonを設定言語として使って、スタートアップ時に計算フローグラフをセットアップするからで、その後の実行時は完全にコンパイルされたコード(一般的にはC++)で動くんだ。もちろん、このアプローチはすべての問題に適用できるわけじゃないけど、遅いグルー言語が受け入れられる場面についての考え方を大きく変えたよ。

効率の悪さだけじゃないよね。PyO3やSWIGみたいな高機能なFFIジェネレーターを使っても、FFIを追加するのはめっちゃ手間がかかるし、複雑になるし、デバッグも難しくなるし、配布も大変になる。個人的には、FFIを使って二つの言語でプロジェクトを書く場合は、通常は一つの言語だけでやった方がいいと思う。たとえその言語が最適じゃなくてもね。この場合は、全部C++(かRust)で書いちゃえばいいんじゃないかな。例外もあるけど、一般的にFFIは大きなコストで、C++を使ってるならPythonを使う理由はあまりないと思う。

ここでの主な焦点は良い点で、私が考えもしなかったことだね。Pythonのメモリが非常にダイナミックなため、キャッシュの局所性が悪くなるってこと。納得だわ。それは他の人に掘り下げてもらうとして、私はある程度の難癖を期待してたけど、これには失望しなかったよ。「C/C++/Rustのコンパイラは、その種の式を三つの操作に変えられる:xの値をロードして、それを二倍にして、結果を保存する。しかしPythonでは、pの型を見つけることから始まり、getattribute()メソッドを呼び出し、p.xと2をアンボックスし、最後に結果をボックスするという長い操作のリストが必要になる。これらのステップは、Pythonが解釈されているかどうかには依存しない、言語のセマンティクスに基づいて必要なんだ。」この議論の問題は、ユーザーがこれらのことをしようとしているのではなく、掛け算をしようとしているということ。だから、言語がすべてのことをしなければならないという事実は、結局遅いということを意味する。なぜなら、これらのことが行われなければ、最終的な結果はまだ達成できるから。これは純粋なオーバーヘッドで、この状況では価値がない。つまり、もしPythonに十分に賢いコンパイラ/JITがあれば、これらのことは最適化できる(この使用例では、全てではないけど)。この議論は、「Pythonは遅くない、ただたくさんの作業をしているだけ」というのに似てるかも。それは真実かもしれないけど、そこで終わらせちゃダメ。これらの作業に価値があるかどうかを問わなきゃいけないし、この場合、価値はない。似たような議論で、誰かが「最適化されたインタープリターを持つ任意の解釈言語は『速い』」と言うかもしれない。でも、これも考え方が間違ってる。常に「ユーザーは何をしようとしているのか? そして(速い言語と比較して)計算は速いのか?」と問いかけることから始めなきゃ。もし答えが「いいえ」なら、その言語は速くない。たとえ期待される目的を達成してもね。こういうことを遊び半分でやるから、ユーザーは「速い」言語と「遅い」言語の違いに混乱するんだ。遅いことは必ずしも「悪い」わけじゃないけど、事実を直視しよう。この場合、正しい言い方は「速いインタープリターを持っている」と言うことだね。最後の言葉は、十分な経験を持つ開発者に必要なことを伝える(静的コンパイルされた/JITと解釈された言語は異なる速度クラスにあり、実行速度で直接比較すべきではないことを理解しているから)。

前の段落は、>「もう一つの『神話』は、Pythonが遅いのは解釈されているからだ。確かにその通りな部分もあるが、解釈はPythonが遅くなる要因のほんの一部に過ぎない。」彼は遅いことを認めているけど、解釈されていることとは関係ないと言っているんだ。

「十分に賢いコンパイラ」は、Pythonのセマンティクスを合法的にスキップできないんだ。Pythonでは、p.x * 2は動的なルックアップや、可能なディスクリプタ、大きな整数のオーバーフローチェックなどを意味する。コンパイラがそれを省略できるのは、重要でないことを証明するか、推測してガードを追加する場合だけなんだけど、それでもオーバーヘッドが発生する。だから、Pythonはスカラーのホットループで遅くなるんだ。解釈されているからじゃなくて、動的な契約を守らなきゃいけないからなんだよね。

この議論の問題点は、ユーザーがそういうことをしようとしていないってことだ。俺はちょっと違う意見を持ってる。問題はユーザーがそういうことをしているわけじゃなくて、言語が彼が何をしようとしているかを理解していないことだ。Pythonの明確な目標は常に使いやすさで、スピードや面倒なコンパイルエラーメッセージよりも使いやすさが優先されていた。「書かれた通りにコードを実行しろ、くそ!」が常に目指していたことだ。クラスモデルが導入されたとき、__get_attribute__の導入が必要になったことを覚えている。Cプログラマーとしての最初の反応は「おお、そこは速度が落ちるね」だった。その後の反応は、新しいシステムを発明者が考えもしなかったような形にねじ曲げるために使うことだった。それはLR(1)パーサーで、文法を通常のPython文として書けるようにしてくれた。彼らが特定の方法で言語を悪用することを考えていなかったかもしれないが、明確な目標は最小限のコードであらゆるアイデアを表現できるフレームワークを作ることだったと思う。他の人たちも、言語の構築方法に提供されたフックを使って、pydanticやspyneのようなものを作っていた。例えば、SpyneはRPCで使われる通信フォーマットをPythonのクラス宣言として表現でき、それをJSONやXML、SOAPなどにコンパイルできる。SqlalchemyはPythonの構文を使ってSQLを表現できるが、もっとストレートな方法だ。どれも言語をうまくねじ曲げているよね。そのフレームワークの中では、「a = b + c」は「bをcに足して、その結果をaに置く」って意味じゃない。例えばLR(1)パーサーでは「'a'という生成物があって、それは'b'の後に'c'が続く」って意味だ。その定義の中で'a'は'b'と'c'への参照を持っている。後でLR(1)パーサーはそれを消費して、全く違うものにコンパイルする。結果は2の補数加算とは大きく異なる。強力な型システムを同じように使うことも可能だ。例えば、Scalarで表現されたFPGA設計を見たことがある。しかし、Scalarの型システムはコンパイル時に何が起こっているかを知ることを要求するので、Scalarはプログラマーが何を作っているかをある程度把握している。コンパイル結果は他のコードと比べて遅くなることはないだろう。Pythonはコンパイル時の型チェックをほぼ完全に放棄することで同じ柔軟性を達成し、すべてをランタイムに押し込んだ。だから、コンパイラーは最終的に何が実行されるかを全く知らない(例えば、LRパーサーでの+操作は一度だけ実行される)。これが俺が言った「言語がプログラマーが何をしようとしているかを知らない」ってことだ。お前は、インタープリター言語だから、インタープリターがランタイムでプログラマーが何をしようとしているかを理解する役割を持つべきだと言っている。確かに「a = b + c」が実際にはオーバーフローしない32ビット整数を加算していることは理解できる。でも、それはランタイムでやるべき仕事が増えるってことだ。これは、同じことを言い換えた形で、話の内容と同じことだ:ランタイムでやることを選ぶってことは、言語がスピードよりも柔軟性を選んだってことだ。インタープリターでこれを常に修正することはできない。Javascriptには最高のインタープリターがあって、ハッピーパスを速く実行することができる。でも、そういうインタープリターには注意点があって、通常は「クラスの内部をいじると、例えばランタイムで関数定義を置き換えると、JITの試みをすべて放棄する」って形だ。人々は通常Javascriptでそんなことをしないけど、実際にはPythonのデザインはメタクラスや「type(...)」、そして「new(..)」を使って、そういうコーディングスタイルを奨励していると言えるかもしれない。つまり、これもまた言語設計の選択で、スピードよりも柔軟性を重視するものなんだ。

彼の「悲しい真実」という結論は、「Pythonは互換性を壊さずには超高速にはなれない」ということだ。Python 4.0の良い例かな? > だから、もしかしたら「JITコンパイラがすべての問題を解決できる」かもしれない。Cuniは、Pythonや他の動的言語を速くするために大きな助けになると言った。でも、それは「もっと微妙な問題」に繋がるんだ。彼はトリレマの三角形のスライドを出して、動的言語、速度、シンプルな実装のどれか2つは持てるけど、3つは無理だって言ってた。このトリレマが、またJuliaに戻る理由なんだ。Pythonよりもシンプルではないけど、ずっと速いし(プリコンパイル時間で軽減されるけど)、ほぼ同じくらい動的だよ。この言語が死ななかったのは嬉しいな。

Python 4.0の良い例かな?最終的にはこれに同意するけど、今は開発者がオブジェクトにdynamic=Falseを設定して、オプトインにするだけでいいんじゃない?これがGoogleがAngularの破壊的アップグレードを扱う方法で、実際には人々が数年かけて破壊的な変更に備えることができるから、うまくいってるんだよね。

Python 4.0の良い例かな?「Python 4.0」は、実質的には別のチームによって作られた新しい言語になると思うけど、強い文法的な類似性があるだけなんだよね。(それがまだ実現していない理由の一部は、みんなそのタスクのスケールにビビっちゃってるからだと思う。)Juliaをチェックするのを忘れてたことを思い出させてくれてありがとう。

Juliaがパッケージマネージャーの問題を解決したら(インポートの読み込みにまだ時間がかかるのかな?)、人気が出ると思う。

そうだね、これは「用途に応じた馬」ってやつだね。Pythonが大好きだよ。uvとの相性が最高で、今朝はデータを分析するためのシンプルなCLIを実装したんだけど、インライン依存関係があって、必要なものにぴったりで、書くのも実行するのも調整するのもめっちゃ簡単だった。過去の経験から言うと、パフォーマンス(レイテンシーやスループット)やリクエストのスケーラビリティが問題になるAPIサーバーにはPythonを使うべきじゃないと思う。そういうのには他に素晴らしいツールがたくさんあるからね。もしAPIサーバーを書く必要があって、超高パフォーマンスじゃなくても大丈夫なら、Pythonはそれにも向いてるよ。でも、Pythonにはそれに合った良さがある。もしPython 4.0がいくつかの破壊的な変更を伴うものになったら、Pydanticみたいなものが引き続き動くように、インタープリタの特性を保ってほしいな。

サイトのトップコメントがCommon LISPのアプローチについてだなんて面白いね。それに同意せざるを得ないよ。数十年前に、最適化が簡単だった超動的システムがあったのが理解できない。もしMathematicaを使うチャンスがあったら、みんな助けてあげてほしいね。

記事では、Pythonのパフォーマンス最適化に関する重要な課題が強調されてるけど、特にそのダイナミックな特性が影響してるんだよね。でも、実用的な解決策は、Pythonを純粋な汎用インタープリタ言語として見るんじゃなくて、基本的にドメイン特化言語(DSL)フレームワークとして見ることだと思う。DSLは、高効率な機械コードにコンパイルできるからね。数値計算のためのNumba JITや、データ処理のためのBodo JIT/データフレーム、深層学習のためのPyTorchなんかがその例だよ。Pythonの柔軟な構文は、配列やデータフレームの操作など、複雑なオブジェクトやそのオペレーターを作ることを可能にしていて、これらのコンパイラはそれをC++レベルのパフォーマンスに近いコードに効率的に変換するんだ。DSLのオペレーター実装は、必要に応じてC++やRustのような低レベル言語を活用することもできる。記事で触れられていないもう一つの重要な側面は、並列性なんだけど、これはDSLコンパイラがかなり効果的に扱うことができるんだよね。データサイエンスやAIがPythonの主要なユースケースだから、NumbaやBodo、PyTorchのようなコンパイラは、パフォーマンスが重要なシナリオにどれだけ効果的に対処できるかを示しているよ。DSLコンパイラにさらに投資することは、開発者の使いやすさや生産性を損なうことなく、Pythonのパフォーマンスやスケーラビリティを向上させる実用的な道筋だと思う。ちなみに、私は以前NumbaとBodo JITに関わってたよ。

このコメント、LLMが書いたのかな?