私は、Javaのクラスとdoubleのプリミティブ型のパフォーマンスの違いが何であるかに興味を持っていました。そこで、少しベンチマークを作成したところ、クラス型がプリミティブ型よりも3倍から7倍遅いことがわかりました。 (ローカルマシンOSXでは3倍、ideoneでは7倍)
ここにテストがあります:
class Main {
public static void main(String args[]) {
long bigDTime, littleDTime;
{
long start = System.nanoTime();
Double d = 0.0;
for (Double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
bigDTime = end - start;
System.out.println(bigDTime);
}
{
long start = System.nanoTime();
double d = 0.0;
for (double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
littleDTime = end - start;
System.out.println(littleDTime);
}
System.out.println("D/d = " + (bigDTime / littleDTime));
}
}
では、なぜDouble型がそれほど遅いのでしょうか。なぜ数学演算子を許可するために実装されているのですか?
では、なぜDouble型がそれほど遅いのでしょうか。
値は、割り当て、割り当て解除、メモリ管理に加えてゲッターとセッターを必要とするオブジェクト内にラップされているため
なぜ数学演算子を許可するために実装されているのですか?
Autoboxは単純な値ではないという事実を心配せずにそのようなラッパーを使用できるようにすることを意図しているためです。 ArrayList<Double>
を使用できないようにしますか?パフォーマンスは常にではない必要であり、状況に応じて3x-7xのパフォーマンスの低下が許容される可能性があります。最適化は常に存在するとは限らない要件です。
これはすべての状況に当てはまります。ランダムアクセス要素にLinkedList
を使用するのはやり過ぎかもしれませんが、これはLinkedList
をまったく実装する必要がないという意味ではありません。これは、少数のランダムアクセスにリンクリストを使用すると、パフォーマンスが大幅に低下する可能性があることも意味しません。
最後の注記:ベンチマークの前にVMをウォームアップする必要があります。
通常、Double
、Integer
などは使用しません(「Integer
」などは、「オプション」の値を格納するのに役立ちます。null
にしたい場合があります。Double
では、NaN
を使用できるため、これはあまりありません。 )
Double
が存在する理由は次のとおりです。 Javaには、主に2つのタイプの値があります:オブジェクト(基本的には算術演算のないC/C++ポインターのような)とプリミティブ値(たとえば、double
)。ArrayList
のようなクラスは、Object
を受け入れるように定義できます。 String
、File
、または好きなものを1つに保存できますが、double
のようなプリミティブ値はそのような定義ではカバーされません。したがって、Double
のようなクラスは、ArrayList
のようなクラスがdouble
sを簡単に保存できるようにし、ArrayList
の作成者を必要としませんすべてのプリミティブタイプの特別なバージョンを作成します。
Double
はボックス化されたdouble
です。したがって、一般に、コンパイルされたコードは、何かを行う前に、Double
がnullかどうかをチェックする必要があります。もちろん、これは何もしないよりも遅いです。
Double
(およびプリミティブの他のボックス版)は、Object
であるため便利です。これにより、Object
を受け取る関数に渡し、Double
にキャストし直すことができます。さらに便利なことに、ジェネリック型にそれを含めることができます。ジェネリック型にはdouble
または他のプリミティブを含めることはできませんが、Double
を含めることはできます。