ロックとしてのオブジェクトとバイト[0]の比較
-
22-09-2019 - |
質問
先ほどコメントさせていただきました この質問 (「なぜ java.lang.Object は抽象的ではないのですか?」) を使用すると聞いたことがあると述べています。 byte[0]
ロックを使用するよりもわずかに効率的だったため、 java.lang.Object
. 。これをどこかで読んだはずですが、どこで読んだのか思い出せません:これが実際に真実かどうか知っている人はいますか?
インスタンス化が原因だと思われます byte[0]
必要なバイトコードがわずかに少なくなります Object
, と指摘されましたが、 byte[0]
長さフィールドを保存するために追加のストレージが必要なため、利点が損なわれる可能性があるように思えます。
解決
私はそれをテストするための好奇心は十分です。ソースコードます:
public class Test {
public static Object returnObject() {
return new Object();
}
public static byte[] returnArray(){
return new byte[0];
}
}
バイトコードます:
public static java.lang.Object returnObject();
Code:
0: new #2; //class java/lang/Object
3: dup
4: invokespecial #1; //Method java/lang/Object."<init>":()V
7: areturn
public static byte[] returnArray();
Code:
0: iconst_0
1: newarray byte
3: areturn
アレイの作成は、独自のJVMオペコードを持っているので、バイトコードは、配列のために短いことで、あなたので、している権利。しかし、それはどういう意味?何も、本当に。これは、仮想マシンですので、少ないバイトコード命令は、実際の物理的なCPUのための少ない作業を意味するという保証は全くありません。私たちは、もちろんプロファイリング開始することができ、それはかなり無意味になります。すべての差異がある場合は、関係なく、どの方法、それは今までにも問題はありません。オブジェクトの作成は、信じられないほど速く、今日です。あなたはおそらく、あなたも合計時間を測定することができます前に、あなたのループインデックス用のlong
の使用を開始する必要があると思います。
他のヒント
のサイズを確認するためにjava.lang.instrument.Instrumentationの使用:
オブジェクトは8つのバイトを使用し、バイト[0]は16バイトを必要とします。 (サイズはバイト単位でないことを確認場合は、文書化されていません)。
私はまた、オブジェクトやバイトを作成するための時間[0](2回)を得た:オブジェクトが勝者です。
(すべてのテストがDELLのノートPC、インテルの2GHz、Windos XP上で実行)
client
を使用してVM
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode)
an implementation-specific approximation of the amount of storage
Object = 8
byte[0] = 16
time to create 1000000000 instances
Object: elapsed=11,140 cpu=9,766 user=9,703 [seconds]
byte[0]: elapsed=18,248 cpu=15,672 user=15,594 [seconds]
time to create 1000000000 instances
Object: elapsed=11,135 cpu=9,828 user=9,750 [seconds]
byte[0]: elapsed=18,271 cpu=15,547 user=15,469 [seconds]
server
を使用してVM
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)
an implementation-specific approximation of the amount of storage
Object = 8
byte[0] = 16
time to create 1000000000 instances
Object: elapsed=8,441 cpu=7,156 user=7,125 [seconds]
byte[0]: elapsed=11,237 cpu=8,609 user=8,500 [seconds]
time to create 1000000000 instances
Object: elapsed=8,501 cpu=7,234 user=7,156 [seconds]
byte[0]: elapsed=11,023 cpu=8,688 user=8,641 [seconds]
私は、new Object()
に滞在するためだけでなく、読みやすさの:-)
コード
public class ObjectArrayCompare {
private static Object o;
public static void main(String[] args) {
Instrumentation instr = InstrumentationAgent.getInstrumentation();
if (instr == null) {
System.err.println("No Instrumentation, use \"-javaagent:Instrumentation.jar\"");
return;
}
System.out.println();
System.out.println("an implementation-specific approximation of the amount of storage");
System.out.println("Object = " + instr.getObjectSize(new Object()));
System.out.println("byte[0] = " + instr.getObjectSize(new byte[0]));
System.out.println();
final int MAX = (int) 1.0e9;
Timer timer;
Times times;
for (int j = 0; j < 2; j++) {
System.out.println("time to create " + MAX + " instances");
timer = new Timer();
for (int i = 0; i < MAX; i++) {
o = new Object();
}
times = timer.times();
System.out.println("Object: " + times);
timer = new Timer();
for (int i = 0; i < MAX; i++) {
o = new byte[0];
}
times = timer.times();
System.out.println("byte[0]: " + times);
System.out.println();
}
}
}
タイマー * 用途は時間を得るためにThreadMXBean
ます。
* のタイマーが、それは私がtimmingのために作られたクラスですの のないJavaのTimerの。が
の1によると、 Java言語仕様で、「すべてのクラスと配列種類は、私はバイト[0]は、より効率的に管理できる方法がわからないので、「クラスのオブジェクトのメソッドを継承します。
最初のために真であるように思われる。同様に仕様する
の版:「アレイ型のスーパークラスがオブジェクトであると考えられている」は、配列を使用することで、読者の私見を混乱させる可能性が高いです。
以下のオブジェクトを作成することが今までそれが重要だっいることを十分にオブジェクトを作成しましたのであれば、あなたはあまりにも多くを作成している、より多くの作成よりも効率的です。
はロックオブジェクトとしてJavaで空の配列を使用してのパターンは、パフォーマンスとはほとんどされています。
空の配列(偶数new Object[0]
)は、シリアライズ可能であるため好ましいです。 new Object()
を使用することにより、自動シリアライズを放棄しています。
私は(パフォーマンスを気にしません)やってに慣れます:
private final Object lock = new Object[0];
プリミティブ配列はので、多分new byte[0]
は、「より良い」だろう、作成するために、より少ないバイトコードを取ります。
を参照してください:?それがシリアライズ可能クラスのロック・トランジェントを作るために大丈夫ですの
あなたの質問には「効率」について言及されていますが、どのような効率を求めているのかは述べられていません。これまでの答えは、 サイズ ただし、どちらの表現でも参照解除と組み込みロックの使用の実行時コストは同じである必要があります。
組み込みロックを使用する場合と、組み込みロックを使用する場合のオーバーヘッドを比較することもできます。 java.util.concurrent.locks.ReentrantLock
明示的に、または自分でその上に書いたもの AbstractQueuedSynchronizer
. 。個別に割り当てられたオブジェクトへの追加参照を許容できるかどうかを評価するには、問題についてより詳細な情報が必要ですが、すでに検討していることを考えると、 byte
配列の場合は、配列とは異なる組み込みロックの使用を検討する必要があります。 this
参照。