【问题标题】:Memory required for 'short' fields in Dalvik?Dalvik中的“短”字段需要内存吗?
【发布时间】:2012-10-25 14:04:59
【问题描述】:

Java 虚拟机也可以为short 字段使用int 大小的宽度(这取决于它们的内部实现)。只有数组 (short[]) 是例外,始终保证它们在内部占用的空间也比 int[] 少)。 Dalvik 呢?

例如我有一个包含 50 个 short 类型字段的类。有时在我的应用程序中,存在 10000 个此类。这意味着short 字段应该使用 1MB 的内存,但 如果 Dalvik 在内部使用 4 字节的 short 值,那么这将是 2MB 的内存使用。

我应该期望 Dalvik 使用多少内存? (这是指它的内部内存使用,我知道它可能不会反映在系统内存使用中,例如因为 Dalvik 已经从系统中保留了更多的内存。)

【问题讨论】:

  • 致为我的帖子准备(格式)编辑的用户:谢谢。不幸的是,系统没有让我接受它,它说“编辑已被拒绝”。据我所知,我尝试自己应用您的编辑。
  • “Java 虚拟机也以对短字段使用 int 大小的宽度而闻名”你能用任何参考来支持这个陈述吗?
  • @Nambari:它没有。它只是引用了 Java 规范。事实上,对于任何应用程序代码,'short' 保证 appearact 作为 2 个字节。我想知道 Dalvik 的内部实现,以及我是否使用 10000 个具有 50 个短字段的类,或者我在每个类中都使用一个 short[] 是否会影响内存使用。跨度>
  • @JesusFreke:是的,在其中一个链接的主题中,OP 也进行了测试,表明他仅在 short[] 的情况下保存内存,而不是在个人 @987654329 的情况下@字段。正如 pst 上面指出的,Dalvik 的工作方式可能有所不同。在几个方面,Dalvik 的工作方式确实与 JVM 不同(因为它是针对移动设备优化的)。在这种情况下,可以合理地假设它以与 JVM 相同的方式处理 short[](如果 short[] 使用更多内存,由于各种原因,这是不可接受的)。我的问题正好相反:Dalvik 如何在内部存储 individual short 字段?
  • @pst 和 Thomas Calc:问题 8855754 专门针对 Android。您可能已经注意到标准 JVM 不能在 Android 上运行。因此,假设他在 dalvik 上进行了测试(可能)是安全的 :)

标签: java android dalvik


【解决方案1】:

在 dalvik 中,double 和 long 字段是 8 个字节,其他所有字段(包括 short)都是 4 个字节。

另一方面,短数组每个元素占用 2 个字节(除了数组+对象簿记的前期空间)。

数组

new-array 操作码调用dvmAllocArrayByClass(第 71 行)来分配空间。然后调用dvmAllocPrimitiveArray(第 113 行)。在dvmAllocPrimitiveArray 的开关中,“S”大小写用于短数组。您可以看到它调用 allocArray(第 38 行),宽度为 2。

allocArray内,它会做如下计算来计算数组的大小:

size_t elementShift = sizeof(size_t) * CHAR_BIT - 1 - CLZ(elemWidth);
size_t elementSize = length << elementShift;
size_t headerSize = OFFSETOF_MEMBER(ArrayObject, contents);
size_t totalSize = elementSize + headerSize;

简而言之,在 32 位系统上,此计算为:

size_t elementShift = (4 * 8) - 1 - 30; //== 1;
size_t elementSize = length << 1; //i.e. length * 2
size_t headerSize = <some constant value>;
size_t totalSize = length*2 + <some constant value>;

短数组每个元素占用 2 个字节。

字段

new-instance 操作码调用dvmAllocObject(第 181 行)为新对象分配空间。分配的大小基于ClassObjectobjectSize 字段。 objectSize 设置在 computeFieldOffsets(第 3543 行)中。如果您在此函数中找到每个 fieldOffset 递增的实例,您会注意到它始终以 4 个字节为增量递增。

短字段占用 4 个字节。

【讨论】:

  • 这正是我正在寻找的分析答案类型。谢谢!
【解决方案2】:

(应该是一个评论,但它太长了。)

将 4 字节字段用于“短”本地变量是相当常规的,因为 JVM 在概念上是具有 4 字节寄存器的机器,并且所有其他垃圾都在堆栈帧中,它不会产生太多区别。

例如字段,它可能取决于在节省存储空间与必须在扩展和对齐上花费周期之间的权衡 - 扩展通常会花费一个较小的周期,即使在所谓的边界对齐方面“不可知”的架构上也存在通常是对越界访问的惩罚,因此“打包”字段而不首先重新排列它们以保持字/双字边界可能会降低性能。

因此,如果 JVM 选择“打包”字段,则通常需要重新排列。幼稚的 JVM 将避免重新排列,因为这使得 JVM 的几个方面更简单,但是(作为一个示例)在 AS/400 上,我们发现积极地重新排序和打包实例字段对于需要存储的应用程序的性能提高了 30%。

我从未看过 Dalvik 的内脏。标准 Sun 派生的 JVM 在历史上(没有查看最近的任何内容)依赖于 .class 文件中事物的布局/顺序,因此不能“自然地”重新排序。但是 Dalvik 重新构建了 .class 文件,因此可以更好地进行实例字段重新排序。

请注意,要测试 Dalvik 打包 short 字段的假设,您必须创建一个具有多个实例字段背靠背的类,然后确定生成的对象大小。另外(假设在第一种情况下看到打包),创建一个交错的shortint(或者可能long)字段的类,以查看Dalvik 是否对它们重新排序以实现打包。

【讨论】:

    猜你喜欢
    • 2011-06-03
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多