2

我正在尝试对不断运行 OOM 的服务器进行内存优化。

服务器中的大多数对象(按计数)采用以下形式:

  • 每个对象都是一个HashMap
  • HashMap 键是字符串
  • HashMap 值是 Attribute 类的对象,它只有一个 int 和 2 个布尔值。

重要的警告:95% 的此类哈希图永远只有一个键;我知道创建哈希图时是否是这种情况。

有数百万个这样的哈希图。

我已经问了一个关于优化这些哈希映射内存的单独问题,并且有人在评论中建议重新设计我的整个数据结构可能会更好,因为即使初始大小为“1”哈希映射仍然占用额外的内存。

因此,我的问题是;有没有更好的 Java 数据结构可以实现,它可以以更好的内存效率存储相同的确切数据?

注意:我需要能够查找特定值是否作为键存在;因此我考虑过但拒绝将数据存储在 [string_value, int, boolean, boolean] 的五元组列表中。

4

2 回答 2

2

向用户公开不太具体的Map接口而不是HashMap,这使您可以根据情况自由使用哈希映射或单例映射。

可以通过以下方式创建内存高效的单例映射 Collections.singletonMap()https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#singletonMap(K,%20V)

SingletonMap似乎被实现为一个只有两个字段和一些缓存的对象:http: //grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collections.java #Collections.SingletonMap

ps 您可以通过将地图和值折叠到一个实例中来为您的特殊情况提供更紧凑的东西,如下所示:

public final class SingletonAttributeMap extends Attribute implements Map<String,Attribute> {

  private final String key;

  public Attribute get(String key) {
    return this.key.equals(key) ? this : null;
  }

  ....
}

pps 属性中的整数是否有最大大小?您也许可以做这样的技巧(这是否真正节省内存将取决于填充/对齐,请参阅Java中对象的内存消耗是多少?):

 class Attribute {
    private int value;

    boolean getBoolean1() {
      return (value & 1) != 0; 
    }

    boolean getBoolean2() {
       return (value & 2) != 0;
    }

    int getInt() {
       return value >> 2;
    }

    void setBoolean1(boolean b) {
      value = (value & ~1) | (b ? 1 : 0);
    }

    void setInt(int i) {
      value = (value & ~3) | (i << 2);
    }

    ... 
于 2017-10-18T20:21:36.850 回答
1

每个对象都是一个HashMap?不是一个很好的抽象。我更喜欢组合:创建一个具有 HashMap 并提供清晰 API 的对象。使其具有可比性并实现 hashCode 和 equals。

如果有很多重复,我建议你遵循享元模式。

如果对象是不可变的和只读的,这将是一个非常好的优化。

有一个工厂对象来创建实例并维护一个唯一的列表。如果有人要求一个已经在 List 中的,则返回不可变的副本。

您可以在实施之前计算这将节省多少内存。

于 2017-10-18T18:09:34.947 回答