Java超级调优,几个问题

时间:2011-03-04 12:33:24

标签: java performance static final initializer

在我提出问题之前,我要求不要无缘无故地进行优化讲座。 考虑以下问题纯粹是学术性的。

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

假设我已经确定在启动时有一些操作顺序或一些参数传递,这意味着我不能有一个静态的最终引用,即使我要解决每个类构建的问题建议其他方法使Java类相互具有静态最终引用。我可能不想这样做的另一个原因是......哦,比方说,例如,我提供了其中一些类的平台特定实现。 ; - )

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

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

然后我发生了其他事情:我可能有静态的最终存根类,有点像古怪的界面,每个调用都被降级为'impl',只能扩展存根。然后,性能命中将是运行函数所需的双函数调用,并且可能我猜你不能再声明你的方法 final。我假设如果它们被恰当地宣布可能会被内联,然后放弃,因为我意识到我将不得不考虑对'impl'的引用是否可以是静态的,或最终的,或者......

那三个中的哪一个会变得最快? : - )

有关降低频繁访问开销甚至其他提示JIT编译器性能的方法的其他想法吗?

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

FWIW你可以测试数据结构,我能够开发一个arylylist实现,使用microbenchmark更能满足我的需求。访问模式必须足够随机以保持编译器的猜测,但它仍然可以解决如何使用更简单和更多调优的代码更好地实现通用的增长数组。

就这里的测试而言,我根本无法获得基准测试结果!我调用函数和从最终对象和非最终对象引用中读取变量的简单测试揭示了JIT比JVM的访问模式更多。令人难以置信的是,在方法中不同位置的相同对象上调用相同的函数会改变因子 FOUR 所花费的时间!

正如IBM文章中的人所说,测试优化的唯一方法就是原位。

感谢所有在路上指点我的人。

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

你遇到麻烦的原因,并且可能在不同的JVM impl中有不同的结果在于Java规范 - 明确指出它没有定义优化并将它留给每个实现来以任何方式优化(或不优化)只要优化没有改变执行行为。

答案 2 :(得分:0)

请参阅更新,我通过做一些基准测试来回答我自己的问题,并发现在意外的领域有更大的收益,并且在大多数现代系统中,诸如引用成员之类的简单操作的性能可比较带宽比CPU周期。