【问题标题】:Enum vs. Static Constants, memory footprint枚举与静态常量,内存占用
【发布时间】:2014-08-14 10:12:33
【问题描述】:

首先请参阅 Android 开发人员指南中的以下引用:

尽管第一个要点中有不祥的警告,即“严格避免在 Android 上使用枚举”,但在那一点下所说的实际上并没有那么糟糕。常量是 32 位整数,而枚举可能是 64 位引用。那里给出的关于枚举昂贵两倍的数学是有道理的,而且看起来并不那么可怕。

我担心该警告可能部分基于第二个要点。

我想知道一个简单的枚举“类”声明是否带有 500 字节的开销? eacn 枚举类型呢?

类型可以是“扩展类”似乎很合理,因为它们可以采用自己的方法,而不仅仅是实例。将其表述为一个问题,如果我的枚举是 Color,并且我有 20 种 Color 枚举类型(例如红色、蓝色、绿色......),那么每种类型是 500 字节吗?

【问题讨论】:

  • 它不应该有明显的区别,除非你创建了数千个枚举类
  • @injecteer 事实并非如此。小事加起来最终会产生很大的不同,请观看这​​个关于 Android 开发者的精彩教程:youtube.com/…

标签: java android enums


【解决方案1】:

枚举在 Android 世界中是一场持续不断的无限辩论。

您可以在这里听到 Romain Guy 和 Chet Haase 的精彩演讲:http://www.parleys.com/play/5298f999e4b039ad2298c9e3/chapter57/about

根据该视频,Dalvik 中的对象有多大可以计算为:

overhead of Object + overhead of dlmalloc + data + align
  • Object 的开销正好是 8 个字节。
  • dlmalloc 的开销可以是 4 - 8 个字节(大多数时候是 8 字节)
  • 数据的大小取决于数据(当然)
  • 最后一切都必须是 8 字节对齐的(例如,如果你有 12 字节 对于一个对象,这将占用 16 个字节)

请记住,枚举的每个值实际上都是枚举类的一个实例。

另一个需要牢记的重点是 dex 文件的大小。 例如,以下枚举将占用大约 1,112 个字节

public static enum Things {
    THING_1,
    THING_2;
};

或者您可以有两个静态 int,占用 128 个字节。

public static int THING_1 = 1;
public static int THING_2 = 2;

您的 dex 文件大小提高了 10 倍。

生成多少已编译的 dalvik 代码也有很大不同。 对于 Enum,编译器为您做了很多事情。第一次在运行时加载类时会进行静态类初始化。它在启动时增加了加班时间。

另一方面,枚举也带来了很多优点:可读性、可用性、类型安全的代码。 我只会在特定的极端情况下担心枚举。

特别是当我们认为使用 ProGuard 可以优化 Enum 将它们转换为普通的 int 常量时。

【讨论】:

  • 请解释1112字节和128的数字来自哪里。然后不适合任何东西。
  • +1 不错的链接。 1,112 与 128 来自反编译字节码。不过,他们没有分解任何关于类与每种类型成本的指标。
  • @NameSpace,即dex文件的大小。这在运行时的内存中没有太多共同点,但在 .apk 大小方面。
  • dex文件的大小确实对运行时内存使用有影响,因为它是在运行时加载到内存中的。
【解决方案2】:

您错过了阅读该消息。

你引用

Every class in Java (including anonymous inner classes) uses about 500 bytes of code.

请参阅您需要将类定义存储在某个位置,这需要 500 个字节。

这意味着enum Const {}class Const{} 之间没有区别。

更重要的是创建实例时对象消耗了多少内存。

Every class instance has 12-16 bytes of RAM overhead. - 下一行表单源。

总结一下。只有在相同的长容器(枚举或类)中声明它们时,才能以 int 值的形式受益。

实际上 enum 也是一个扩展 Enum<?> 类型的类,它的一个实例比静态 int 常量需要更多的内存。

您在这里交易的是内存消耗和类型安全代码。当您使用 int 作为常量时,您无法保证类型安全。

public void doAction(int what) {}

public void doAction(What what) {}

在现代设备上,您可以编写消耗更多内存的代码。但是对于您的代码的某些方面可能更容易使用 int 对于其他枚举是正确的选择。这在代码量很大的 android R 包上尤其明显。

在这种情况下,您应该将 int 用于小型域字段 enum 更安全。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-01-14
  • 2014-06-01
  • 1970-01-01
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
相关资源
最近更新 更多