过时的Java优化技巧

8 浏览
0 Comments

过时的Java优化技巧

有一些性能优化技巧已经被Java编译器和特别是Profile-guided optimization所淘汰。例如,这些由平台提供的优化可以大大(根据来源)减少虚拟函数调用的成本。虚拟机还能够进行方法内联、循环展开等等。

你遇到的其他性能优化技术还在使用中,但实际上已经被更现代的JVM中的优化机制所淘汰了吗?

0
0 Comments

过时的Java优化技巧

在Java中,对方法和方法参数使用final修饰符对性能没有任何帮助。在Java HotSpot wiki中,可以了解到HotSpot使用的优化技巧以及如何在Java代码中有效地使用它们。然而,这个链接似乎并没有排除final。它表示'final'是内联的一个提示。我认为即使在循环中调用其他方法并超出当前范围,final修饰符也可以确保编译器知道其值不会改变。在stackoverflow.com上有相关讨论。在方法(或类)上使用final对JIT提供的信息没有影响。然而,在方法参数上使用final可能会提供有用的优化提示(类似于声明为final的局部变量)。但是,使用final的原因是强制不可变性-这是一种设计时的特性,可以使代码更容易维护。任何优化效果都需要考虑两个问题:a)只有在实际存在性能问题时才需要担心,b)需要彻底测试以确保它真的有所改变。

实际上,对参数使用final通常不会有任何影响(编译器确实可以看到您是否对其进行赋值,但Java不会通过引用传递变量-对象通过引用传递,但持有它们的变量不会)。但是,它确实意味着参数可以与内部类或匿名类一起使用。如果有意义的话可以使用,否则不要使用。

我使用final来确保类的不可变性,通常是作为私有final字段。我还使用它来确保不更改传递参数的值/引用。换句话说,我只是为了正确性而使用它,而不是为了优化。

我不使用final在方法参数或方法变量上进行优化,我使用它作为编码实践,以便其他开发人员可以看到这个值确实不会改变。任何优化都是次要的。

0
0 Comments

问题的出现的原因:

问题的出现是因为在早期开发阶段进行性能优化是不必要的,而且可能会导致额外的复杂性和困扰。因此,需要在开始性能优化之前明确定义时间/内存的权衡。

解决方法:

1. 不要在开发的早期阶段进行性能优化,除非真正需要。如果决定进行性能优化,可以采取以下步骤:

2. 使用性能分析工具查找瓶颈,并检查源代码以找到瓶颈的原因;

3. 选择适当的数据结构,以最好地适应已定义的时间/内存权衡;

4. 选择适当的算法(例如迭代与递归等);

5. 避免使用Java库中的同步对象,除非真正需要;

6. 避免显式/隐式创建新对象;

7. 如果确定Java自带的数据类型/算法不符合要求,可以进行重写/重新实现;

8. 使用小型、独立的测试来测试选择的算法/数据结构的性能。

此外,为了减轻第一条规则的影响,有一些易于编写和阅读的方法,任何合格的软件工程师都应该知道并正确地做到,比如在链表和数组列表之间进行选择。这是免费的,并且可以避免以后的麻烦。这就是良好的软件设计的本质。

0
0 Comments

过时的Java优化技巧

在Java编程中,有些人会将字符串连接操作String a = "this" + var1 + " is " + var2;替换为多次调用StringBuilder或StringBuffer。实际上,Java编译器已经在幕后使用了StringBuilder。

在这种情况下,我认为优化仍然适用。你展示的示例代码将构建3个不同的StringBuilder实例,每个连接操作都会构建一个实例;而只构建一个实例会更高效(稍微)。如果我错了,请纠正我。

哦,我以为它会等同于String a = new StringBuilder("this").append(var1).append("is").append(var2).toString();

这个不可靠的来源rgagnon.com/javadetails/java-0129.html表明Paul是正确的,只使用一个StringBuilder,但它说StringBuilder的默认容量可能太短(奇怪的是,如果编译器在使用StringBuffer之前计算容量是微不足道的)。

使用StringBuffer甚至会降低代码的速度,因为它涉及同步操作。在一个过度使用StringBuffer的应用程序中,我将所有出现的StringBuffer替换为StringBuilder,性能提高了10%。

当字符串连接操作在一行上完成时,使用StringBuilder没有任何作用。然而,将这个:String a = "this" + var1; a += " is " + var2;替换为StringBuilder仍然有效。(至少在我上次检查时是有效的:-)

我认为你是对的,因为将其拆分成多行将涉及创建大量不同的String对象。

在最后一天,“谁在乎这是否被优化?”(考虑到绝大多数使用场景。)

stackoverflow.com/questions/22241841/…是一个例子,将循环中的+=替换为单个StringBuilder显著影响了性能;在该例中,执行时间从35分钟减少到6分钟。

如果你在循环中进行了成千上万次的字符串连接操作,这确实是一种值得优化的方法,但是我回答中的示例不会节省你可测量的时间。

0