Java JVM是否可以省略短期对象创建,这样我就可以在不影响性能的情况下进行重构?
有时,在算法过程中,我们需要计算或简单地存储几个相互依赖或彼此之间没有任何意义的值 作为一个(非常荒谬,但重要的是,很简单)示例,让我们在Java JVM是否可以省略短期对象创建,这样我就可以在不影响性能的情况下进行重构?,java,performance,jvm,refactoring,escape-analysis,Java,Performance,Jvm,Refactoring,Escape Analysis,有时,在算法过程中,我们需要计算或简单地存储几个相互依赖或彼此之间没有任何意义的值 作为一个(非常荒谬,但重要的是,很简单)示例,让我们在int[]中找到两个最接近数字3的不同值: int a = values[0]; int b = values[1]; for (int value : values) { int distance = Math.abs(value-3); if (value != b) { if (distance < Math.abs
int[]
中找到两个最接近数字3
的不同值:
int a = values[0];
int b = values[1];
for (int value : values) {
int distance = Math.abs(value-3);
if (value != b) {
if (distance < Math.abs(a-3) ) {
a = value;
}
}
if (value != a) {
if (distance < Math.abs(b-3) ) {
b = value;
}
}
}
takeSausageSliceBetween(a, b);
因此,更高级别的代码变得清晰明了:
DistinctNumbersNearestTo3 nearest = new DistinctNumbersNearestTo3(values);
takeSausageSliceBetween(nearest.a, nearest.b);
// nearest never leaves the method it was declared in
然而(如果我错了,请纠正我),它引入了一个新对象的实例化,然后垃圾收集(只是从eden开始,但无论如何),这只是为了让代码更清晰。在堆栈中查找int也会变成在堆中查找对象
这里的问题是:JVM是否足够聪明,能够最终优化重构后的代码,使其与未经分解的代码一样运行
另一种情况是,我想把几个变量组合到一个新对象中,只是为了更干净的代码,我想通过引入一个新类C
将一个长方法a()
重构成几个新方法,该类保存a()的特定数据
的调用,因此包含对该数据进行操作的几个新方法。我在实现一个类时偶然发现了这种情况,该类表示一组链,我们可以向其中添加新链接(节点对),从而扩展现有链,将两条链合并为一条链,或者创建两个节点的新链。让我们从一些角度来讨论这个特定的类:
public class SetOfChains {
List<List<Node>> chains;
public void addLink(Node a, Node b) {
// Very long method that mutates field this.chains. Needs refactoring.
}
}
但是,从功能上讲,这相当于让我的旧长的未分解的addLink()
,JVM能使生成的指令像未分解的情况一样优化吗,就好像没有任何LinkAddition
对象一样
那么,在这堵文本墙下画一条底线:如果我通过将数据和方法提取到新类而不是方法来努力实现易于理解的代码,那么这是否必然会导致性能下降
我是否正确地理解了所描述的案例正是关于什么的?有人说“过早优化是万恶之源”
一般来说,最好是让代码更容易理解,并且在检测到性能瓶颈时,只会使代码更复杂、更难理解
大多数Java代码都会创建大量短期对象,这些对象很快就变得不可访问。因此,我认为热点垃圾收集器是“分代”的,这意味着它将堆划分为两个独立的区域:年轻一代和老一代
- 年轻一代-包含大多数新创建的对象,并且预期寿命很短。这个地区的垃圾收集效率很高
- 老一代-寿命更长的对象最终从年轻一代“提升”到老一代。这个地区的垃圾收集费用更高
因此,总结一下,让代码变得更容易理解和维护,从而生成许多短期对象。你不应该看到太多的性能下降。配置它以查看实际性能。如果性能不符合您的要求,您还可以重构瓶颈以加快速度。我想您应该在第一句中引用Knuth。然而,实际引用说,过早优化是万恶之源,因此通常不会谴责优化。我同意你回答的其他部分。是的,你是对的,我知道是Knuth,我应该在引文中加上“不成熟”。我会更新的,谢谢
public class SetOfChains {
List<List<Node>> chains;
public void addLink(Node a, Node b) {
// Very long method that mutates field this.chains. Needs refactoring.
}
}
class SetOfChains{
List<List<Node>> chains;
void addLink(Node a, Node b) {
new LinkAddition(a,b).compute();
}
class LinkAddiditon { // Instances never leave addLink()'s scope
private final Something bunch, of, common, fields;
compute() {
this.properly();
this.isolated();
this.steps();
this.of();
this.the();
this.refactored();
this.method();
}
// There be code for the properly isolated steps...
}