【问题标题】:Speed optimizing: private and public variables - Java速度优化:私有和公共变量 - Java
【发布时间】:2011-11-13 23:39:46
【问题描述】:

我问这个问题纯粹是为了问题的速度方面。

当对象是私有或公共 (Java) 时,从对象获取值的速度有何不同?

class MyClass {
    public int myInt = 5;
}
class MyOtherClass {
    private int myInt = 5;

    public int getMyInt() {
        return myInt;
    }
}
class MyMainClass {
    public static void main (String [] args) {
        MyClass myObject = new MyClass();
        MyOtherClass myOtherObject = new MyOtherClass();

        // which is faster?
        System.out.println(myObject.myInt);
        System.out.println(myOtherObject.getMyInt ());
    }
}

我知道我可以测试它,但如果有人已经知道它,它不会受到伤害:) 提前致谢!

【问题讨论】:

  • 应该对其进行测试。而且你不应该对它进行微基准测试,而是在一个实际上做了一些有用工作的大型程序上尝试它,让它运行一分钟,因为那是优化最重要的维度。每次您考虑进行微优化时都这样做,直到从您的思考过程中消除浪费的能量。
  • @delnan,我不确定你的意思。如果您的意思是在大型程序的上下文中,particular 优化可能会带来不可估量的好处,这在定义上是正确的。就普遍适用的理解哪种方式更好而言,特殊编码的测试不会提供信息吗?当然,您可能想要迭代很长时间,因为您不知道内存管理功能何时运行等。我认为不需要真正的程序来做真正的工作。
  • @broiyan:如果它仅对微基准测试有任何(相关)影响,那么实际解决问题的程序不会从中受益。如果它不能加快解决实际问题的速度,它会增加零价值,不值得担心。没有人关心它是否会让你的微基准测试运行得更快。如果有技术深度(例如,由于封装较少而导致设计更差),这将是三次。即使在执行大量其他操作的实际程序中,值得担心和实施的优化也会带来可衡量的好处(记住 80-20 规则!)。

标签: java performance variables


【解决方案1】:

公共和私人访问只不过是在编译时确定您是否有权访问变量。在运行时,它们完全相同。这意味着,如果您可以诱使 JVM 认为您可以访问(通过反射、不安全或修改字节码),那么您可以。公共和私有只是编译时间信息。这并不是说它不会存储在字节码中,因为它确实存在,但只有在某些东西试图针对它进行编译时才能引用它。

【讨论】:

  • 而且调用函数的麻烦一点都不重要?
  • @Hidde:在 JIT 启动后,它很容易内联该调用。即使不是这样,您也可以优化一百万种事物以获得更大的效果,而无需将设计变得更糟。
  • 其实在这种情况下,可能不会。它可能是由编译器内联的。对于一个不平凡的方法,是的,方法调用会导致小的性能损失,但是对于 getter 方法,您的方法不太可能超过几行。
  • 谢谢 :) 实际上我完全忘记了内联函数。
  • 只有当方法是final时,它才会被编译器内联,并且内联访问不会违反访问控制。否则,它必须等到运行时。
【解决方案2】:

字段上的访问修饰符对速度没有任何影响,但调用访问器方法会。

但是,差异并不大,并且由于 JIT 编译器优化,在重复调用后可能会减小。这取决于您的情况,但我还没有发现性能问题证明消除访问器是合理的情况。让良好的设计原则推动您的决策。

在这种情况下有助于提高性能的一个良好设计原则是禁止继承,除非您知道需要继承并已采取措施支持它。特别是,将类声明为final(或至少是访问器方法)将提供更快的方法分派,并且还可以作为 JITC 更积极地内联的提示。

保持访问器最终状态还允许编译器内联对访问器的调用。如果该字段是私有的,则可以内联从类中对访问器的调用(在良好的设计中,这些是最常见的情况),而包可访问字段可以在整个包中内联,等等。

【讨论】:

  • 大+1 为许多好的智慧珍珠。设计原则 > 性能(尤其是像这样的微优化)就是其中之一。将其设为 final 也是一个相当不错的想法,因为我认为在子类中重写直接访问器方法是不明智的,我没有理由不将其设为 final。
【解决方案3】:

据我所知,当您调用 getter 或任何只返回一些值而不返回其他任何值的函数时,此方法将被内联,因此方法调用和字段的直接访问之间没有任何区别.

【讨论】:

    【解决方案4】:

    您询问有关访问私有变量与公共变量的问题,但您的代码示例和对 Glowcoder 的评论暗示您实际上是在询问私有 字段 与公共 方法(或者,字段 vs. 方法...正如 gloomcoder 正确所说,公共 vs. 私有对性能没有影响)。

    许多现代编译器将优化对短方法的调用,使其等同于访问它们包装的字段(通过内联调用),但完全有可能给定的 Java 环境将执行函数调用(速度稍慢)调用该方法。

    生成内联代码还是函数调用取决于特定的编译器。由于不知道您正在使用哪个 Java 编译器(可能还有哪些编译器选项),因此无法确定。

    【讨论】:

      【解决方案5】:

      从性能的角度来看,如果有任何差异的话,差异是无限小的。编译器将几乎相同地优化此代码,并且一旦编译代码,JVM 将以完全相同的方式处理公共变量和私有变量(我不相信它甚至不知道公共和私有之间的区别 post-编译)。

      从实用的角度来看,很难想象有任何可能的场景值得打破传统的 Java 属性访问模式以提高性能。在 StackOverflow 上针对 C++ 的这个主题提出了类似的问题,答案与 Java 一样相关:

      Any performance reason to put attributes protected/private?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-25
        • 2011-12-03
        • 2012-01-25
        • 1970-01-01
        • 2014-08-21
        • 2012-09-03
        • 2011-05-25
        • 1970-01-01
        相关资源
        最近更新 更多