【发布时间】:2011-07-08 19:14:42
【问题描述】:
在我提出问题之前,请请不要无缘无故地接受关于优化的讲座。 考虑以下纯学术问题。
我一直在考虑 Java 中根(即经常使用和经常相互访问)类之间的访问效率,但这适用于大多数 OO 语言/编译器。您可以在 Java 中访问某些内容的最快方式(我猜)将是静态最终引用。从理论上讲,由于该引用在加载期间可用,因此一个好的 JIT 编译器将无需进行任何引用查找来访问该变量,并将对该变量的任何访问直接指向一个常量地址。也许出于安全原因,它无论如何都不会那样工作,但请耐心等待......
假设我已经决定在启动时存在一些操作顺序问题或一些参数要传递,这意味着我不能有静态最终引用,即使我要费心让每个类都构造其他建议让 Java 类对彼此具有静态最终引用。我可能不想这样做的另一个原因是……哦,比如说,我正在提供其中一些类的特定于平台的实现。 ;-)
现在我有两个明显的选择。我可以通过静态引用(在某个系统集线器类上)让我的类相互了解,该引用是在构造所有类之后设置的(在此期间我要求它们还不能相互访问,从而消除了操作顺序问题施工期间最少)。另一方面,类可以有 instance 最终相互引用,如果我现在决定整理操作顺序很重要,或者可以由传递参数的人负责 -或者更重要的是,提供我们希望相互引用的这些类的特定于平台的实现。
静态变量意味着您不必在其所属的类中查找变量 wrt 的位置,从而节省了一次操作。 final 变量意味着您根本不必查找该值,但它必须属于您的类,因此您保存“一个操作”。好的,我知道我现在真的在挥手!
然后我想到了其他事情:我可以有静态的最终存根类,有点像一个古怪的接口,其中每个调用都被降级为可以扩展存根的“impl”。那么性能损失将是运行函数所需的双重函数调用,并且可能我猜你不能再声明你的 methods final 了。我假设如果它们被适当地声明,也许它们可以被内联,然后放弃,因为我意识到我将不得不考虑是否可以将'impl's的引用设为静态,或最终,或......
那么这三个中哪一个会最快呢? :-)
关于降低频繁访问开销或什至以其他方式提示 JIT 编译器性能的其他想法?
更新:在对各种事物进行了几个小时的测试并阅读 http://www.ibm.com/developerworks/java/library/j-jtp02225.html 之后,我发现您在调整时通常会看到的大多数事物,例如C++ 使用 JIT 编译器完全消失了。我已经看到它运行了 30 秒的计算一次、两次,并且在第三次(以及随后的)运行中决定“嘿,你没有读取该计算的结果,所以我没有运行它!”。
FWIW,您可以测试数据结构,并且我能够使用微基准测试开发出性能更高的数组列表实现,以满足我的需求。访问模式一定是随机的,足以让编译器猜测,但它仍然解决了如何用我更简单、更优化的代码更好地实现泛型化的增长数组。
就这里的测试而言,我根本无法获得基准测试结果!我对调用函数并从最终与非最终对象引用中读取变量的简单测试揭示了更多关于 JIT 的信息,而不是 JVM 的访问模式。令人难以置信的是,在方法的不同位置调用 same 对象上的 same 函数会改变 FOUR 因子所花费的时间!
正如 IBM 文章中的人所说,测试优化的唯一方法是现场测试。
感谢一路上给我指点的每一个人。
【问题讨论】:
-
编写您自己的微基准测试,使用“How do I write a corrrect microbenchmark in Java?”的答案作为指导。
标签: java performance static final initializer