4

興味深い: 最近、Java プロジェクトの 1 つで、データを 2 次元配列に格納するか、そのインスタンスを 1 次元配列に入れる専用のクラスを作成できるという状況に遭遇しました。それで、パフォーマンス(ランタイム、メモリ消費)に関して、このトピックに関する標準的な設計アドバイスがあるかどうか疑問に思いますか?

設計パターン(非常に単純化された状況)に関係なく、次のようなデータを保存できるとしましょう

class MyContainer {
  public double a;
  public double b;
  ...
}

その後

MyContainer[] myArray = new MyContainer[10000];
for(int i = myArray.length; (--i) >= 0;) {
  myArray[i] = new MyContainer();
}
...

double[][] myData = new double[10000][2];  
...

どういうわけ、配列ベースのアプローチは、よりコンパクト (メモリ) で高速 (アクセス) であるべきだと思います。繰り返しになりますが、そうではないかもしれません。配列もオブジェクトであり、配列アクセスはインデックスをチェックする必要がありますが、オブジェクト メンバー アクセスはそうではありません。(?)オブジェクト配列の割り当てには、おそらく(?)時間がかかります。インスタンスと私のコードは、追加のクラスのために大きくなります。

したがって、一般的な JVM の設計は、アクセス速度とメモリ消費の点で、一方のアプローチに対して他方のアプローチよりも優れているのでしょうか?

どうもありがとう。

4

3 に答える 3

3

繰り返しますが、そうではないかもしれません。配列もオブジェクトです

それは正しい。したがって、このアプローチでは何も得られないと思います。

そのルートをたどりたい場合は、これを 1 次元配列にフラット化できます (各「オブジェクト」は 2 つのスロットを使用します)。これにより、ポインターをたどる必要なく、すべてのオブジェクトのすべてのフィールドにすぐにアクセスできます。全体として、1 つの大きなメモリ割り当てだけで済みます。コンポーネント タイプはプリミティブであるため、メモリ割り当てに関する限り、オブジェクトは 1 つだけです (コンテナー配列自体)。

これは、 Java で構造体と値の型を持ちたいという人々の動機の 1 つであり、同様の考慮事項により、特殊な高性能データ構造ライブラリ (不要なオブジェクト ラッパーを取り除く) の開発が促進されます。

ただし、実際に巨大なデータ構造ができるまで、私はそれについて心配しません。そうして初めて、オブジェクト指向の方法のオーバーヘッドが問題になります。

于 2015-10-08T00:25:14.720 に答える
3

この状況で私が見た標準的なアドバイスは、時期尚早の最適化は諸悪の根源だというものです。これに従うということは、コードの品質体制を超えて、最も簡単に記述/保守/取得できるコードに固執し、測定可能なパフォーマンスの問題がある場合は最適化を検討する必要があることを意味します。

あなたの例では、オブジェクトの場合には10,000の参照と参照ごとに2つのダブルがあり、2D配列の場合にはそれぞれ2つのダブルを含む小さな配列への10,000の参照(最初の次元)があるため、メモリ消費は似ています。したがって、どちらも 1 つの base 参照と 10,000 の参照と 20,000 の double です。

より効率的な表現は、2 つの基本参照と 20,000 の double を持つ 2 つの配列です。

double[] a = new double[10000];
double[] b = new double[10000];
于 2015-10-08T02:56:40.393 に答える