成员订单是否会像在C或C++中那样在Java中产生性能差异?

Dan*_*lme 7 java optimization bytecode

在C和C++中,不允许编译器重新排序结构的数据成员,因此如果您不小心订购它们,最终会浪费空间.例如:

struct S {
    int i;
    void *p;
    int i2;
};
Run Code Online (Sandbox Code Playgroud)

在具有32位int和64位指针的平台上,i将首先放置,然后是32位填充,以便p可以进行64位对齐.i2然后占用下一个字的一半,接着是另外32位的填充.生成的结构长度为24个字节,而如果p首先声明,则只有16个字节长.如果在阵列中有很多这些结构,找到并删除填充有时可能是一个重要的优化,以节省内存并减少缓存流失.

我很想知道Java是否具有相同的功能.未装箱的类型(例如intboolean)是否与引用相同或更小?如果它们更小,是否允许编译器对它们重新排序以避免插入填充以对齐后续字段?最后,如果是,那么任何编译器都这样做吗?

我现在对此没有特别的优化需求,我只是很想知道在选择声明我的字段的顺序时是否应该记住这一点,就像我在C中所做的那样.

Pet*_*rey 4

int类型始终是 32 位,引用通常也是 32 位,即使在 64 位 JVM 中也是如此。

不利的一面是,Java 在每个对象的开头都有一个 8-12 字节的标头,并使用 8 字节对齐。顺便说一句,某些 C++ 环境具有 16 字节对齐方式。

未装箱的类型(例如 int 和 boolean)是否与引用的大小相同或更小?

您可以预期布尔型、字节型、字符型和短型的它们会更小,但长型和双精度型的原语可能会比引用更大。

如果它们较小,是否允许编译器对它们重新排序以避免插入填充来对齐后续字段?

JIT 可以重新组织字段,甚至优化它们。

最后,如果是的话,有编译器这样做吗?

编译javac几乎没有进行任何优化,并且查看字节码将为您提供关于运行时会发生什么的线索。JIT 可以以它选择的任何方式优化对象中的字段。

我只是想知道在选择声明字段的顺序时是否应该记住这一点,就像我在 C 中所做的那样。

恕我直言,您可以假设您在 C 中使用的几乎所有优化技巧都不再适用于 Java。在少数这样做的人中,它们可能并不完全相同。

您应该假设 JIT 将根据需要优化代码,并使用分析器来确定是否以及何时出现问题。然后才考虑出于性能原因更改代码。