6

在我问我的问题之前,我可以请求不要无缘无故地接受关于优化的讲座。考虑以下纯学术问题。

我一直在考虑 Java 中根类(即经常使用并经常相互访问)之间的访问效率,但这适用于大多数 OO 语言/编译器。您可以在 Java 中访问某些内容的最快方式(我猜)将是静态最终引用。从理论上讲,由于该引用在加载期间可用,因此一个好的 JIT 编译器将无需进行任何引用查找来访问该变量,并将对该变量的任何访问直接指向一个常量地址。也许出于安全原因,它无论如何都不会那样工作,但请耐心等待......

假设我已经决定在启动时存在一些操作顺序问题或一些参数要传递,这意味着我不能拥有静态最终引用,即使我要麻烦让每个类按原样构造另一个建议让 Java 类彼此具有静态最终引用。我可能不想这样做的另一个原因是……哦,比如说,我正在提供其中一些类的特定于平台的实现。;-)

现在我有两个明显的选择。我可以通过静态引用(在某个系统集线器类上)让我的类相互了解,该引用是在构造所有类之后设置的(在此期间我要求它们还不能相互访问,从而消除了操作顺序问题施工期间最少)。另一方面,如果我现在决定整理操作顺序很重要,或者可以让传递参数的人负责 - 或者更确切地说,提供我们希望这些类的平台特定实现相互引用。

静态变量意味着您不必在变量 wrt 所属的类中查找变量的位置,从而节省了一次操作。final 变量意味着您根本不必查找该值,但它必须属于您的类,因此您保存“一个操作”。好的,我知道我现在真的在挥手!

然后我想到了其他事情:我可以拥有静态的最终存根类,有点像一个古怪的接口,其中每个调用都被降级为可以扩展存根的“impl”。那么性能损失将是运行函数所需的双重函数调用,并且可能我猜你不能再将你的方法声明为final 了。我假设如果它们被适当地声明,也许它们可以被内联,然后放弃,因为我意识到我将不得不考虑是否可以将'impl's的引用设为静态,或最终,或......

那么这三个中哪一个会最快呢?:-)

关于降低频繁访问开销或什至其他暗示 JIT 编译器性能的方法的其他想法?

更新:在对各种事物进行了几个小时的测试并阅读http://www.ibm.com/developerworks/java/library/j-jtp02225.html之后,我发现您在调整时通常会看到的大多数东西,例如 C++使用 JIT 编译器完全退出窗口。我已经看到它运行了 30 秒的计算一次、两次,并且在第三次(以及随后的)运行中决定“嘿,你没有读取该计算的结果,所以我没有运行它!”。

FWIW,您可以测试数据结构,并且我能够使用微基准测试开发出更符合我需求的数组列表实现。访问模式必须足够随机以使编译器猜测,但它仍然解决了如何使用我更简单和更优化的代码更好地实现泛型化的增长数组。

就这里的测试而言,我根本无法获得基准测试结果!我对调用函数并从最终与非最终对象引用中读取变量的简单测试揭示了更多关于 JIT 的信息,而不是 JVM 的访问模式。令人难以置信的是,在方法的不同位置对同一个对象调用同一个函数会改变四倍的时间!

正如 IBM 文章中的那个人所说,测试优化的唯一方法是现场测试。

感谢一路上给我指点的每一个人。

4

3 回答 3

1

值得注意的是,静态字段存储在一个特殊的每类对象中,该对象包含该类的静态字段。使用静态字段而不是对象字段不太可能更快。

于 2011-03-04T13:03:48.317 回答
1

查看更新,我通过做一些基准测试回答了我自己的问题,发现在意想不到的领域有更大的收益,并且在大多数现代系统上,像引用成员这样的简单操作的性能是相当的,因为内存带宽比 CPU 对性能的限制更多循环。

于 2011-06-22T12:01:59.053 回答
0

假设您找到了一种可靠地分析您的应用程序的方法,请记住,如果您切换到另一个 jdk impl(IBM 到 Sun 到 OpenJDK 等),甚至升级现有 JVM 的版本,它都会消失。

您遇到问题的原因,并且可能会因不同的 JVM 实现而产生不同的结果,原因在于 Java 规范 - 明确指出它没有定义优化并将其留给每个实现以任何方式优化(或不优化),只要优化不会改变执行行为。

于 2011-04-14T01:44:41.897 回答