何时废弃hashmap内容以避免性能下降?

时间:2010-03-11 16:30:20

标签: java performance hashmap load-factor

我正在使用大量(数百万)hashmap实现Java,实际上构建的容量为10.000.000,加载因子为.75,它用于缓存一些值

因为缓存的值随着时间的推移变得无用(不再被访问)但是我无法删除无用的值,而在我希望在其性能开始降低时完全清空缓存的方式。我怎样才能决定什么时候这样做好?

例如,当它达到750万个元素时,我应该清空它的1000万容量和.75因为我尝试了各种阈值,但我希望有一个分析值。

我已经测试了这样一个事实:当它非常饱满时将它移除是对性能的提升(擦除之后的前2-3次算法迭代只是填充它,然后它开始比擦除之前更快地运行)

编辑:附加信息

hashmap长按键,浮动为值。它包含内容的缓存关联,因为它是我想要缓存它们的标记向量的点积(以提高性能)。

所以基本上我所做的是使用2个内容的哈希码计算long密钥:

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;
}

并使用它来检索存储的值。会发生什么事情,因为它是一个层次化的聚类内容被合并,并且不再需要它们与其他内容的相关值..这就是为什么我想不时擦除hashmap,以避免由于其中无用的值而导致的降级。 / p>

使用WeakHashMap也会在需要时无法预测地删除数据..我无法控制它。

由于

3 个答案:

答案 0 :(得分:5)

为什么不使用LRU缓存? 来自Java的LinkedHashMap文档:

  

提供了一个特殊的构造函数   创建一个其顺序的链接哈希映射   迭代的顺序是它的顺序   上次访问的条目来自   最近访问过的   最近(访问顺序)。这个   一种地图非常适合建筑   LRU缓存。调用put或get   方法导致访问   相应的条目(假设它   调用后存在   完成)。 putAll方法   为每个生成一个条目访问权限   映射在指定的映射中   命令键值映射   由指定地图的条目提供   设置迭代器。没有其他方法   生成入口访问。在   特别是,开展业务   集合视图不会影响   支持地图的迭代顺序。

所以基本上,每当你的地图变得太大时,只需删除迭代器为你提供的前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}
  }

答案 1 :(得分:2)

你调查了WeakHashMaps吗?垃圾收集器可以确定何时删除东西,它可能会给你一个可接受的替代品而不是自己编写代码。

This article有更多有用的信息。

答案 2 :(得分:2)

您可能希望使用Google Collections'MapMaker制作包含软参考和特定超时的地图。

软引用“由垃圾收集器根据内存需求自行决定清除。”

示例:

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

如果你想让它的键像WeakHashMap中的那样,你也可以指定weakKeys。