このプロジェクトはもはや維持されていません!!!
OHCは、非uniform骨メモリ - アーキテクチャを使用して、コモディティハードウェアと大きなシステムの両方で優れたパフォーマンスを提供するものとします。
パフォーマンステストの結果はまだ利用できません - OHCベンチマークツールを試すことができます。以下の手順を参照してください。速度に関する非常に基本的な印象は、_benchmarking_セクションにあります。
64bitをサポートし、 sun.misc.Unsafe
(x64 Intel CPUのOracle JVMS)を備えたJava 8 VM。
OHCはLinuxとOSXの標的を絞っています。 Windowsやその他のUNIX OSSで動作するはずです。
OHCは、さまざまなキャッシュエントリ特性に対して2つの実装を提供します。 -_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
オプションを使用して構成されています。
リンクされた実装と同様に、ハッシュエントリは、セグメントに実際のプットが発生する前に、最初に一時バッファーにシリアル化されます(セグメント操作は同期されます)。
現在の書き込みチャンクに新しいエントリが配置されます。そのチャンクがいっぱいになると、次の空のチャンクが新しい書き込みチャンクになります。すべてのチャンクがいっぱいになると、含まれるすべてのエントリを含め、最近使用されていないチャンクが追い出されます。
fixedKeyLength
およびfixedValueLength
Builderプロパティを指定すると、メモリフットプリントがエントリごとに8バイト減少します。
この実装では、シリアル化、直接アクセス、およびローダー機能がサポートされていません。
チャンクされた実装を有効にするには、 org.caffinitas.ohc.OHCacheBuilder
でchunkSize
を指定します。
注:チャンクされた実装は、まだ実験的と見なされる必要があります。
OHCは3つのVevictionアルゴリズムをサポートしています。
クラスOHCacheBuilder
を使用して、必要なすべてのパラメーターを次のように構成します
通常、大きなハッシュテーブルを使用する必要があります。ハッシュテーブルが大きいほど、各ハッシュパーティションのリンクリストが短くなります。これは、リンクリンクウォークが少なく、パフォーマンスの向上を意味します。
必要なヒープメモリの合計量は、総容量とハッシュテーブルです。各ハッシュバケット(現在)には8バイトが必要なため、式はcapacity + segment_count * hash_table_size * 8
。
OHCは、Javaのオフヒープメモリ制限を直接バイパスするオフヒープメモリを割り当てます。これは、OHCによって割り当てられたすべてのメモリが-XX:maxDirectMemorySize
にカウントされないことを意味します。
特にリンクされた実装は、個々のエントリごとにAlloc/Free操作を実行するため、メモリの断片化が発生する可能性があることを考慮してください。
また、いくつかの割り当てがまだ飛行中であり、「他のもの」(オペレーティングシステム、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() .keyserializer(yourkeyserializer) .ValuesErializer(YourValuesErializer) 。建てる();
このQuickStartは、少なくともデフォルトの構成を使用します。
オプションの完全なリストについては、Javadoc of CacheBuilder
を参照してください。
KeyおよびValue Serializersは、 CacheSerializer
インターフェイスを実装する必要があります。このインターフェイスには3つの方法があります。
int serializedSize(T t)
指定されたオブジェクトのシリアル化サイズを返すvoid serialize(Object obj, DataOutput out)
に与えられたオブジェクトをデータ出力にシリアル化するT deserialize(DataInput in)
データ入力からオブジェクトを脱また重化するGit Repoをローカルマシンにクローンします。安定したマスターブランチまたはリリースタグを使用します。
git clone https://github.com/snazy/ohc.git
Sourceから構築するには、OpenJDK 11以下が必要です。実行するだけです
mvn clean install
大きなベンチマークアーティファクトはMaven Centralにアップロードされていないため、ソースからOHCを構築する必要があります。
java -jar ohc-benchmark/target/ohc-benchmark-0.7.1-SNAPSHOT.jar -h
(ソースから構築するとき)を実行して、ヘルプ情報を取得します。
通常、ベンチマークツールはスレッドの束を開始し、_Get_および_put_操作の構成可能なキーディストリビューションを使用して_Get_および_put_操作を実行します。値サイズ分布も構成する必要があります。
利用可能なコマンドラインオプション:
-cacheの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ロックを使用しない - シングルスレッドモードにはApproPiateのみ -HM <Arg>使用するハッシュアルゴリズム-MURMUR3、XX、CRC32 -bh統計でバケツhisthorgramを表示します -kl <Arg>バケットヒストグラムを有効にします。デフォルト:false
読み取りキー、書き込みキー、値のサイズの分布は、次の機能を使用して構成できます。
exp(min..max)範囲上の指数分布[min..max] 極端(min..max、shape)範囲上の極端な値(weibull)分布[min..max] Qextreme(min..max、shape、quantas)極端な値、Quantasに分かれています。 ガウス(min..max、stdvrng)平均=(min+max)/2、およびstdevは(平均min)/stdvrngです。 ガウス(min..max、平均、stdev)ガウス/正規分布、明示的に定義された平均とstdev 均一(min..max)範囲上の均一な分布[最小、最大] 固定(val)固定分布。常に同じ値を返します 〜で名前の前に分布が反転します。 エイリアス:extr、qextr、gauss、normal、norm、weibull
(注:これらはApache Cassandraストレスツールに似ています - あなたが知っているなら、あなたは両方を知っています;)
読み取り/書き込み比が.9
、約1.5GBの最大容量、30秒間実行される16個のスレッドを持つクイック例:
Java -Jar OHCベンチマーク/ターゲット/OHCベンチマーク-0.5.1-Snapshot.jar
(JARファイル名のバージョンが異なる場合があることに注意してください。)
2.6GHz Core i7システム(OSX)では、次の数値は上記のベンチマーク(.9読み取り/書き込み比)を典型的に実行しています。
非常に大きなヒープで非常に膨大な数のオブジェクトを使用する場合、仮想マシンはGC圧力の増加に苦しみます。これは、基本的にすべてのオブジェクトを収集できるかどうかを検査し、すべてのメモリページにアクセスする必要があるかどうかを検査する必要があるためです。キャッシュは、高速アクセスのためにオブジェクトのホットセットをアクセスできるようにします(例:ディスクまたはネットワークの往復を省略します)。唯一の解決策は、ネイティブメモリを使用することです。そこで、JNIを介してネイティブコード(C/C ++)を使用するか、直接メモリアクセスを使用するかの選択になります。
JNI経由でC/C ++を使用したネイティブコードには、すべてのプラットフォームに対してC/C ++コードを自然に記述する必要がある欠点があります。ほとんどのUNIX OS(Linux、OSX、BSD、Solaris)は、比較対象のライブラリやPOSIXライブラリなどを扱う場合、非常に似ていますが、通常、他のプラットフォーム(Windows)もサポートしたいと考えています。
ネイティブコードとダイレクトメモリアクセスには、JVMのコンテキストを「残す」必要があるという欠点があります。オフヒープメモリへのアクセスは、Javaヒープ内のデータへのアクセスよりも遅く、各JNIコールにはいくらかがあると言いたいと思います。 JVMコンテキストからの脱出 "コスト。
しかし、DOSがJava Garbage Collectorにプレッシャーをかけないため、大量/多くのGBのキャッシュメモリに対処しなければならない場合、ヒープメモリは素晴らしいことです。 Java GCに、このライブラリがキャッシュデータのために仕事をするアプリケーションのために仕事をさせてください。
TL; DRは、オフヒープメモリを直接割り当て、 ByteBuffer.allocateDirect
をバイパスします。GCには非常に穏やかであり、メモリの割り当てを明示的に制御し、さらに重要なことには無料です。 Javaでの在庫の実装は、ゴミコレクション中にオフヒープメモリを解放します - また、オフヘープメモリが利用できなくなった場合、それはフルGCをトリガーする可能性があります。フル-GCSの順次。さらに、在庫の実装では、グローバルな同期リンクリストを使用して、HEAPオフメモリの割り当てを追跡します。
これが、OHCがオフヒープメモリを直接割り当てる理由であり、LinuxシステムでJemallocをプリロードしてメモリ管理のパフォーマンスを改善することを推奨しています。
OHCは、2014/15年にApache Cassandra 2.2および3.0が新しいRow-Cacheバックエンドとして使用されるように開発されました。
利用可能な完全にオフホイップオフキャッシュの実装がなかったため、まったく新しいものを構築することが決定されました - それはOHCです。しかし、OHCだけでも他のプロジェクトでも使用できる可能性があることが判明しました。そのため、OHCは別のライブラリである理由です。
OHCへの非常に便利な入力のために、DataStaxのベネディクト・エリオット・スミスとアリエル・ワイスバーグに大きな「ありがとう」が必要です!
W-Tiny LFUを使用した高度に構成可能なオンヒープキャッシュの著者であるBen Manes。
開発者:Robert Stupp
Copyright(c)2014 Robert Stupp、Koeln、ドイツ、Robert-Stupp.de
Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。ライセンスに準拠している場合を除き、このファイルを使用することはできません。ライセンスのコピーを取得できます
http://www.apache.org/licenses/license-2.0
適用法で要求されていないか、書面で合意されていない限り、ライセンスに基づいて配布されたソフトウェアは、明示または黙示のいずれかの保証または条件なしに、「現状のまま」に基づいて配布されます。ライセンスに基づく権限と制限を管理する特定の言語のライセンスを参照してください。