web-dev-qa-db-ja.com

インタープリターコードとコンパイル済みコードのパフォーマンスに関する一般的な説明はできますか?

私は2つのテクノロジーを比較して、企業がどちらを使用すべきかという推奨事項に到達しました。テクノロジーAのコードは解釈され、テクノロジーBのコードはマシンコードにコンパイルされます。私の比較では、通訳プロセスの追加のオーバーヘッドがないため、技術Bの方が一般にパフォーマンスが優れていると述べています。また、プログラムはさまざまな方法で作成できるため、技術Aで作成されたプログラムが技術Bで作成されたプログラムよりも優れている可能性があることも述べています。

レビューのためにこのレポートを提出したとき、レビュー担当者は、通例、解釈プロセスのオーバーヘッドが技術Bのパフォーマンスの方が優れていると結論付けるのに十分な大きさである理由を明確に示していないと述べました。

だから私の質問は、コンパイル/解釈されたテクノロジーのパフォーマンスについて何か言うことができるでしょうか?コンパイルされたものが一般的に解釈された後、解釈されたと言える場合、レビュー担当者に私の主張をどのように説得できますか?

60
EpicSam

番号。

一般に、言語実装のパフォーマンスは、主にそれに費やされたお金、リソース、人材、研究、エンジニアリング、開発の量に依存します。

具体的には、特定のプログラムのパフォーマンスは、主にそのアルゴリズムに組み込まれた思考の量に依存します。

very高速インタープリターがいくつかあり、very slowコードを生成するコンパイラーもあります。

たとえば、Forthが依然として人気がある理由の1つは、多くの場合、解釈されたForthプログラムが同等のコンパイル済みCプログラムよりも高速であると同時に、Forthで記述されたユーザープログラムplus Cで書かれたForthインタープリターは小さい Cで書かれたユーザープログラムよりも小さい.

110
Jörg W Mittag

一般化と特定のシナリオは文字通り正反対です。

あなたは自分と矛盾しているようです。一方では、インタプリタ言語とコンパイル済み言語についての一般的な声明を出したいとします。しかし、その一方で、テクノロジーAとテクノロジーBを含む具体的なシナリオにその一般的なステートメントを適用したいとします。

具体的なシナリオに何かを適用すると、それはもう一般化されません。したがって、インタプリタ言語が一般的に遅い場合であると主張できても、まだあなたの主張はしていません。レビュー担当者は一般化について気にしません。 2つの非常に具体的なテクノロジーの分析を行っています。それは文字通り一般化の逆です。

81
loneboat

経験則として、インタープリタープログラムは、インタープリターのホスト言語でプログラムを作成するよりも約2倍から10倍遅く、より動的な言語のインタープリターは低速です。これは、インタプリタされたプログラムが実際の作業をすべて実行する必要があるだけでなく、解釈のオーバーヘッドが発生するためです。

インタープリターの構造によっては、非常に大きな違いがある場合があります。インタープリター設計には2つの相反する方法があります。1つは、オプコードをできるだけ簡単に最適化できるようにできるだけ小さくすべきであり、もう1つは、オプコードをできるだけ大きくしてインタープリター内でより多くの作業を行えるようにするべきだと言います。プログラムの構造がインタプリタの哲学と一致する場合、オーバーヘッドは無視できるほどになります。

例えば。 Perlは、テキスト操作を目的としたインタプリタ言語です。テキスト操作を行う慣用的なPerlプログラムは、Cプログラムほど遅くはなく、場合によってはCプログラムよりもパフォーマンスが優れている可能性があります(Perlは異なる文字列表現を使用し、さまざまなテキストおよびIO関連の最適化が組み込まれているため可能性があります)。ただし、Perlで数値を計算するのは非常に遅くなります。増分++xは単一のAssembly命令ですが、Perlインタープリター用の複数のポインタートラバーサルとブランチが含まれます。最近、CPUにバインドされたPerlスクリプトをC++に移植し、コンパイラーの最適化レベルに応じて、7倍から20倍のスピードアップを実現しました。

ここでは、最適化について話すことが重要です。洗練された最適化されたインタープリターが、最適化されていない素朴なコンパイラーをかなり上回っている可能性があるためです。最適化コンパイラーの作成は困難であり、多くの労力を必要とするため、「テクノロジーB」がこのレベルの成熟度を持っているとは考えられません。

(注: Computer Language Benchmarks Game サイトの構造は混乱しますが、1つの問題のタイミングの表に到達すると、さまざまな言語のパフォーマンスが至るところにあることに気付くでしょう–多くの場合、そこにありますは、コンパイルされたソリューションと解釈されたソリューションの明確なパフォーマンスの境界ではありません。サイトの最も重要な部分はベンチマークの結果ではありませんが、ベンチマークがいかに難しいかについての議論です。

技術を選択するとき、言語ランタイム自体のパフォーマンスは完全に無関係です。技術がいくつかのベースライン制約を満たしていることがより重要である可能性が高く(予算は$ x、yyyy-mm-ddの前に提供できなければならず、さまざまな非機能要件を満たす必要があります)、総所有コスト(開発者の生産性、ハードウェアコスト、ビジネスチャンスコスト、バグのリスク、技術における予期しない制約、メンテナンスコスト、トレーニングおよび採用コストなどを考慮に入れる)例えば。市場投入までの時間が最も重要な要素である業界では、開発者の生産性が最も高い技術が最適です。大規模な組織では、保守性と長期的なコストの方が興味深いかもしれません。

37
amon

コンパイルされた/解釈されたテクノロジーのパフォーマンスについて何か言うことができます。しかし、最初に、「パフォーマンス」を定義する必要があります。計算が簡単な組み込みシステムを構築している場合、「パフォーマンス」はおそらくメモリ使用量の側面に傾くでしょう。一方、大規模なデータセットで動作する計算が複雑なシステムは、JVMまたは.NETからのメモリオーバーヘッドが無視できるため、単位時間あたりの計算数で「パフォーマンス」を定義します。

「パフォーマンス」とは何かを決定したら、「いつでもメモリに500億のオブジェクトが存在し、解釈されたtechAが各オブジェクトに追加の8バイトを追加して、内部管理のために400GBのメモリオーバーヘッドに相当します。このデータを追加しないtechBと比較して」

18
jhbh

これは技術的な質問であり、すでに多くの優れた技術的回答を得ていますが、状況の少し異なる側面を指摘したいと思います。「テクノロジーAまたはテクノロジーB」のような決定は、純粋にベースにできないという事実技術的および/またはパフォーマンス上の理由。

このようなものの技術的な側面は、AとBの間の決定のほんの一部です。覚えておくべき他の要素がたくさんあります。

  • ライセンス費用はかかりますか?例:SQL Serverマシンのクラスターを使用する場合とPostgreSQLマシンのクラスターを使用する場合では、(かなりの金額)を支払う必要があります。
  • そのテクノロジー(スタック)とそのエコシステムに精通している従業員はいますか?はいの場合、それらは利用可能ですか?いいえの場合、雇うことはできますか?どれくらいの費用がかかりますか?または、既存のものをトレーニングしますか?それはいくらかかりますか?
  • クライアントは何を望んでいるのですか?これは多くの場合、問題になる可能性があります。
  • 私が推奨するテクノロジーは本番環境で使用する準備ができていますか?それとも、おそらく現在消滅する可能性のある誇大宣伝ですか?(たとえば、最初に登場したNode.jsについて考えます)
  • 私が推奨するテクノロジは、既存のアーキテクチャまたは私が考えていたアーキテクチャにうまく適合しますか?または、それらをシームレスに連携させることにより、多くの費用を費やす必要がありますか?
  • そしてあなたの特定の状況に依存する多くのより多くの側面。

ご覧のとおり、このような決定を行う際に考慮すべき事項がたくさんあります。

これは具体的にあなたの質問に答えるものではないことは知っていますが、あなたの状況とそのような決定の詳細についてより全体像をもたらすと思います。

12
Radu Murzea

部分評価 は、インタプリタとコンパイラの関連に関連する概念的なフレームワークです。

インタープリターコードとコンパイル済みコードのパフォーマンスに関する一般的な説明はできますか?

プログラミング言語は仕様です(- R5RS または n157 などのレポートに記述されています)。これらはではないソフトウェアであるため、パフォーマンスといっても意味がありません。ただし、一部のプログラミング言語には interpreters および compilers を含むいくつかの実装がある場合があります。

Cのような伝統的にコンパイルされた言語(つまり、実装がしばしばコンパイラーである言語)でさえ、一部はしばしば解釈されます。たとえば、フォーマット制御文字列 printf (C標準で定義)はoften "interpreted"(- C標準ライブラリ 、これはprintf関数を使用して可変引数テクニックを使用しますが、一部のコンパイラー(- [〜#〜] gcc [〜#〜] )は、limited特定のケースで-最適化し、低レベルの呼び出しに「コンパイル」することができます。

また、一部の実装では、「インタプリタ」内であっても JITコンパイル テクニックを使用しています(runtimeでマシンコードを生成します)。良い例は luajit です。他の実装(例:Python、Ocaml、Java、Parrot、Lua)は、ソースコードを bytecode に変換して解釈されます。

[〜#〜] sbcl [〜#〜] は、すべての動的なLISP "コンパイラ"です [〜#〜] repl [〜#〜] インタラクション(およびマシンコードへのeval etc ...)の呼び出し。だからあなたはそれが通訳だと感じます。ブラウザーでのほとんどのJavaScript実装(例 v8 )は、JITコンパイル技術を使用します。

つまり、インタープリターとコンパイラーの違いは非常にあいまいであり(実際には両方の間に連続体があります)、実際には、ほとんどのプログラミング言語の実装にはインタープリターとaの両方があることがよくあります。コンパイラ(少なくともバイトコードに対して)ファセット。

実装は、ほとんどの「コンパイラー」または「インタープリター」のような手法を使用するかどうかに関係なく、高速または低速です。

一部の言語特性は解釈アプローチを支持します(そしてプログラム全体分析を通じてのみ効率的にコンパイルできます)。

someタイプの問題の場合、いくつかの metaprogramming アプローチでソフトウェアを設計することは価値があり、重要なスピードアップを提供します。特定の入力が与えられると、プログラムが動的に処理するための特別なコードを生成すると想像できます。これは、CまたはC++で 可能 でもあります(JITライブラリを使用するか、Cコードを生成し、動的にロードされるプラグインとしてコンパイルします)。

this related Pythonに関する質問、および that も参照してください。

10

_A = A + B_のようなコードの場合、1つまたは2つの機械語命令にコンパイルでき、それぞれが特定のサイクル数を必要とします。単純な理由で、インタプリタがそのサイクル数で同じことを行うことはできません。

インタプリタは、独自の命令セットも実行します(バイトコード、pコード、中間言語などと呼びます)。 ADDのようなバイトコードを見つけるたびに、どういうわけかそれを調べて、加算を行うコードに分岐する必要があります。

次の時間を見て、そのルックアップを繰り返しする必要があります、 unlessそれは前の検索を記憶する方法があります。以前のルックアップを記憶する方法がある場合、それはもはや「インタープリター」と呼ばれるものではなく、ジャストインタイムコンパイラーまたはJITterです。

一方...

callSomeFunction( ... some args ...)のようなコードの場合、そのコードの入力と終了の間に何サイクルが費やされますか?それはすべてcallSomeFunction内で何が起こるかに依存します。たとえcallSomeFunction自体がコンパイルされたとしても、それは数兆になることもあり、数兆になることもあります。それが多ければ、そのコード行の解釈コストを議論する意味がありません-お金は別の場所にあります。

インタプリタ言語には、コンパイルする必要がないなど、独自の価値があることに注意してください。 (サーフェス構文のバイトコードへの「コンパイル」には、簡単な時間がかかります。たとえば、RまたはMATLABを使用してください。)

また、インテリジェントなレベルのプログラミングには柔軟性が必要です。 Minskyの Society of Mind では、6.4章[〜#〜] b [〜 #〜]-頭脳、世界を扱うAプログラムがあり、Aプログラムを扱うBプログラムがあり、さらにレベルがあります。他のプログラムを作成して管理するプログラムは、解釈システムでより簡単に実行できます。

LISPでは、_(+ A B)_を記述してAとBを追加できますが、一度書き込むと、実行するかどうかしか選択できません。プログラムを作成して実行する_(eval (list '+ 'A 'B))_を記述することもできます。それは何か違うものを構築することができます。

プログラムの件名は別のプログラムです。これは、インタープリター言語で書く方が簡単です(ただし、Jörgが指摘するように、LISPの新しいバージョンはevalを備えているため、その場でコンパイルできるため、解釈の速度のペナルティはありません。 )。

7
Mike Dunlavey

それは仮定ですが、あなたの仮定は十分に確立されています。

コンパイルされたコードすべきが解釈されたコードよりも速い理由を説明するつもりはありません。コンピューターがどのように機能するかを知っていれば、それは明らかです。違いは、特定の種類の問題では桁違いの場合があります。レビュアーがその一般的なケースに真剣に異議を唱えた場合、レビュアーは自分が何について話しているのかわかりません。

ただし、開発者が開発しているアプリケーションのタイプに大きな違いがあるかどうかは重要です。ほとんどがI/Oであるか、ほとんどがコンパイル済みのライブラリを呼び出していて、計算量が少ない場合、解釈プロセスのオーバーヘッドは実際には重要ではない可能性があります。

しかし、私の投稿のポイントはこれです:I.T.エキスパートは、物事がどのように機能するかについての一般的な知識に基づいて簡単な決定を行うためにしばしば呼び出されます。特定のテストを行うと、より正確な答えが得られる可能性がありますが、コストが高くなり、最初にそこに到達することはありません。

しかし、時々あなたは引っ掛かります。それは私に起こりました。あなたは良い仮定をします、そして、あなたはあなたが世界の愚かさを考慮に入れなかったことに気づきます。

しかし、私は私の好きなディルバートの漫画と同じくらい説明することはできません。スマートアスであることの危険をこれほど上手く示すものはありません。

alt text

TL; DR:あなたは正しいはずですが、念のため実際の世界を確認してください。

5
rghome

種類、種類によって異なりますが、コンパイルされた-JITを介したものか、静的にコンパイルされたものかにかかわらず、コンパイルされた環境は、同じ言語を単純化することを前提として、多くの計算集中型タスクに対して高速になります。

その理由の1つは、インタープリター型言語にインタープリターループが必要であるということです。つまり、命令を読み取り、適切なアクションを選択して実行するループです。 PythonまたはJava bytecode(asold)を解釈するようなベストケース)いくつかの命令のオーバーヘッドがあり、ブランチプレディクターで大混乱を引き起こします-最後のものがないと、予測ミスによる大きなペナルティが予想されます。

そうは言っても、解釈された言語はだまされるかもしれない。たとえば、Matlabは行列乗算用に最適化されたルーチンを備えており、いくつかの変更を加えるだけで、GPUでコードを実行できます(免責事項:私はnVidiaで働いています-ここで表明された意見はすべて私の意見であり、雇用主の見解を表すものではありません)。そうすれば、細部を気にすることなく、短くて強力な上位レベルのコードを書くことができます。誰かがそれを気にし、低レベル言語でコードを最適化するために時間とリソースを注ぎました。それについては何も継承されておらず、たとえばMatlabからコードをJITに変換することを妨げるものではありませんが、高レベルのルーチンを呼び出すオーバーヘッドは、低レベルのルーチンで費やされる時間と比較して最小限であるため、理由はありません。

TL; DR-コンパイルされたプログラムは、解釈されたプログラムよりもパフォーマンスが大幅に向上します(りんご同士の比較については PyPy Speed を参照)。ただし、実行可能ファイルの速度は問題の一部にすぎず、全体の速度にはあまり貢献しない場合があります(ほとんどがライブラリーで時間を費やしている場合)。また、実装も重要です。

5

少し変わったものを使用しない限り、問題はインタープリター型言語Aとコンパイル型言語Bに関するパフォーマンスではありません。

あなたやあなたのチームがAではなくBを知っているので、AよりBよりも優れたコードを書くと、BよりもAではるかに優れたパフォーマンスが得られる可能性があります。1つの言語で経験した人がいて、言語/ライブラリでできることは、あなたが必要とする仕事、それに固執する。

さまざまな言語の正規表現に関するリンクは次のとおりです。コンパイルされていてもいなくても、一部の言語では正規表現がより適切に実装されていることがわかります。 http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna

3
Walfrat

2つのテクノロジーのパフォーマンスについて、一方がコンパイルされ、もう一方が解釈されるという事実だけに基づいて話をするのは、良い考えではないと思います。他の回答で述べたように、それはアプリケーションの領域(一部の言語は、一部の操作を非常に迅速に実行し、他の処理をより低速に実行するように最適化される場合があります)や、そのテクノロジを使用しようとしている人々の経験に依存する場合があります。

優れたインタープリター型言語コーダーを採用して、馴染みのないテクノロジーを提供すると、パフォーマンスが向上すると期待するのは合理的ではないと思います。理論的には、後者の方がパフォーマンスが向上するかもしれませんが、実際には、必要なスキルと経験がなければ、最適化の機会をすべて活用することはできません。

よく知られているシリコンバレーの会社の従業員の1人から、複雑で高度に最適化されたコードを維持するために熟練した開発者にお金を払うことは、効率の悪い実装に対処するために、より多くのリグを購入します。そのため、テクノロジーを選択する際には、それも考慮する必要があります。

1
KjMag

かつて、大きな決定を正当化するために、同様の抜本的な発言をしなければなりませんでした。

最初に、彼らは謙虚なエンジニアを信じたくないかもしれないので、私はいくつかの同等のベンチマークテストを見つけて引用しました。それらの多くは、マイクロソフトのような人々から、または有名な大学からです。変数XとYに応じて、メソッドAはメソッドBの3倍から10倍高速です。

次に、独自のベンチマークを実行したい場合があります。問題のコードの代表的なチャンク、またはすでに持っている類似のものを使用する場合があります。一晩1000回実行するので、測定可能な違いがあります。

この時点で、AとBの違い(またはその欠如)は非常にはっきりしているので、提示するだけで十分です。そのため、可能な場合は図を使用して結果を明確にフォーマットし、すべての仮定を述べ、使用するすべてのデータを定義します。

0
RedSonja

動的言語は静的にコンパイルされた言語よりも優れていると私は主張します:「ランタイム最適化」

これが理由の1つですJavaはC++よりも高速である可能性があります

はい、loading動的に型付けされた言語は常に翻訳コストがかかり、不利になります。しかし、いったん実行されると、インタープリターは、静的言語が決して持っていないランタイム情報を使用して、頻繁なコードパスをプロファイリングおよび強化できます。

注:まあ、Javaは動的言語ではなくインタプリタ言語ですが、ランタイム情報でスピードアップできるものの良い例です

0
SystematicFrank