2

私は、実際には容量が10.000.000、負荷率が.75で構築され、いくつかの値をキャッシュするために使用される大規模な(数百万の)ハッシュマップを使用してJavaを起動しています。

キャッシュされた値は時間の経過とともに役に立たなくなります(もうアクセスされなくなります)が、パフォーマンスが低下し始めたときにキャッシュを完全に空にしたい途中で、役に立たない値を削除することはできません。いつそれをするのが良いかをどうやって決めることができますか?

たとえば、容量が1,000万で、0.75の場合、750万の要素に達したときに空にする必要がありますか?いろいろ試してみましたが、分析的なものが欲しいので。

完全にいっぱいになったときにそれをエンピングするとパフォーマンスが向上するという事実をすでにテストしました(ワイプ後の最初の2〜3回のアルゴリズムの反復は、それを埋め戻すだけで、ワイプ前よりも速く実行を開始します)

編集:追加情報

ハッシュマップには、キーとフロートが値として含まれています。これには、コンテンツのキャッシュされた相関関係が含まれています。これは、(パフォーマンスを向上させるために)キャッシュしたかったタグベクトルの内積であるためです。

つまり、基本的に私が行うことは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と、データがまだ必要な場合でも、予期せずにデータが消去されます。私はそれを制御できません。

ありがとう

4

3 に答える 3

5

LRUキャッシュを使用してみませんか?JavaのLinkedHashMapドキュメントから:

リンクされたハッシュマップを作成するための特別なコンストラクターが提供されます。その反復の順序は、エントリが最後にアクセスされた順序であり、最近アクセスされた順序から最近アクセスされた順序(access-order)までです。この種のマップは、LRUキャッシュの構築に最適です。putまたはgetメソッドを呼び出すと、対応するエントリにアクセスできます(呼び出しの完了後に存在すると想定)。putAllメソッドは、指定されたマップのエントリセットイテレータによってキーと値のマッピングが提供される順序で、指定されたマップのマッピングごとに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}
  }
于 2010-03-11T16:54:22.087 に答える
2

WeakHashMapsを調査しましたか?ガベージコレクターは、いつ削除するかを決定でき、自分でコーディングするのではなく、許容できる代替手段を提供する場合があります。

この記事には、より役立つ情報があります。

于 2010-03-11T16:34:51.337 に答える
2

GoogleコレクションのMapMakerを使用して、ソフト参照と特定のタイムアウトを含むマップを作成することをお勧めします。

ソフト参照は、「メモリの需要に応じて、ガベージコレクタの裁量でクリアされます」。

例:

ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
    .concurrencyLevel(32)
    .softValues()
    .expiration(30, TimeUnit.MINUTES)
    .makeMap();

キーをWeakHashMapのキーのように動作させる場合は、weakKeysを指定することもできます。

于 2010-03-11T16:59:06.143 に答える