パフォーマンスの劣化を避けるために、いつハッシュマップの内容を破壊するのですか?
-
19-09-2019 - |
質問
私は実際に10.000.000の容量と0.75の負荷係数で構築されている大きな(数百万)ハッシュマップでJavaでウォーキングをしています。
キャッシュされた値は時間とともに役に立たないので(もうアクセスしていません)が、パフォーマンスが低下し始めたときにキャッシュを完全に空にしたいときは、役に立たないものを削除することはできません。いつそれをするのが良いかをどうやって決めることができますか?
たとえば、1億1000万人の容量と.75で、750万の要素に達したら空にする必要がありますか?さまざまなしきい値を試したが、分析値が欲しいからです。
私はすでに、それが非常にいっぱいになったときにそれを拡大することがパフォーマンスのためのブーストであるという事実をすでにテストしました(ワイプ後の最初の2-3アルゴリズムの反復は、それを後ろに満たしただけで、それはワイプの前よりも速く実行を開始します)
編集:追加情報
ハッシュマップには、キーとフロートとして値として長くあります。コンテンツのキャッシュされた相関が含まれています。なぜなら、それは私がそれらをキャッシュしたいタグベクターのドット製品であるため(パフォーマンスを向上させるため)。
だから基本的に私がしていることは、aを計算することです long
2つの内容のハッシュコードを使用したキー:
static private long computeKey(Object o1, Object o2)
{
int h1 = o1.hashCode();
int h2 = o2.hashCode();
if (h1 < h2)
{
int swap = h1;
h1 = h2;
h2 = swap;
}
return ((long)h1) << 32 | h2;
}
保存された値を取得するために使用します。起こることは、それが階層的なクラスタリングの内容がマージされ、他の内容との相関値がもう必要ないので、そのためのハッシュマップを時々拭き取り、その内部の役に立たない値のために劣化を避けることです。
を使って WeakHashMap
データがまだ必要なときにも予測不可能なデータを一掃します。私はそれを制御できません。
ありがとう
解決
LRUキャッシュを使用してみませんか? JavaのLinkedHashmapドキュメントから:
特別なコンストラクターが提供され、リンクされたハッシュマップが作成されます。リンクハッシュマップでは、最小限のアクセスから最小限の(アクセスオーダー)まで、エントリが最後にアクセスされた順序であるリンクハッシュマップが作成されます。この種のマップは、LRUキャッシュの構築に適しています。プットまたは取得メソッドの結果を呼び出すと、対応するエントリにアクセスできます(呼び出しが完了した後に存在すると仮定します)。 Putallメソッドは、指定されたマップのエントリセットIteratorによってキー値マッピングが提供される順に、指定されたマップ内の各マッピングに1つのエントリアクセスを生成します。他のメソッドはエントリアクセスを生成しません。特に、コレクションビューの操作は、バッキングマップの反復順に影響しません。
基本的には、マップが大きくなりすぎると時々、イテレーターが与える最初のX値を削除するだけです。
のドキュメントを参照してください removeEldestEntry
これを自動的に行うために。
これが示すコードです:
public static void main(String[] args) {
class CacheMap extends LinkedHashMap{
private int maxCapacity;
public CacheMap(int initialCapacity, int maxCapacity) {
super(initialCapacity, 0.75f, true);
this.maxCapacity = maxCapacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size()>maxCapacity;
}
}
int[] popular = {1,2,3,4,5};
CacheMap myCache = new CacheMap(5, 10);
for (int i=0; i<100; i++){
myCache.put(i,i);
for (int p : popular) {
myCache.get(p);
}
}
System.out.println(myCache.toString());
//{95=95, 96=96, 97=97, 98=98, 99=99, 1=1, 2=2, 3=3, 4=4, 5=5}
}
他のヒント
調査しましたか weakhashmaps ?ゴミコレクターは、いつ除去するかを決定することができ、何かを自分でコーディングするのではなく、許容できる代替品を提供する可能性があります。
この記事 より有用な情報があります。
Googleコレクションを使用してください。 マップメーカー ソフト参照と特定のタイムアウトでマップを作成します。
ソフト参照「メモリの需要に応じて、ゴミコレクターの裁量によりクリアされます。」
例:
ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
.concurrencyLevel(32)
.softValues()
.expiration(30, TimeUnit.MINUTES)
.makeMap();
WeakKeysをWeakHashmapのように動作させたい場合は、WeakKeysを指定することもできます。