7

インタープリターは多くの余分な作業を行うため、ネイティブのマシン コードよりも大幅に遅くなることは理解できます。しかし、C# や Java などの言語には JIT コンパイラがあり、おそらくプラットフォーム ネイティブのマシン コードにコンパイルされます。

それでも、十分に正当と思われるベンチマークによると、ほとんどの場合、C/C++ よりも 2 倍から 4 倍遅いですか? もちろん、同等に最適化された C/C++ コードと比較することを意味します。私は、JIT コンパイルの最適化の利点と、最適化が不十分な C+C++ よりも高速なコードを生成できることを十分に認識しています。

そして、Java のメモリ割り当てがどれほど優れているかについての騒ぎの後で、なぜこれほど恐ろしいメモリ使用量が発生するのでしょうか? その特定のベンチマーク スイート全体で 2 倍から 50 倍、平均で約 30 倍のメモリが使用されています。

WAR を開始したくないことに注意してください。これらのパフォーマンスと効率の数値を定義する技術的な詳細について質問しています。

4

3 に答える 3

7

違いのいくつかの理由;

  • JIT コンパイラはほとんどの場合、コンパイルが速く、見つけるのに時間がかかるいくつかの最適化をスキップします。

  • VM は多くの場合、安全性を強制するため、実行が遅くなります。たとえば、配列アクセスは、正しい範囲内で保証されない限り、.Net で常に境界チェックされます。

  • SSE の使用 (該当する場合はパフォーマンスに優れている) は、C++ では簡単ですが、現在の VM では困難です。

  • VM と比較した場合、C++ では他の側面よりもパフォーマンスが優先されます。

  • 多くの場合、VM は未使用のメモリをしばらく保持してから、OS に戻ってより多くのメモリを「使用」しているように見えます。

  • 一部の VM は、int/ulong などの値型のオブジェクトを作成します。オブジェクト メモリのオーバーヘッドを追加します。

  • 一部の VM の自動整列データ構造は、大量のメモリを浪費します (パフォーマンス向上のため)。

  • 一部の VM は boolean を int (4 バイト) として実装しており、メモリの節約にほとんど重点を置いていません。

于 2012-08-09T11:52:03.517 に答える
0

しかし、C# や Java などの言語には JIT コンパイラがあり、おそらくプラットフォーム ネイティブのマシン コードにコンパイルされます。

通訳者は、最終的に機械語に変換する必要もあります。しかし、JIT 担当者は、起動時間と実行時間を短縮するために、コンパイルと最適化に費やす労力を減らします。コンパイルに時間を浪費すると、ユーザーの観点から知覚されるパフォーマンスが低下するため、これはAoT コンパイラーのように 1 回だけ行う場合にのみ可能です。

また、コンパイル結果を監視して、ホット スポットをさらに再コンパイルおよび最適化するか、ほとんど使用されないパスを最適化解除する必要があります。そして、たまにGCを起動する必要があります。これらは、通常のコンパイル済みバイナリよりも時間がかかります。さらに、JITter と JITted プログラムのメモリ使用量が多いと、キャッシュの使用効率が低下し、パフォーマンスが低下する可能性があります。

メモリ使用量の詳細については、こちらを参照してください

次の理由により、Java のメモリ使用量は C++ のメモリ使用量よりもはるかに多くなります。

  • Java では、オブジェクトごとに 8 バイト、配列ごとに 12 バイトのオーバーヘッドがあります (32 ビット。64 ビット Java では 2 倍)。オブジェクトのサイズが 8 バイトの倍数でない場合は、次の 8 の倍数に切り上げられます。これは、1 バイト フィールドを含むオブジェクトが 16 バイトを占有し、4 バイトの参照が必要であることを意味します。C++ は、仮想関数を宣言するすべてのオブジェクトにもポインター (通常は 4 または 8 バイト) を割り当てることに注意してください。
  • Java ライブラリの一部は、プログラムの実行前にロードする必要があります (少なくとも、プログラムによって「フードの下で」使用されるクラス)。[60] これにより、小規模なアプリケーションのメモリ オーバーヘッドが大幅に増加します [要出典]。
  • 通常、Java バイナリとネイティブの再コンパイルはどちらもメモリ内にあります。
  • 仮想マシン自体が大量のメモリを消費します。
  • Java では、複合オブジェクト (B と C のインスタンスを使用するクラス A) は、B と C の割り当てられたインスタンスへの参照を使用して作成されます。C++ では、これらのタイプの参照のメモリとパフォーマンスのコストは、B のインスタンスと/または C が A 内に存在する。
  • アドレス演算の欠如により、狭い間隔の構造体や XOR リンク リストなど、メモリ効率の高いコンテナーを作成することができなくなります。

ほとんどの場合、C++ アプリケーションは、Java の仮想マシン、クラスのロード、および自動メモリ サイズ変更のオーバーヘッドが大きいため、同等の Java アプリケーションよりも少ないメモリを消費します。言語とランタイム環境を選択する際にメモリが重要な要素となるアプリケーションでは、費用対効果の分析が必要です。

また、ガベージ コレクタを使用するプログラムは、明示的なメモリ管理を使用するプログラムと同じパフォーマンスを達成するために、5 倍ものメモリを必要とする可能性があることにも注意してください。

于 2013-08-03T14:32:09.043 に答える
-1

なぜこのような恐ろしいメモリ使用量が発生するのですか? その特定のベンチマーク スイート全体で 2 倍から 50 倍、平均で約 30 倍のメモリが使用されています。

https://softwareengineering.stackexchange.com/a/189552を参照してください。

于 2016-05-26T23:19:01.083 に答える