【问题标题】:Do private functions use more or less computer resources than public ones?私人职能比公共职能使用更多还是更少的计算机资源?
【发布时间】:2016-03-02 23:28:52
【问题描述】:

计算机资源是 RAM、电源和磁盘空间。我只是好奇,尽管它或多或少只是很小的一部分。

【问题讨论】:

  • 您怀疑其中一个与另一个不同的背后的逻辑是什么?

标签: java private public


【解决方案1】:

私有函数比公共函数使用更多还是更少的计算机资源?

没有。无论单个字段或方法上的访问修饰符如何,JVM 都使用相同的资源。

但是,除了资源利用率之外,还有一个更好的理由更喜欢private(或protected);即encapsulation。另外,我强烈建议您阅读The Developer Insight Series: Part 1 - Write Dumb Code

【讨论】:

    【解决方案2】:

    理论上,在某些情况下,它可能头发更快。在实践中,它们同样快。

    使用invokevirtual 字节码操作调用非静态、非公共方法。此操作码要求 JVM 动态查找实际的方法解析:如果您有一个静态编译为 AbstractList::contains 的调用,应该解析为 ArrayList::contains 还是 LinkedList::contains 等?更重要的是,编译器不能只在下一次重用这次编译的结果;如果下次调用myList.contains(val) 时,它是在不同的实现上怎么办?因此,编译器必须对非私有方法进行至少一些量的检查,大致是每次调用。

    私有方法不能被覆盖,它们是使用invokespecial 调用的。此操作码用于各种方法调用,您只需解析一次,然后永远不会更改:构造函数、对超级方法的调用等。例如,如果我在 ArrayList::add 并且我调用 super.add(value)(其中那里不会发生,但让我们假装发生了),那么编译器就可以确定 this 指的是AbstractList::add,因为类的超类永远不会改变。

    所以,粗略地说,invokevirtual 调用需要解析方法然后调用它,而invokespecial 调用不需要解析方法(在第一次调用之后 - 你必须解析至少一次!)。

    这在JVM spec, section 5.4.3:

    解决了一次调用动态指令的符号引用并不暗示任何其他调用动态指令都认为相同的符号引用已解决。

    对于上述所有其他指令,解决一次出现的指令的符号引用确实意味着对于任何其他非动态调用指令都认为相同的符号引用已解决。

    (原文强调)

    好的,现在是“但您不会注意到差异”部分。 JVM 针对虚拟调用进行了大量优化。它可以做一些事情,比如检测某个站点总是专门看到ArrayList,因此“静态化”List::add 调用实际上是ArrayList::add。为此,它需要验证传入的对象确实是预期的ArrayList,但这很便宜;如果一些较早的方法调用已经在此方法中完成了该工作,则不需要再次发生。这称为单态调用站点:尽管代码在技术上是多态的,但实际上列表只有一种形式。

    JVM 优化了单态调用点,甚至是双态调用点(例如,列表总是ArrayListLinkedList,从来没有其他任何东西)。一旦它看到三种形式,它必须使用一个完整的多态调度,这比较慢。但是话又说回来,此时您正在将苹果与橙子进行比较:非私有的多态调用与根据定义单态的私有调用。比较两种单态调用(虚拟调用和私有调用)更公平,在这种情况下,您可能会发现差异微乎其微,即使可以检测到。

    我刚刚做了a quick JMH benchmark 来比较 (a) 直接访问字段,(b) 通过公共 getter 访问它和 (c) 通过私有 getter 访问它。这三个人都花费了相同的时间。当然,超微基准测试很难做到正确,因为 JIT 可以通过优化完成如此美妙的事情。再说一遍,这就是要点:JIT 通过优化完成了如此美妙的事情,以至于公共和私有方法都一样快。

    【讨论】:

      【解决方案3】:

      我只是好奇,尽管它或多或少只是一点点。

      虽然好奇是件好事......如果你在编程时开始考虑这种事情,那么:

      • 您可能会浪费大量时间寻找不需要的微优化,

      • 您的代码可能无法维护,因为您牺牲了良好的设计原则,并且

      • 您甚至可能使您的代码效率低于未优化时的效率*


      * - 可以这样。 1)您花费大量时间调整代码以在测试平台上快速运行。 2)当你在生产平台上运行时,你会发现硬件给了你不同的性能特征。 3) 您升级了 Java 安装,新的 JVM 的 JIT 编译器以不同的方式优化您的代码,或者它有一堆被您的调整禁止的新优化。 4) 当您在实际工作负载上运行代码时,您会发现作为调整基础的假设是无效的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-31
        • 1970-01-01
        • 1970-01-01
        • 2020-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多