這個項目不再維護!!!
OHC應使用非均勻內存架構在商品硬件和大型系統上提供良好的性能。
尚無性能測試結果 - 您可以嘗試使用OHC基準測試工具。請參閱下面的說明。速度上的一個非常基本的印像是_benchmarking_節中。
Java 8 VM支持64位,並具有sun.misc.Unsafe
(X64 Intel CPU上的Oracle JVM)。
OHC針對Linux和OSX。它應該在Windows和其他Unix OSS上使用。
OHC為不同的緩存輸入特性提供了兩種實現: - _linked_實現分別為每個條目分別分配了臨時內存,並適用於中等和大參賽作品。 - _chunked_實施將為整個哈希段分配外部內存,並用於小條目。
片段的數量通過org.caffinitas.ohc.OHCacheBuilder
配置,默認為# of cpus * 2
,並且必須是2的冪。條目是使用64個位哈希碼中最重要的片段在段上分發的。每個段上的訪問都同步。
每個哈希地圖條目都是單獨分配的。條目是免費的(交易)的,當它們不再由外部地圖本身或任何外部參考(例如org.caffinitas.ohc.DirectValueAccess
或org.caffinitas.ohc.CacheSerializer
引用時。
該實現的設計將細分市場的鎖定時間縮短到很短的時間。將/替換操作分配內存,首先分配內存,調用org.caffinitas.ohc.CacheSerializer
序列化鍵和值,然後將完全準備好的入口放入該段。
使用LRU算法進行驅逐。通過每個段的所有緩存元素鏈接列表用於跟踪最大條目。
存儲器分配塊外部實現。
與鏈接的實現相比,此實現的目的是減少相對較小的緩存條目的開銷,因為整個段的內存已預先分配。此實現適用於具有org.caffinitas.ohc.CacheSerializer
的快速(de)序列化實現的小條目。
細分與鏈接的實現相同。片段的數量通過org.caffinitas.ohc.OHCacheBuilder
配置,默認為# of cpus * 2
,並且必須是2的冪。條目是使用64個位哈希碼中最重要的片段在段上分發的。每個段上的訪問都同步。
每個部分分為多個塊。每個細分市場負責總容量(capacity / segmentCount)
的一部分。在初始化期間,將這種內存量分配後一次分配,並在邏輯上分為可配置數量的塊。每個塊的大小都使用org.caffinitas.ohc.OHCacheBuilder
中的chunkSize
選項進行配置。
像鏈接的實現一樣,哈希條目首先將其序列化為臨時緩衝區,然後在實際投入到一個細分市場中(Semement Operations同步)。
新條目放入當前寫入塊中。當塊滿時,下一個空的塊將成為新的寫作塊。當所有塊都滿時,最近使用的最少使用的塊,包括其包含的所有條目,都將被驅逐出境。
指定fixedKeyLength
和fixedValueLength
Builder屬性可將內存足跡減少每個條目8個字節。
在本實現中不支持序列化,直接訪問和獲取加載器功能。
要啟用塊的實現,請在org.caffinitas.ohc.OHCacheBuilder
中指定chunkSize
。
注意:塊的實現仍應被視為實驗。
OHC支持三種驅逐算法:
使用類OHCacheBuilder
來配置所有必要的參數
通常,您應該使用一個大哈希桌。哈希表越大,每個哈希分區中的鏈接列表越短 - 這意味著鏈接的步行和性能提高。
所需的關閉內存的總量是總容量加上哈希表。每個哈希桶(當前)需要8個字節 - 因此公式為capacity + segment_count * hash_table_size * 8
。
OHC直接繞過Java的離容器內存限制直接分配了主內存。這意味著,OHC分配的所有內存都不計入-XX:maxDirectMemorySize
。
由於尤其是鏈接的實現為每個單獨的條目執行異鏈/自由操作,因此請考慮可能發生內存碎片。
另外,由於某些分配可能仍在飛行中,並且“其他東西”(操作系統,JVM等)需要內存,因此請留下一些頭部空間。這取決於使用模式需要多少頭空間。請注意,鏈接的實現將在寫操作過程中分配內存_before_,它被計入段,這將驅逐較舊的條目。這意味著:請勿將所有可用的內存獻給OHC。
我們建議使用Jemalloc保持碎片較低。在UNIX操作系統上,預付Jemalloc。
出於性能原因,OSX通常不需要Jemalloc。另外,請確保您使用的是Jemalloc的最新版本 - 某些Linux發行版仍然提供相當舊的版本。
要在Linux上預緊jemalloc,請使用export LD_PRELOAD=<path-to-libjemalloc.so
,在OSX上預留jemalloc,請使用export DYLD_INSERT_LIBRARIES=<path-to-libjemalloc.so
。可以在Apache Cassandra項目中找到用於預加載的腳本模板。
QuickStart:
ohcache ohcache = ohcachebuilder.newbuilder() 。 .Valueserializer(YourValueserializer) 。建造();
此QuickStart使用至少默認配置:
有關選項的完整列表,請參見CacheBuilder
的Javadoc。
鍵和值序列化需要實現CacheSerializer
界面。該接口具有三種方法:
int serializedSize(T t)
以返回給定對象的序列化大小void serialize(Object obj, DataOutput out)
以序列化給定對像到數據輸出T deserialize(DataInput in)
中對象進行對象化克隆GIT存儲庫到您當地的機器。使用穩定的主分支或發布標籤。
git clone https://github.com/snazy/ohc.git
您需要OpenJDK 11或更新才能從源構建。只是執行
mvn clean install
您需要從源構建OHC,因為大型基準工件未上傳到Maven Central。
執行java -jar ohc-benchmark/target/ohc-benchmark-0.7.1-SNAPSHOT.jar -h
(從源來構建時)以獲取一些幫助信息。
通常,基準工具啟動了一堆線程,並使用_get_和_put_ operations配置的鍵分佈同時執行_et_和_put_操作。還需要配置價值大小分佈。
可用命令行選項:
-cap <arg>緩存的大小 -d <ARG>基準持續時間秒 -H幫助,打印此命令 -lf <arg>哈希表負載因子 -r <arg>讀取版評分(作為雙重0..1代表讀取的機會) -rkd <arg>熱鍵使用分佈 - 默認值:統一(1..10000) -sc <arg>段數(單個非主映射的數量) -t <arg>線程執行 -vs <arg>值大小 - 默認值:固定(512) -wkd <arg>熱鍵使用分佈 - 默認值:統一(1..10000) -wu <arg>熱身 - <Work-Secs>,<Sleep-Secs> -z <arg>哈希表尺寸 -cs <arg>塊尺寸 - 如果指定,它將使用“塊”實現 -fks <arg>修復了字節中的密鑰大小 -fvs <arg>字節中的固定值大小 -Mes <ARG>最大輸入大小在字節中 -unl不使用鎖定 - 僅適當用於單線讀模式 -HM <ARG> HASH算法要使用-Murmur3,XX,CRC32 -BH統計數據中顯示存儲庫紀錄 -kl <arg>啟用桶形直方圖。默認值:false
可以使用以下功能配置讀取鍵,寫鍵和值大小的分佈:
Exp(min..max)在[min..max]範圍內的指數分佈 極端(最小值,形狀)在[min..max]範圍內的極值(weibull)分佈 qExtreme(min..max,Shape,Quantas)一個極值,分為Quantas,其中選擇的機會是均勻的 高斯(min..max,stdvrng)高斯/正態分佈,其中平均值=(min+max)/2,stdev為(平均值)/stdvrng 高斯(Min..max,平均,stdev)的高斯/正態分佈,具有明確定義的平均值和stdev 在[min,max]範圍內的均勻分佈(最小值)均勻分佈 固定(val)固定分佈,總是返回相同的值 在使用〜的名稱之前將倒轉分佈,例如exp(1..10)將產生最多的10,而不是通常,通常會產生 別名:extr,qextr,高斯,正常,標準,威布爾
(注意:這些類似於Apache Cassandra壓力工具 - 如果您知道,您都知道;)
讀/寫入比為.9
的快速示例,大約1.5GB最大容量,16個線程運行30秒:
Java -Jar OHC基準/target/ohc-benchmark-0.5.1-snapshot.jar
(請注意,JAR文件名中的版本可能有所不同。)
在2.6GHz Core i7系統(OSX)上,以下數字是典型運行上述基準測試的(.9讀/寫比):
當在很大的堆中使用大量對象時,虛擬機將遭受GC壓力的增加,因為它基本上必須檢查每個對像是否可以收集它並必須訪問所有內存頁面。緩存應保持一組熱門對象,以便快速訪問(例如省略磁盤或網絡往返機)。唯一的解決方案是使用本機內存 - 您最終將選擇通過JNI使用某些本機代碼(C/C ++)或使用Direct Memory訪問。
使用JNI使用C/C ++的本機代碼具有您必須自然編寫每個平台的C/C ++代碼的缺點。儘管大多數Unix OS(Linux,OSX,BSD,SOLARIS)在處理諸如“比較”和“盤”或“ Posix庫”之類的內容時非常相似,但您通常還希望支持其他平台(Windows)。
本機代碼和直接內存訪問都有一個缺點,即他們必須“離開” JVM“上下文” - 想說訪問OFF HEAP內存的訪問比對Java Heap中數據的訪問較慢,並且每個JNI調用都有一些'逃離JVM上下文“成本”。
但是,當您不得不處理大量/多個GB的緩存內存時,堆內的內存非常好,因為DOS沒有對Java垃圾收集器施加任何壓力。讓Java GC在該庫為緩存數據完成工作的應用程序中完成工作。
TL; DR直接分配了異位記憶並繞過ByteBuffer.allocateDirect
對GC非常柔和,我們對內存分配有明確的控制,更重要的是免費。 Java中的庫存實施在垃圾收集期間釋放了臨時內存- 另外:如果沒有更多的離容器內存,則可能會觸發全GC,如果多個線程同時遇到這種情況,這是有問題的,因為這意味著很多。完整的GC依次。此外,股票實施使用全局同步的鏈接列表來跟踪非主機內存分配。
這就是為什麼OHC直接分配離容器內存並建議在Linux系統上預努加載Jemalloc以提高內存管理性能的原因。
OHC於2014/15年開發,用於Apache Cassandra 2.2和3.0,用作新的Row-Cache後端。
由於沒有合適的完全離子緩存實現,因此已決定構建一個全新的速度 - 這就是OHC。但是事實證明,僅OHC也可能適用於其他項目 - 這就是為什麼OHC是一個單獨的庫。
一個很大的“謝謝”必須向Benedict Elliott Smith和DataStax的Ariel Weisberg提供對OHC非常有用的意見!
Ben Manes,咖啡因的作者,咖啡因是使用W-Biny LFU的高度可配置的植型緩存。
開發人員:羅伯特·斯圖普(Robert Stupp)
版權(c)2014羅伯特·斯圖普,德國科恩,羅伯特 - 斯圖普。
根據Apache許可證(版本2.0(“許可”)獲得許可;除了符合許可外,您不得使用此文件。您可以在
http://www.apache.org/licenses/license-2.0
除非適用法律要求或以書面形式同意,否則根據許可證分配的軟件是按照“原樣”分發的,沒有任何明示或暗示的任何形式的保證或條件。請參閱許可證,以獲取執行許可條款和限制的特定語言。