【问题标题】:Optimized variable declaration primitive vs null object优化的变量声明原语与空对象
【发布时间】:2014-05-07 16:22:03
【问题描述】:

我有一个名为 Location 的类,它有两种类型的信息,一种是 nodeID(整数),另一种是 diskPosition(长整数)。 我的应用程序需要创建这个 Location 类的许多对象,但大多数时候我会为 Location 类中的这两个变量之一分配一个默认值(比如 -1)。

我的问题是“我是否应该将这些 nodeID 和 diskPosition 声明为 Integer 和 Long 并分配默认值 null 而不是将它们保持为原始值并将默认值分配为 -1)”

我担心我的 Location 对象占用的内存量,我想将其最小化。

下面是Location类的代码sn-p:

public class Location
{
    private int     nodeID  = -1;
    private long    diskPos = -1;

    public Location(long diskPos)
    {
        this.diskPos = diskPos;
    }

    public Location(Node node)
    {
        this.nodeID = node.getNodeID();
    }

    // Test main method to elaborate usage of Location object
    public void main(String[] args)
    {
        Map<Integer, Location> cellIDToLocationMap = new HashMap<Integer, Location>();

        // Consider there is a list of nodes which is obtained from somewhere
        List<Node> nodeList = getNodeList();

        Location loc = null;
        for (int i = 1; i <= 10000; i++)
        {
            if (i % 2 == 0)
                loc = new Location(nodeList.get(i));
            else
                loc = new Location(i);

            // Put in map
            cellIDToLocationMap.put(i, loc);
        }
    }
}

【问题讨论】:

  • 那之后你如何使用 Location
  • 默认值打破了独特的约束。
  • 根据经验,基元比对象占用更少的内存。
  • @Chris 继承没有一些开销吗?我认为它会抵消任何内存节省。
  • @WhoAmI 即使不是最终的,它们也不会在 OPs 示例中进行修改。但是,如果需要这样的微优化(实例大小可能从 24 字节下降到 16 字节),我们现在还需要更多信息。我非常怀疑——您至少需要 10-1 亿个位置实例才能有所作为。几乎不可能。

标签: java memory optimization


【解决方案1】:

答案取决于您创建的实例数量以及nodeIDdiskPos 值的分布。让我们看看这些数字,假设是 32 位 JVM(或 64 位,带有指针压缩)。这些值可能仍然与您的 JVM 实现不匹配,但它们对于 HotSpot 应该是正确的。

对于intlongLocation 实例占用 24 个字节。对于IntegerLong,这取决于。 Location 实例占用 16 个字节,IntegerLong 对象可能每个占用 16 个字节,除非它们是共享的。如果如您所说,其中一个大部分时间保持 -1(或null),则不占用内存,因此总共需要 16 或 32 个字节。是否共享 IntegerLong 实例取决于值和 JVM 设置。由于diskPos 需要很长,因此实例不太可能被缓存。

所以答案是:原始 = 24 字节,装箱很可能是 32 字节。保持原始状态。

如果您使用不同的类实现一个通用接口,您可以将每个实例的内存消耗降低到 16 个字节。我不会这样做是为了节省内存(在你注意到之前你需要数百万个实例),而是为了更易读的代码,因为对于字段 -1 之一,Location 实际上是一个联合类型,而你可能有这样的代码:

if (location.getNodeId() >= 0) {
    // do something with node id
} else {
    // do something with diskPos
}

更面向对象的设计可以让您将不同的行为合并到相应的类中。

【讨论】:

    猜你喜欢
    • 2015-08-17
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多