2017-08-03 27 views
2

Java中的UUIDs像Strings一樣被執行嗎?如果沒有,我是否應該嘗試回收UUID對象以儘量減少RAM使用量?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)I沒有看到任何嘗試尋找已有的等價UUID。每個實例的狀態也很少。 –

+0

據我所知,Strings在這方面對Java有着特殊的處理。無論/如何緩存可能取決於實現(ORM,jdbc驅動程序等),我懷疑有些人會那樣做,但我不會認爲這是真的。 – Luke

回答

4

快速查看java runtime source code可以看出UUID未被攔截。

如果你要遍歷一個大型的數據庫,UUID實習可能會導致JVM運行內存不足,因爲永遠不會預先給出它所看到的任何UUID。

而且,沒有太多的好處實習的UUID,因爲

  • 他們不佔用太多空間

  • (存儲爲一對 long基本上只是UUID的128位值)
  • 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是一個包含兩個long變量的對象。在64位JVM中,這將佔用32個字節。如果您共享UUID,那麼您只需支付32個字節一次,然後僅支付8個字節作爲參考。如果使用compressed pointers,則引用將適合4個字節。

這個收益是否足夠重要?這取決於你的具體應用。一般來說,我不會共享一個UUID。然而,我曾經在一個應用程序上工作,在那裏共享UUID確實是一個改進。減少內存使用量是至關重要的,從完整的對象減少到參考是一個改進。

話雖如此,這種類型的優化是很少需要的。作爲一個經驗法則,我只會在UUID被大量共享的時候這樣做,並且不惜一切代價減少內存。否則,對它們進行重複數據刪除的CPU開銷以及代碼中的額外複雜性通常是不值得的,或者更糟的是,甚至可能會減慢應用程序的運行速度。

如果您決定對它們進行重複數據刪除,那麼您將如何做?沒有像String#intern這樣的內置功能,但您可以手動創建映射到重複數據刪除。根據您想要在當前函數調用中全局刪除重複項還是僅在本地進行重複項刪除,可以使用ConcurrentHashMap或簡單地使用(非同步)HashMap


作爲一個側面說明,不直接關係到你的問題,我提到String#intern,因爲它是字符串API的一部分。不過,我強烈建議不要使用它,因爲它是a huge performance bottleneck。自己執行重複數據刪除將顯着加快。