【问题标题】:Can I constrain a HashMap by the amount of memory it takes up?我可以通过它占用的内存量来限制 HashMap 吗?
【发布时间】:2010-07-28 20:17:07
【问题描述】:

我正在根据here 找到的指令使用LinkedHashMap 实现一个简单的缓存。我使用以下代码:

public class Cache extends LinkedHashMap {
  private final int capacity;

  public Cache(int capacity) {
    super(capacity + 1, 1.1f, true);
    this.capacity = capacity;
  }

  protected boolean removeEldestEntry(Entry eldest) {
    return size() > capacity;
  }
}

这很容易。然而,它只是在地图上强加了一个固定的大小。我在一个非常小的堆上运行,根据缓存对象的大小和我选择的容量,这仍然可能会耗尽内存。这些对象是任意的,所以我无法估计它们可能有多大。我不想依赖SoftReferences 来修剪缓存,因为清理缓存的方式不可靠;它会从 VM 更改为 VM,它们可能会过早地被回收,或者它们可能永远不会被回收,直到它们填满我的堆。

我有什么方法可以监控地图的大小并以此为基础进行约束吗?

【问题讨论】:

    标签: java memory-management caching


    【解决方案1】:

    如果软/弱引用是不可能的,那么我会看到 2 个(重要的)选项:

    1) 使用 Java 工具检查添加到地图中的项目的实际大小。检测接口提供对象的"shallow" size,您将需要更多代码来探索引用(并避免计算重复!)。 Here 是一种计算一个对象的深度大小的解决方案。

    2) 使用 JMX 跟踪 GC 后的堆大小,并在达到某个危险阈值时更改映射行为。请参阅MemoryMXBean javadoc 中的“通知”部分。

    【讨论】:

      【解决方案2】:

      地图本身只包含固定大小的条目,其中包含对地图中“包含”的实际对象的引用。您需要覆盖所有映射变异方法(即put()、复制构造函数等)以跟踪映射中引用的对象的大小(您甚至可以确定 Java 对象占用了多少内存吗?)。然后考虑您添加到缓存中的对象本身可能包含对其他对象和/或集合的引用。你去多深?

      看看http://www.javapractices.com/topic/TopicAction.do?Id=83

      【讨论】:

      • 我想这基本上就是我要问的 - 是否可以确定任意对象的浅和/或保留大小?我知道,这是一个可笑的问题。 :-P
      • 我添加了一个链接,指向我通过 Google 搜索“对象的 java 大小”找到的页面。该结果页面上有许多看起来很有趣的链接。
      【解决方案3】:

      正如其他人所提到的,您可以使用代理工具来执行此操作。 SizeOf 项目为这种方法提供了一个方便的实用程序。这可以与 ConcrrentLinkedHashMap 的加权值概念一起使用,其中 Weigher 确定一个值消耗多少容量单位。除了传统的最大条目数限制之外,这使缓存能够正确处理集合或内存限制。

      如果你希望被堆绑定,那么有一个早期版本的 ConcurrentLinkedHashMap 的分支可以做到这一点。这保留了原始的 Apache 许可证,因此它可以根据您的需要进行调整,因为它与 Voldemort 打包在一起。

      http://sizeof.sourceforge.net/

      http://code.google.com/p/concurrentlinkedhashmap/

      http://github.com/Omega1/voldemort/blob/master/src/java/voldemort/store/memory/ConcurrentLinkedHashMap.java

      【讨论】:

        【解决方案4】:

        您可以包装 Map 实现并在 putputAll 方法中强制执行大小。

        【讨论】:

        • 我很困惑,我将如何评估传入对象的大小?我问的是实际占用的堆空间字节数,而不是对象数。
        猜你喜欢
        • 2010-12-06
        • 2011-12-09
        • 2022-10-30
        • 1970-01-01
        • 2015-01-01
        • 2021-04-27
        • 2017-06-11
        • 1970-01-01
        • 2013-11-12
        相关资源
        最近更新 更多