创建对象和委派比一个大方法慢得多



这个问题与内存和主要性能有关。最近几天我在思考这个话题,它不是我需要使用的东西,只是好奇。我创建了一个简单的例子:

1) 一个不使用委托并且没有内部类的类:

public class NoInnerClass {
public void theMethod(int times){
for(int i=0; i<times; i++){
System.out.println("No Inner hello: " + i);
}
}
}

2) 一个调用四个内部类的类。最后一个与方法中的NoInnerClass相同

public class InnerMain {
private Inner1 inner1 = new Inner1();
public void theMethod(int times){
inner1.doIt(times);
}
}

public class Inner4 {
public void theMethod(int times){
for(int i=0; i<times; i++){
System.out.println("Inner 4 hello: " + i);
}
}
}

我测量了这两种类型的调用之间的时间差(以毫秒为单位)。差异并没有那么大——一毫秒多一点。但是,如果我们有更复杂的内部对象和更多的委托调用,我们肯定会有更大的差异。

所以问题是:

  • 两种方法在使用时间和内存量方面的差异会显著增加吗
  • 如果有,有关于这方面的文章吗(我找不到太多)
  • 也许今天的JVM太聪明了,我们不应该去想它

提前感谢您的回答。

您发现的差异(一毫秒多一点)在很大程度上可能是您的基准测试技术的产物。此外,在不知道整个运行的时间的情况下谈论一毫秒是没有意义的:如果时间以数百毫秒为单位,那么差异很小;如果时间本身以个位数毫秒为单位,则差异显著;如果时间以秒为单位,则差值为测量误差。

现代JVM将虚拟调用优化到这样的效率水平,您所能看到的任何差异都很难衡量。最好集中精力使用所有可用的编码技术(包括虚拟调用)使代码尽可能清晰,并仅在探查器告诉有必要时才开始优化。

对于绝大多数程序来说,差异可以忽略不计。是的,一个方法调用可能需要几十个cpu周期,但对于大多数方法来说,这远远少于被调用的方法。在你的情况下,你在做I/O。即使它只是一个控制台,重新绘制该控制台也要比调用一个方法昂贵得多。

此外,JVM非常擅长内联方法调用,这进一步减少了方法调用开销(只为可重写方法留下类型检查)。

我建议在您的代码中有实际性能问题的证据之前,不要担心语言结构的性能。

附言:4个方法调用的毫秒是不合理的。它可能是您基准测试方法的产物。(计时器有多准确?你确定基准线程没有被加速以将CPU分配给另一个程序吗?你是在暂停垃圾收集吗?即时编译器运行了吗?)

哦,关于内存:区别在于堆上有4个对象。当然,这取决于这些对象是什么(如果每个对象都引用一个巨大的数组,那可能很重要),但小对象占用大约16字节的内存。你肯定能腾出4*16=64字节的内存吗?还是您在询问增加的堆栈大小?这也是微不足道的。

最新更新