哪个函数更快(p是MyObject的atomic public int属性):

public static boolean check(MyObject o1, List<MyObject> list) {

    int p = o1.p;
    for (int i = 0; i < 1000000; i++) {
        MyObject o = list.get(i);
        if (o.p < p) return false;
    }

    return true;
}


要么

public static boolean check(MyObject o1, List<MyObject> list) {

    for (int i = 0; i < 1000000; i++) {
        MyObject o = list.get(i);
        if (o.p < o1.p) return false;
    }

    return true;
}


因此,通过使用局部变量p我们可以缓存对象属性调用,还是由编译器优化内联完成?

最佳答案

简短答案:这取决于

稍长一点的答案:这取决于编译器,VM和VM的设置。

背景:在服务器模式下使用HotSpot VM(最常见的风味)将使两个变体相同,因为VM确实在服务器模式下循环不变式提升。在客户端模式下,如果VM认为值得优化,则可以执行,不执行或什至以后执行。

Loop invariant hoisting是循环优化的一种,已在大多数现代编译器(或Java,VM)中实现。至于javac生成的代码:如果VM不做进一步优化,您的第一个代码段将表现得更快。

public static boolean check(Test$MyObject, java.util.List);
  Code:
   0:   aload_0
   1:   getfield        #7; //Field Test$MyObject.p:I
   4:   istore_2
   5:   iconst_0
   6:   istore_3
   7:   iload_3
   8:   ldc     #4; //int 1000000
   10:  if_icmpge       42
   13:  aload_1
   14:  iload_3
   15:  invokeinterface #11,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
   20:  checkcast       #5; //class Test$MyObject
   23:  astore  4
   25:  aload   4
   27:  getfield        #7; //Field Test$MyObject.p:I
   30:  iload_2
   31:  if_icmpge       36
   34:  iconst_0
   35:  ireturn
   36:  iinc    3, 1
   39:  goto    7
   42:  iconst_1
   43:  ireturn


-

public static boolean check(Test$MyObject, java.util.List);
  Code:
   0:   iconst_0
   1:   istore_2
   2:   iload_2
   3:   ldc     #4; //int 1000000
   5:   if_icmpge       38
   8:   aload_1
   9:   iload_2
   10:  invokeinterface #11,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
   15:  checkcast       #5; //class Test$MyObject
   18:  astore_3
   19:  aload_3
   20:  getfield        #7; //Field Test$MyObject.p:I
   23:  aload_0
   24:  getfield        #7; //Field Test$MyObject.p:I
   27:  if_icmpge       32
   30:  iconst_0
   31:  ireturn
   32:  iinc    2, 1
   35:  goto    2
   38:  iconst_1
   39:  ireturn


如您所见,第二个示例中第20行的getfield操作位于第一个示例中的第1行中,并且在循环之外(变量1中的第7至39行以及变量2中的第2至35行),因此仅执行而不是1000000次。

10-07 12:08
查看更多