1. 程式人生 > >AJPFX總結OpenJDK 和 HashMap大量數據處理時,避免垃圾回收延遲的技巧一

AJPFX總結OpenJDK 和 HashMap大量數據處理時,避免垃圾回收延遲的技巧一

col 使用 標準化 存儲 管理 困難 spa 標準 經驗

從Java 6開始,要求標準化非堆存儲(off-heap)作為Java內部API的提議就已經在JDK強化提案(JEP)中被提出。這種方式的處理能力和堆存儲(on-heap)一樣高效,並且沒有堆存儲使用中的一些局限問題。堆存儲在百萬數量級瞬時使用的對象/值下工作的相當好,但是一旦你試圖存儲十億數量級的對象/值時,你就要想辦法去避免垃圾回收帶來的持續增加的延遲。並且有時系統會要求同時保證大量數據處理和低延遲。非堆存儲就是有這樣一種能力:獨立管理內存空間而不產生垃圾回收壓力。Java中管理集合的兩個類”Queue“和"HashMap"使用起來相當方便,如果使用這兩個已有接口再加上我們自己的垃圾回收機制實現起來應該不是很難。這樣既能實現大量數據存儲並且能大大減少延遲,相比而言,原有的堆存儲方式很容易產生內存不足錯誤,隨之就要重啟服務了。



這篇文章將會研究 JEP所帶來的影響,將使得我們獲悉類似於Java HashMap和新的off-heap的性能。簡言之,JEP可能就有“指導”HashMap這個可愛的老家夥的一些新特性的魔法。 JEP所述的特性,在OpenJDK的發布來看,相對於傳統的Java平臺優先級做了許多重大的改變。 1、關於安全性的重構,這一sun.misc.Unsafe上的有用的部分,被放入了 新的API包
2、提倡使用新的API包,直接影響高性能的本地內存操作(在off-heap上的本地內存操作對象上)。
3、(通過新的API)提供一個 外部函數接口(FFI)橋 針對Java直接操作系統資源和系統調用。
4、許可了Java運行時能輔助 硬件事務性內存(Hardware Transactional Memory)的提供者能把焦點集中在重寫低並發字節碼到高並發的 speculatively branched機器碼。
5、移除了FUD(坦率的講這是一種技術偏見),這與使用off-heap編程策略來提升Java的執行性能有關。總的來講,JEP有幾點是很清楚的,在OpenJDK平臺上,相對於曾經的 dark craft, secret society of off-heap practitioners,現在的主流對開放是擁抱的。

本文力求(用普遍而溫和的方式)讓所有對此感興趣的 Java 開發者都能有所收獲。作者希望即使新手也能跟上本文節奏,而不會有看不懂的“磕磕絆絆”;因此不要氣餒,耐心坐下來讀完吧。本文努力介紹一些歷史背景,為以下問題提供思路:
  • 堆存儲 HashMap 的問題是怎麽產生的?
  • 在解決這個問題上面,有過哪些經驗/教訓?
  • 在堆存儲 HashMap 的應用情景中,有哪些仍未解決的問題?
  • 新的 JEP 提供的功能(將 HashMap 非堆存儲)能帶來哪些好處?
  • 未來的 JEP 在解決現在尚未解決的問題上面,有哪些值得期待之處?
那就讓我們一起開始這段旅程吧。值得記住的是,在 Java 出現之前,hash 表是實現在原生內存堆中的,如C 和 C++ 都是如此。某種意義上來說,重新引入非堆存儲是重新介紹一些古老的技巧,這些技巧當代的開發者往往不曾了解。各種意義上來說,這都是一次“回到未來”的旅程。旅途愉快!


OpenJDK的非堆存儲(Off-Heap)的強化提案(JEP)

已經有一些非堆存儲(Off-Heap)的強化提案(JEP)被提出來。下面描繪了一個提供非堆存儲(Off-Heap)內存的最低要求。方案試圖替代現在sun.misc.Unsafe所提供的內容,不僅如此,這些方案還提供了另外一些有用的功能。
提案總結:總的來說就是為sun.misc.Unsafe創建了一個替代的部分,這樣就可以不用直接使用那個庫。
直接目標:移除需要直接訪問的內部類。
間接目標:不提供那些不推薦的方法,也不實現那些不安全(Unsafe)的方法。
成功標準:提供一種方式去實現那些重要的功能,並且達到與那些不安全(Unsafe)和 FileDispatcherImpl的方式一樣的性能。
提案動機:當前不安全(Unsafe)的方式就意味著就需要構建更大的,線程上更安全的非堆存儲(Off-Heap)結構。這對於最小化垃圾處理器(GC)的開銷有益。這對於在進程和內嵌數據庫之間的內存共享可以不用C語言和JNI,這也就有可能提供更快更多的移動計算性能。當前的FileDispatcherImpl方式用於實現任意大小內存的映射。(標準API被限制在2GB以內。)



描述:為非堆存儲(off-heap)提供一個包裝類(類似於 ByteBuffer) ,還需要下面的增強。
  • 64位的大小和偏移量
  • 對於易失(volatile)的和有序的訪問以及比較和交換的操作上有線程安全的結構。
  • JVM優化邊界檢查,開發者控制邊界檢查。(允許提供安全性設置)
  • 有能力在同一緩沖區的不同記錄復用一份緩沖。
  • 有能力去映射一個非堆存儲(off-heap)數據結構,讓緩沖區在優化過的方式下進行邊界檢查。
保留關鍵功能
  • 支持內存映射文件
  • 支持NIO
  • 支持把寫操作提交到磁盤
候選方案:直接使用sun.misc.Unsafe
測試:sun.misc.Unsafe和內存映射文件有同樣的測試需求。附加的測試應該工作在同樣的方式下,要求展示的線程安全的操作為AtomicXxxx類。AtomicXxxx類應該被重寫並且單獨使用公共的API。

風險: 當一群開發者使用了Unsafe之後,他們可能一致認為沒有更適合的替代品。這意味著JEP的範圍很廣,或者創建了新的JEP覆蓋了Unsafe中的其他功能。 其他JDK : NIO 兼容性: 提供了向後兼容的庫。它兼容java7,如果你有足夠的興趣去研究的話,也有可能兼容java6。(截止到這篇文章,Java 7是當前的版本)。 安全性: 在理想情況下,安全的風險性不能超過ByteBuffer太多。 性能和可擴展性: 優化邊界檢查是困難的。為了添加更多的普通操作,則需要把功能添加到新的緩沖區,以減少開銷,例如讀寫UTF。

AJPFX總結OpenJDK 和 HashMap大量數據處理時,避免垃圾回收延遲的技巧一