2012-09-01 7 views
8

私はJavaからC++への特定のデータ処理アルゴリズムを移植しています。コードを書き直す理由は移植性です。Javaが利用できない環境で実行する必要があります。しかし、副次的なメリットとして、パフォーマンスの向上が期待されていました。Javaの.getClass()はどれくらいの費用がかかりますか?

基本的に、アルゴリズムは、相互にポインタを持つオブジェクトで構成されたグラフからデータを読み取り、結果を計算します。計算中に多数のオブジェクトの割り当てが行われるため、おそらくこれが減速の原因となります。つまり、C++コードは現在のところ、古いJavaコードより約10倍高速です。これは本当に予想外でした。私は50-60%の改善が見られると思っていました。

残念ながら、私は分析のためにここにコードを掲載する自由はありません。とにかく便利だとは思えません。

ところで、アルゴリズムはほぼ同じです。私が考えることができる唯一の大きな違いは、Javaでは単一のスーパークラスの多くの娘クラスがあり、if(object.getClass()== daughterx.class)が計算中に何度も呼び出されるのに対し、C++コードでは一般クラスが使用されます(娘クラス間のコードの違いが少ないため)。単純な整数比較が使用されます。 if(object-> type == 15)

JavaのObject.getClass()メソッドの高さはどれくらいですか?このメソッドが呼び出されたときに、低レベルで正確には何が起きていますか?

+5

倍に向上しましたどちらもないのJavaを理解していない他の人のいずれかであります! ;) – cheeken

+0

@cheekenそれはJVMに依存しますが、JITがなければ、JavaはPythonよりも遅いと思います。 –

+3

正直なところ、これは問題ではないようです。推奨されていないコードをベンチマークしプロファイリングするのは貴重な時間ですか?あなたがそれをしない限り、 '.getClass()'がボトルネックであることを知る方法はありません。推測は、アルゴリズムの全体的な複雑さを大幅に減らすことができない(つまり、N-squared操作からlog-N操作に移行する)ことができ、データセットが非常に大きい場合を除き、パフォーマンスの問題をデバッグするのに役立ちません。 –

答えて

7

10倍の違いの最も一般的なケースは、JVMが完全にウォームアップされなかったことです。これをしないと、Javaでさえも10倍以上のパフォーマンスの違いが見えます。私は10,000のバッチで実行しようとし、最初のいくつかの実行を無視します。

public static void main(String... args) throws IOException { 
    timeObjectGraph("First run", 1); 
    timeObjectGraph("Second run", 2); 
    timeObjectGraph("Next thousand", 1000); 
    for (int i = 0; i < 5; i++) 
     timeObjectGraph("Next ten thousand", 10000); 
} 

static int dontOptimiseAway = 0; 

public static void timeObjectGraph(String desc, int runs) throws IOException { 
    long start = System.nanoTime(); 
    for (int i = 0; i < runs; i++) { 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     ObjectOutputStream oos = new ObjectOutputStream(out); 
     oos.writeObject(Calendar.getInstance()); 
     oos.close(); 
     dontOptimiseAway = out.toByteArray().length; 
    } 
    long time = System.nanoTime() - start; 
    System.out.printf("%s took an avg time of %,d ns%n", desc, time/runs); 
} 

プリント

最後の実行に最初から
First run took an avg time of 37,509,488 ns 
Second run took an avg time of 439,054 ns 
Next thousand took an avg time of 185,242 ns 
Next ten thousand took an avg time of 41,698 ns 
Next ten thousand took an avg time of 19,981 ns 
Next ten thousand took an avg time of 11,541 ns 
Next ten thousand took an avg time of 13,451 ns 
Next ten thousand took an avg time of 11,289 ns 

は、パフォーマンスがxlc0212 @ 3000X

+0

なぜCalendar.getInstance()を使用していますか?まず、getClassメソッドに関する質問です。 2番目のカレンダーは作成するには重い**クラスなので、Calendar.getInstance()**はそれ自体で高価です**、getClassが内部で呼び出されるわけではありません。私はこの例が正しいとは思わないか、より明確なコメントを与えるべきです。 – Cherry

+2

@Cherry私はCalendarとObjectOutputStreamを使用しましたが、これは短いコードではどちらも高価です。これはコードの大部分に対してウォームアップの違いがどれほどのものかを現実的に示しています。 –

5

パフォーマンスの違いは唯一の要因ではありません。残念ながら、あなたのコードが実際に行っていることをはるかに完全に把握することなく、何が起きているのかを伝えるのは本当に難しいでしょう。

私の経験では、JavaはC++よりも10倍遅くする必要はありません。私はおそらくプロファイラから始めて、推測するのではなく、問題を理解するためにどこが指しているのかを見ていきます。

11

JavaのObject.getClass()メソッドはどれくらいの費用がかかりますか?

それは非主流のJVMに実装されているかの私の知識に基づいて、このメソッドが呼び出されたときに、低レベルで起こっている正確に何

安いのですか?典型的

...

  1. 、オブジェクトのヘッダからクラスインデックス(2つのまたは3命令)
  2. ルックアップクラスインデックスからクラスのディスクリプタ(2つのまたは3命令)
  3. を抽出クラス記述子からClassオブジェクト参照をフェッチして返します(2または3命令)

事実、C++コードは現在、古いJavaコードよりも約10倍高速です。

私はパフォーマンスのボトルネックが他の場所にあると思います。 Javaコードをプロファイリングしてから、なぜそれが遅いのかについての結論にジャンプする必要があります。

+6

+1ルックアップ自体は安いですが、 'if(getClass()== SomeClass.class)のシーケンスを持っていると、意義深い設計とパフォーマンスの問題が発生します。'これは、OOデザインをもっと必要とするか、これらのクラスを組み合わせて、機能のためにスイッチなどを使用することができます。 –

関連する問題