web-dev-qa-db-ja.com

JavaランタイムパフォーマンスとネイティブC / C ++コードの違いは?

Javaの方がC++やCよりもプログラミングが快適になりました。同じことを実行するのではなく、JVMインタープリターを使用して発生したパフォーマンスヒットの感覚を得たいと思っています。私はここにある程度の主観性があることを理解しています。プログラムの品質は適切な実装に大きく依存します。一般的な意味で以下の側面に興味があります。

  • インタープリターを使用する場合、オーバーヘッドのベースラインが必要です。覚えておくべき一般的な経験則はありますか? 10%15%? (私はこれらの数を薄い空気から引き出しました)Javaコードはネイティブコードとほぼ同じ速さですが、偏った可能性があると私は時々ブログを読みました。

  • JVMガベージコレクターはランタイムパフォーマンスに大きなオーバーヘッドを追加しますか? Cocoaアプリケーションがガベージコレクションモデルを使用し始めたことを知っています。これにより、プログラミングが大幅に簡素化されることに同意しますが、どのようなコストがかかりますか?

  • Javaからシステムコールを行う際のオーバーヘッドはどのくらいですか?たとえば、CソケットAPIではなくSocketオブジェクトを作成します。

  • 最後に、JVM実装がシングルスレッドであることをどこかで読んだことを思い出します。これが真実である場合(私はそれについて懐疑的です)、それはJavaスレッドは実際には真のスレッドではないということですか?Javaスレッド、一般的に、基になるカーネル提供スレッドに対応しますか?Javaアプリケーションは、ネイティブアプリケーションが複数のコア/複数のCPUから得られるのと同じ方法でメリットがありますか?

JVMの複雑さと、Javaプログラムのパフォーマンス)を理解している開発者からのアドバイスは、大歓迎です。

40
D.C.

Javaはインタプリタ言語ではなく、いくつかのバージョンでは使用されていません。 JavaバイトコードはオンザフライでJIT化されます(技術的にはコードの一部を解釈しますが、パフォーマンスに関して重要なものはすべてJIT化されます)

パフォーマンスに関して、地球上で「オーバーヘッドのベースラインがある」というおかしなアイデアを教えてください。ありません。かつてなかったし、今後もないだろう。 C++とJavaの間ではなく、PythonとJavascript、またはany他の2つの言語の間ではありません。特定のバージョンのJVMは、特定のC++コンパイラ、および特定のC++コンパイラが特定のJVMよりも優れていること。

したがって、選択した言語の「オーバーヘッド」は、1)コードに何を実行させたいか、および2)コードの記述方法に完全に依存します。

Javaプログラムを使用してそれをC++に変換すると、結果はほぼ確実に遅くなります。

C++プログラムをJavaに変換すると、実行速度も遅くなります。

ある言語が他の言語よりも「速い」のではなく、元のプログラムが1つの言語用に作成され、その言語でうまく機能するように調整されているためです。そして、それを別の言語に翻訳しようとすると、この利点が失われます。 C++スタイルのJavaプログラムはJVMで効率的に実行されないか、JavaスタイルのC++プログラムは非常にとして実行されます。上手。

どちらの言語仕様にも「結果は言語yより少なくともx%遅くなる必要がある」という条項は含まれていません。 C++コンパイラとJVMの両方が、物事を高速化するために最善を尽くします。

そして、今日見ているパフォーマンス特性は、明日変わるかもしれません。言語にはスピードがありません。

しかし、特定の質問に答えるには:

インタープリターを使用する場合、オーバーヘッドのベースラインが必要です。覚えておくべき一般的な経験則はありますか? 10%15%? Javaコードはネイティブコードとほぼ同じ速さであると述べていましたが、バイアスがかけられている可能性があることを述べたブログを時々読んだことがあります。

上記のように、それは依存します。多くの一般的なタスクでは、通常、どちらの方法でも数パーセントを超える違いは見られません。いくつかのユースケースでは、より大きな違いが見られます(どちらの方向に進んでも。パフォーマンスに関しては、どちらの言語にも利点があります。JVMに関連するオーバーヘッドがいくつかありますが、最適化の機会が非常に大きく、ガベージコレクターも重要です)

JVMガベージコレクターはランタイムパフォーマンスに大きなオーバーヘッドを追加しますか? Cocoaアプリケーションがガベージコレクションモデルを使用し始めたことを知っています。これにより、プログラミングが大幅に簡素化されることに同意しますが、どのようなコストがかかりますか?

基本的になし。ガベージコレクターは、多くの理由で、平均して、手動のメモリ管理よりもはるかに速いです。

  • マネージヒープでは、動的割り当てをはるかに高速に実行できます。
  • 共有所有権はごくわずかな償却費で処理できますが、母国語では参照カウントを使用する必要があるため、非常に高価です。
  • 場合によっては、オブジェクトの破棄も大幅に簡略化されます(ほとんどのJavaオブジェクトは、メモリブロックをGCするだけで回収できます。C++では、デストラクタはalwaysを実行する必要があります、そしてほぼすべてのオブジェクトに1つあります)

GCの主な問題は、平均してガベージコレクターのパフォーマンスは向上しますが、パフォーマンスコストを取るためにwhenをある程度制御できなくなることです。手動のメモリ管理により、メモリがクリーンアップされるのを待つ間、スレッドが停止することがなくなります。ガベージコレクターは、ほとんどいつでも、プロセスを一時停止してメモリをクリーンアップすることを決定できます。ほとんどの場合、これは問題なく十分な速さですが、重要なリアルタイムのものには問題です。

(もう1つの問題は、表現力が少し失われることです。C++では、RAIIを使用してあらゆる種類のリソースを管理します。Javaでは、RAIIを使用できません。代わりに、GCがメモリを処理し、他のすべてのリソースは、あなたはめちゃくちゃで、たくさんのtry/finallyブロックを使って自分でやらなければなりません。RAIIがGCされた言語で実装できなかった理由はありませんが、どちらもJavaまたはC#)

Javaからシステムコールを行う際のオーバーヘッドはどのくらいですか?たとえば、CソケットAPIではなくSocketオブジェクトを作成します。

ほぼ同じです。なぜ違うのでしょうか?もちろん、Javaは関連するOSサービスとAPIを呼び出す必要があるため、わずかなオーバーヘッドがありますが、実際には気づかない可能性があります。

最後に、JVM実装がシングルスレッドであることをどこかで読んだことを思い出します。これが真実である場合(私はそれについて懐疑的です)、それはJavaスレッドは実際には真のスレッドではないということですか?Javaスレッド、一般的に、基になるカーネル提供スレッドに対応しますか?Javaアプリケーションは、ネイティブアプリケーションが複数のコア/複数のCPUから得られるのと同じ方法でメリットがありますか?

はい、Javaは複数のスレッドを使用できます。 JVM それ自体はシングルスレッド化されている可能性があり(すべてのJVMサービスが同じスレッドで実行されるという意味で)、それについては知りません。しかし、あなたのJava applicationは好きなだけ多くのスレッドを使用でき、それらはOSスレッドにマップされ、複数のコアを使用します。

53
jalf

詳細な比較については、 ここ を参照してください。

17
Adeel Ansari

Javaとc#(およびObjective-C)はネイティブコードほど高速ではありませんが、エンジニアリング時間に制限がない問題がある場合にのみ問題になります。高級言語でより良いアルゴリズムを考案する時間があるでしょう。

したがって、基本的には、年間100万台を構築する予定のデバイスを開発している場合、またはバッテリー駆動のデバイスである場合、Javaまたはc#を使用してコアを構築することはありません。ただし、カスタマイズを容易にするためにLISPインタープリターを追加することもできます。Microsoftは、パフォーマンスが本当に重要であるSQLサーバーのコアなどにc#を使用しません。一方、Visual Studioでは、MSがユーザーに高いパフォーマンスを期待できます。エンドのハードウェア。遅いが生産性の高いテクノロジーのショーケースとして使用できます。

私は現在、プログラミングの大部分をPharo Smalltalkで行っています。これは、Java、c#、またはObjective-Cよりもはるかに遅く、最速のSmalltalkの1つでもありません。生産性はパフォーマンスよりも優れています。

5

各ポイントに対処するには:

  • 解釈コードのオーバーヘッドは10-15%よりはるかに高くなります(私は3x-5x以上で推測します)。 10-15%に下げるには、なんらかの形式のマシンコードコンパイルステップ(つまり、JIT)を使用する必要があります。 (JITをオフにしてJVMを実行してみてください。パフォーマンスの低下が見られます。)
  • ガベージコレクションはパフォーマンスに影響を与えますが、それだけの価値があると誰もが同意するでしょう。バイトコードのコンパイル/解釈のオーバーヘッドを許容できるのであれば、GCのオーバーヘッドも許容できます。
  • ソケットプログラミングは、C/C++よりもJavaの方がはるかに簡単です。パフォーマンス面では、ソケットI/OオーバーヘッドがJava実行オーバーヘッドよりも支配的です。
  • 最新のJVMには真のスレッドがあります。つまり、各Javaスレッドはカーネルスレッドによって実行されるため、Javaスレッドは最新のマルチコアCPUを利用できます。
2
JesperE

多くの人がJavaのパフォーマンスを過小評価しています。私もかつてこれに興味があり、Javaで簡単なプログラムを書いた後、同等のプログラムをcで作成しました(forループと大規模な配列で操作を実行する以上のものはありません)。私は正確な数字を思い出しませんが、cプログラムが最適化フラグ(gccの下)でコンパイルされなかった場合、Javaはcを打ち負かしました。予想通り、積極的な最適化を行って最終的にコンパイルしたとき、cは先行しました。正直なところ、それは決して科学的な実験ではありませんでしたが、Javaがどこにあるのかを知るための基準を私に与えました。

もちろん、Javaは、システムコールを必要とする処理を開始すると、おそらくさらに遅れます。しかし、控えめなハードウェアでJavaプログラムが実行されているディスクとネットワークで100MB/sの読み取りパフォーマンスを確認しました。それが正確に何を言っているのかはわかりませんが、それは私がそれを必要とするほとんどすべてのものに対して十分であるということを私に示しています。

スレッドについては、Javaプログラムが2つのスレッドを作成する場合、2つのrealスレッドがあります。

2
exabytes18
1
Bozho

実際、a VMは、実行時にのみ利用できる情報に基づいて、C/C++コンパイラが実行できない多くの最適化を実行時に実行できます。したがって、ほとんどの状況で、JVMは少なくともネイティブプログラムと同じくらい高速です。

ブライアンゲッツは、講演のすべての質問ではないにしても、ほとんどの質問に答えてくれます ユニバーサルVMに向けて

1
jqno

注意すべき重要なことは

JavaバイトコードJITをコンパイル特定のハードウェアに固有のはるかに最適化されたコード

一般的なハードウェアにコンパイルおよび最適化されたCコード特定のハードウェアが提供する機能を利用することはできません

0
Xinus

これに対する簡単な答えはありません。 CスタイルのC++を書くことは可能ですが(良いアイディアでさえ)、Cで継承を行おうとすると、状況は醜くなります。したがって、Cを無視してJava -vs- C++を使用してください。

それを実際に理解するには、2つの比較的大きなアプリケーションを両方の言語で同様の方法で作成する必要があります。その場合、STLとJava=コレクションクラスを使用しますか、それとも独自のクラスを作成して言語間で移植しますか?ネイティブクラスを使用する場合、どちらの実装がより速いかによって異なりますまるで自分のものを使用するかのように、アプリケーションの実際の速度をテストしていません。

私はあなたがアプリケーションをできるだけ似たものにする必要があると思いますが、それが意味のある場所で言語固有のライブラリ/イディオムを使用します。 C++とJavaコードは、似ていますが、物事の実行方法が異なります。Javaで簡単に実行できるコードは、C++では非常に難しく、その逆も同様です。

最新のGC実装ではオーバーヘッドはそれほど追加されません。必要に応じて C++のGC に切り替えて比較を行うことができます:-)

Javaランタイムが実行できることには、仮想メソッドをインライン化する機能など、C++コンパイラでは一般的に実行されないことがいくつかあります。

システムタイプの場合Javaは通常、Cへの呼び出しに依存しているため、オーバーヘッドが発生します(JNIは以前より高速ですが)。

スレッド化は実装に依存します。 Sunはかつて「グリーンスレッドを使用していました。Solarisの場合、それはもうありません。私が知る限り、ほとんどすべての(すべての)VMはネイティブスレッドを使用しています。

要するに、Java -vs- C++のオーバーヘッド%に関する適切な測定基準はないと思います。実際の世界を表していないマイクロベンチマークである可能性があります。 (残念ながら)。

0
TofuBeer

あなたの目的は非常に控えめなので「パフォーマンスヒットの感触を得たいと思っています...」表示されているプログラムと測定値を調べることで、ほとんどのことを達成できるはずです。 コンピュータ言語ベンチマークゲーム

ご存知のとおり、JavaとC++の両方

しかし、あなたは考える必要がありますについて 小さなプログラムの測定値がyourアプリケーション

0
igouy