2017-08-03 3 views
2

UUIDsはJavaの文字列のように使用できますか?そうでない場合は、RAM使用量を最小限に抑えるためにUUIDオブジェクトをリサイクルする必要がありますか?java.util.UUIDインターンシップ/リサイクル

データベースプライマリキー&の外部キー列のデータ型としてUUIDを使用します。これは、共有外部キー値のUUIDの使用を繰り返している多くの行を意味します。

データベースから行を取得する場合、各UUIDが重複しているかどうかを確認し、重複している場合は元のオブジェクト参照を使用するかどうかを確認する必要がありますか?または、これは私のためにすでに行われていますか?Strings are internedと同様ですか?

… // common JDBC code 
UUID id = null ; 
while (rs.next()) { 
    UUID idFresh = rs.getObject(1); 
    // Recycle the UUID object where possible. 
    id = ((null == id) || idFresh.equals(id)) ? idFresh : id ; // If null or identical, use the existing object reference. 
    String name = rs.getString(2); 
} 
… 
+1

実際にプログラムでRAMの使用が問題になっていますか? – bcsb1001

+0

[grepcodeのソースコード](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/UUID.java#UUID)を見るとすでに存在する同等のUUIDを探す試みは何も見ないでください。インスタンスあたりの状態もほとんどありません。 –

+0

私が知っていることから、StringsはJavaで特別な扱いをしています。そして、何かがキャッシュされているかどうかは、おそらく(ORM、jdbcドライバなどの)実装に依存するでしょうが、それはいくつかの疑いがありますが、すべてのことが正しいとは思わないでしょう。 – Luke

答えて

4

java runtime source codeを見ると、UUIDは受け入れられていないことがわかります。

大規模なデータベースをトラバースする場合、UUIDインターンシングを実行すると、見たUUIDを絶対に上回らないため、JVMがメモリ不足になる可能性があるため、それらをインターンするのは悪い考えです。

彼らは多くのスペース
longのペアとして保存され、基本的にはUUIDの128ビット値)

を占有しない

  • のでまた、UUIDをインターンに多くの利点が、そこではありません

  • UUIDの比較とハッシュコードの計算は安いです。
    Stringインターンの最大の利点の一つは、文字列のハッシュコードは、その計算が少し高価なことができますので、関心のビットである、一度だけ計算されることをである。)

1

のUUID(とも文字列)は自動的に重複排除されません。新しく作成されたUUIDはユニークでなければならないので、一般的には悪い考えです。共有は機能しません。

あなたがインターンの文字列を参照する場合は、JVMは、例えば、特定の場合には、文字列を共有することは事実である:

String x = "ab"; 
String y = "a" + "b"; 
assert x == y; // references are identical (x and y are shared) 

これらは文字列である、しかし、コンパイル時に解決することができます。実行時に文字列またはUUIDを作成すると、常に新しいオブジェクトが作成されます。

あなたの質問では、別のシナリオを説明します。ここでは、データベースからUUIDを読み込みます。データに依存して、UUIDを共有する良い機会があるかもしれないし、存在しないかもしれない(例えば、UUIDが主キーとして使用されている場合)。

id | name | country 
1 | A  | <UUID-1> 
2 | B  | <UUID-1> 
3 | C  | <UUID-2> 
4 | D  | <UUID-1> 
5 | E  | <UUID-1> 

(一般的には、あなたが同じ値のコピーを受け取ります。データベースまたはネットワークからUUIDを読むとき、あなたはのUUIDが重複除外されると仮定することができないことに注意してください。)

したがって、あなたのデータが上記のように見える場合、UUIDの共有は理にかなっています。しかし、それはメモリの使用量を減らすでしょうか?

UUIDは、2つのlong変数を持つオブジェクトです。 64ビットJVMでは、32バイトを要します。あなたがUUIDを共有している場合は、一度32バイトを支払うだけで、その後は8バイトしか支払われません。 compressed pointersを使用すると、参照は4バイトに収まります。

このゲインは十分ですか?それはあなたの特定のアプリケーションに依存します。一般的に、私はUUIDを共有しません。しかし、私はUUIDの共有が本当に改善されたアプリケーションに取り組んできました。メモリ使用量を削減することは重要であり、完全なオブジェクトから参照への削減は改善されました。

このように言えば、この種の最適化はめったに必要ありません。大雑把に言えば、UUIDが大量に共有され、すべてのコストでメモリを削減する必要がある場合にのみ、私はそれを実行します。さもなければ、それらを重複排除するCPUのオーバーヘッドとコードの余分な複雑さはしばしばそれに値するものではなく、悪い場合にはアプリケーションの速度を低下させる可能性があります。

重複排除する場合はどうすればよいですか? String#internのような組み込み関数はありませんが、重複排除するマップを手動で作成できます。グローバルに重複排除するか現在の関数呼び出しでローカルにのみ重複排除するかによって、ConcurrentHashMapまたは単に(非同期の)HashMapを使用できます。あなたの質問に直接関連サイドノート、ないよう


それは文字列のAPIの一部であるとして、私はString#internを述べました。しかし、それを使用することを強くお勧めします。それはa huge performance bottleneckです。重複排除を自分で行うことは、大幅に高速になります。

関連する問題